inspector cleanups

clustering work for datablocks for both consistent scanning for object parameters, as well as an eye towards orgainizing things to make reviewing what variations of components we'll be needing down the line clearer
This commit is contained in:
AzaezelX 2023-01-24 17:12:23 -06:00
parent 23895e365a
commit f07c8745b2
27 changed files with 692 additions and 700 deletions

View file

@ -295,21 +295,22 @@ bool DebrisData::preload(bool server, String &errorStr)
void DebrisData::initPersistFields() void DebrisData::initPersistFields()
{ {
addGroup("Display"); addGroup("Shapes");
addField("texture", TypeString, Offset(textureName, DebrisData), addField("texture", TypeString, Offset(textureName, DebrisData),
"@brief Texture imagemap to use for this debris object.\n\nNot used any more.\n", AbstractClassRep::FIELD_HideInInspectors); "@brief Texture imagemap to use for this debris object.\n\nNot used any more.\n", AbstractClassRep::FIELD_HideInInspectors);
INITPERSISTFIELD_SHAPEASSET(Shape, DebrisData, "Shape to use for this debris object."); INITPERSISTFIELD_SHAPEASSET(Shape, DebrisData, "Shape to use for this debris object.");
endGroup("Display"); endGroup("Shapes");
addGroup("Datablocks"); addGroup("Particle Effects");
addField("emitters", TYPEID< ParticleEmitterData >(), Offset(emitterList, DebrisData), DDC_NUM_EMITTERS, addField("emitters", TYPEID< ParticleEmitterData >(), Offset(emitterList, DebrisData), DDC_NUM_EMITTERS,
"@brief List of particle emitters to spawn along with this debris object.\n\nThese are optional. You could have Debris made up of only a shape.\n"); "@brief List of particle emitters to spawn along with this debris object.\n\nThese are optional. You could have Debris made up of only a shape.\n");
addGroup("Particle Effects");
addGroup("Datablocks");
addField("explosion", TYPEID< ExplosionData >(), Offset(explosion, DebrisData), addField("explosion", TYPEID< ExplosionData >(), Offset(explosion, DebrisData),
"@brief ExplosionData to spawn along with this debris object.\n\nThis is optional as not all Debris explode.\n"); "@brief ExplosionData to spawn along with this debris object.\n\nThis is optional as not all Debris explode.\n");
endGroup("Datablocks"); endGroup("Datablocks");
addGroup("Physical Properties"); addGroup("Physics");
addField("elasticity", TypeF32, Offset(elasticity, DebrisData), addField("elasticity", TypeF32, Offset(elasticity, DebrisData),
"@brief A floating-point value specifying how 'bouncy' this object is.\n\nMust be in the range of -10 to 10.\n"); "@brief A floating-point value specifying how 'bouncy' this object is.\n\nMust be in the range of -10 to 10.\n");
addField("friction", TypeF32, Offset(friction, DebrisData), addField("friction", TypeF32, Offset(friction, DebrisData),
@ -338,7 +339,7 @@ void DebrisData::initPersistFields()
"@brief Use mass calculations based on radius.\n\nAllows for the adjustment of elasticity and friction based on the Debris size.\n@see baseRadius\n"); "@brief Use mass calculations based on radius.\n\nAllows for the adjustment of elasticity and friction based on the Debris size.\n@see baseRadius\n");
addField("baseRadius", TypeF32, Offset(baseRadius, DebrisData), addField("baseRadius", TypeF32, Offset(baseRadius, DebrisData),
"@brief Radius at which the standard elasticity and friction apply.\n\nOnly used when useRaduisMass is true.\n@see useRadiusMass.\n"); "@brief Radius at which the standard elasticity and friction apply.\n\nOnly used when useRaduisMass is true.\n@see useRadiusMass.\n");
endGroup("Physical Properties"); endGroup("Physics");
addGroup("Behavior"); addGroup("Behavior");
addField("explodeOnMaxBounce", TypeBool, Offset(explodeOnMaxBounce, DebrisData), addField("explodeOnMaxBounce", TypeBool, Offset(explodeOnMaxBounce, DebrisData),

View file

@ -72,9 +72,9 @@ RenderShapeExample::~RenderShapeExample()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void RenderShapeExample::initPersistFields() void RenderShapeExample::initPersistFields()
{ {
addGroup( "Rendering" ); addGroup( "Shapes" );
INITPERSISTFIELD_SHAPEASSET(Shape, RenderShapeExample, "The path to the shape file.") INITPERSISTFIELD_SHAPEASSET(Shape, RenderShapeExample, "The path to the shape file.")
endGroup( "Rendering" ); endGroup( "Shapes" );
// SceneObject already handles exposing the transform // SceneObject already handles exposing the transform
Parent::initPersistFields(); Parent::initPersistFields();

View file

@ -387,17 +387,16 @@ ExplosionData* ExplosionData::cloneAndPerformSubstitutions(const SimObject* owne
void ExplosionData::initPersistFields() void ExplosionData::initPersistFields()
{ {
addGroup("Shapes");
INITPERSISTFIELD_SHAPEASSET(ExplosionShape, ExplosionData, "@brief Optional shape asset to place at the center of the explosion.\n\n" INITPERSISTFIELD_SHAPEASSET(ExplosionShape, ExplosionData, "@brief Optional shape asset to place at the center of the explosion.\n\n"
"The <i>ambient</i> animation of this model will be played automatically at the start of the explosion."); "The <i>ambient</i> animation of this model will be played automatically at the start of the explosion.");
endGroup("Shapes");
addField( "explosionScale", TypePoint3F, Offset(explosionScale, ExplosionData), addGroup("Sounds");
"\"X Y Z\" scale factor applied to the explosionShape model at the start "
"of the explosion." );
addField( "playSpeed", TypeF32, Offset(playSpeed, ExplosionData),
"Time scale at which to play the explosionShape <i>ambient</i> sequence." );
INITPERSISTFIELD_SOUNDASSET(Sound, ExplosionData, "Sound to play when this explosion explodes."); INITPERSISTFIELD_SOUNDASSET(Sound, ExplosionData, "Sound to play when this explosion explodes.");
endGroup("Sounds");
addGroup("Particle Effects");
addField( "faceViewer", TypeBool, Offset(faceViewer, ExplosionData), addField( "faceViewer", TypeBool, Offset(faceViewer, ExplosionData),
"Controls whether the visual effects of the explosion always face the camera." ); "Controls whether the visual effects of the explosion always face the camera." );
@ -420,7 +419,9 @@ void ExplosionData::initPersistFields()
"@brief List of additional ParticleEmitterData objects to spawn with this " "@brief List of additional ParticleEmitterData objects to spawn with this "
"explosion.\n\n" "explosion.\n\n"
"@see particleEmitter" ); "@see particleEmitter" );
endGroup("Particle Effects");
addGroup("Debris");
addField( "debris", TYPEID< DebrisData >(), Offset(debrisList, ExplosionData), EC_NUM_DEBRIS_TYPES, addField( "debris", TYPEID< DebrisData >(), Offset(debrisList, ExplosionData), EC_NUM_DEBRIS_TYPES,
"List of DebrisData objects to spawn with this explosion." ); "List of DebrisData objects to spawn with this explosion." );
addField( "debrisThetaMin", TypeF32, Offset(debrisThetaMin, ExplosionData), addField( "debrisThetaMin", TypeF32, Offset(debrisThetaMin, ExplosionData),
@ -439,10 +440,17 @@ void ExplosionData::initPersistFields()
"Velocity to toss debris at." ); "Velocity to toss debris at." );
addField( "debrisVelocityVariance", TypeF32, Offset(debrisVelocityVariance, ExplosionData), addField( "debrisVelocityVariance", TypeF32, Offset(debrisVelocityVariance, ExplosionData),
"Variance in the debris initial velocity (must be >= 0)." ); "Variance in the debris initial velocity (must be >= 0)." );
addField( "subExplosion", TYPEID< ExplosionData >(), Offset(explosionList, ExplosionData), EC_MAX_SUB_EXPLOSIONS, addField( "subExplosion", TYPEID< ExplosionData >(), Offset(explosionList, ExplosionData), EC_MAX_SUB_EXPLOSIONS,
"List of additional ExplosionData objects to create at the start of the " "List of additional ExplosionData objects to create at the start of the explosion." );
"explosion." ); endGroup("Debris");
addGroup("Animation");
addField("explosionScale", TypePoint3F, Offset(explosionScale, ExplosionData),
"\"X Y Z\" scale factor applied to the explosionShape model at the start "
"of the explosion.");
addField("playSpeed", TypeF32, Offset(playSpeed, ExplosionData),
"Time scale at which to play the explosionShape <i>ambient</i> sequence.");
addField( "delayMS", TypeS32, Offset(delayMS, ExplosionData), addField( "delayMS", TypeS32, Offset(delayMS, ExplosionData),
"Amount of time, in milliseconds, to delay the start of the explosion effect " "Amount of time, in milliseconds, to delay the start of the explosion effect "
@ -472,7 +480,9 @@ void ExplosionData::initPersistFields()
"The explosionShape (if defined) will be scaled using the times/sizes " "The explosionShape (if defined) will be scaled using the times/sizes "
"keyframes over the lifetime of the explosion.\n" "keyframes over the lifetime of the explosion.\n"
"@see lifetimeMS" ); "@see lifetimeMS" );
endGroup("Animation");
addGroup("Camera Shake");
addField( "shakeCamera", TypeBool, Offset(shakeCamera, ExplosionData), addField( "shakeCamera", TypeBool, Offset(shakeCamera, ExplosionData),
"Controls whether the camera shakes during this explosion." ); "Controls whether the camera shakes during this explosion." );
addField( "camShakeFreq", TypePoint3F, Offset(camShakeFreq, ExplosionData), addField( "camShakeFreq", TypePoint3F, Offset(camShakeFreq, ExplosionData),
@ -487,7 +497,9 @@ void ExplosionData::initPersistFields()
"center of the explosion to be shaken." ); "center of the explosion to be shaken." );
addField( "camShakeFalloff", TypeF32, Offset(camShakeFalloff, ExplosionData), addField( "camShakeFalloff", TypeF32, Offset(camShakeFalloff, ExplosionData),
"Falloff value for the camera shake." ); "Falloff value for the camera shake." );
endGroup("Camera Shake");
addGroup("Light Emitter");
addField( "lightStartRadius", TypeF32, Offset(lightStartRadius, ExplosionData), addField( "lightStartRadius", TypeF32, Offset(lightStartRadius, ExplosionData),
"@brief Initial radius of the PointLight created by this explosion.\n\n" "@brief Initial radius of the PointLight created by this explosion.\n\n"
"Radius is linearly interpolated from lightStartRadius to lightEndRadius " "Radius is linearly interpolated from lightStartRadius to lightEndRadius "
@ -515,6 +527,7 @@ void ExplosionData::initPersistFields()
addField( "lightNormalOffset", TypeF32, Offset(lightNormalOffset, ExplosionData), addField( "lightNormalOffset", TypeF32, Offset(lightNormalOffset, ExplosionData),
"Distance (in the explosion normal direction) of the PointLight position " "Distance (in the explosion normal direction) of the PointLight position "
"from the explosion center." ); "from the explosion center." );
endGroup("Light Emitter");
// disallow some field substitutions // disallow some field substitutions
onlyKeepClearSubstitutions("debris"); // subs resolving to "~~", or "~0" are OK onlyKeepClearSubstitutions("debris"); // subs resolving to "~~", or "~0" are OK

View file

@ -88,7 +88,6 @@ ConsoleDocClass( ItemData,
" density = 2;\n" " density = 2;\n"
" drag = 0.5;\n" " drag = 0.5;\n"
" maxVelocity = \"10.0\";\n" " maxVelocity = \"10.0\";\n"
" emap = true;\n"
" sticky = false;\n" " sticky = false;\n"
" dynamicType = \"0\"\n;" " dynamicType = \"0\"\n;"
" lightOnlyStatic = false;\n" " lightOnlyStatic = false;\n"
@ -109,9 +108,6 @@ ConsoleDocClass( ItemData,
ItemData::ItemData() ItemData::ItemData()
{ {
shadowEnable = true;
friction = 0; friction = 0;
elasticity = 0; elasticity = 0;
@ -141,6 +137,7 @@ EndImplementEnumType;
void ItemData::initPersistFields() void ItemData::initPersistFields()
{ {
addGroup("Physics");
addField("friction", TypeF32, Offset(friction, ItemData), "A floating-point value specifying how much velocity is lost to impact and sliding friction."); addField("friction", TypeF32, Offset(friction, ItemData), "A floating-point value specifying how much velocity is lost to impact and sliding friction.");
addField("elasticity", TypeF32, Offset(elasticity, ItemData), "A floating-point value specifying how 'bouncy' this ItemData is."); addField("elasticity", TypeF32, Offset(elasticity, ItemData), "A floating-point value specifying how 'bouncy' this ItemData is.");
addField("sticky", TypeBool, Offset(sticky, ItemData), addField("sticky", TypeBool, Offset(sticky, ItemData),
@ -150,7 +147,17 @@ void ItemData::initPersistFields()
"@note Valid objects to stick to must be of StaticShapeObjectType.\n"); "@note Valid objects to stick to must be of StaticShapeObjectType.\n");
addField("gravityMod", TypeF32, Offset(gravityMod, ItemData), "Floating point value to multiply the existing gravity with, just for this ItemData."); addField("gravityMod", TypeF32, Offset(gravityMod, ItemData), "Floating point value to multiply the existing gravity with, just for this ItemData.");
addField("maxVelocity", TypeF32, Offset(maxVelocity, ItemData), "Maximum velocity that this ItemData is able to move."); addField("maxVelocity", TypeF32, Offset(maxVelocity, ItemData), "Maximum velocity that this ItemData is able to move.");
addField("simpleServerCollision", TypeBool, Offset(simpleServerCollision, ItemData),
"@brief Determines if only simple server-side collision will be used (for pick ups).\n\n"
"If set to true then only simple, server-side collision detection will be used. This is often the case "
"if the item is used for a pick up object, such as ammo. If set to false then a full collision volume "
"will be used as defined by the shape. The default is true.\n"
"@note Only applies when using a physics library.\n"
"@see TurretShape and ProximityMine for examples that should set this to false to allow them to be "
"shot by projectiles.\n");
endGroup("Physics");
addGroup("Light Emitter");
addField("lightType", TYPEID< Item::LightType >(), Offset(lightType, ItemData), "Type of light to apply to this ItemData. Options are NoLight, ConstantLight, PulsingLight. Default is NoLight." ); addField("lightType", TYPEID< Item::LightType >(), Offset(lightType, ItemData), "Type of light to apply to this ItemData. Options are NoLight, ConstantLight, PulsingLight. Default is NoLight." );
addField("lightColor", TypeColorF, Offset(lightColor, ItemData), addField("lightColor", TypeColorF, Offset(lightColor, ItemData),
"@brief Color value to make this light. Example: \"1.0,1.0,1.0\"\n\n" "@brief Color value to make this light. Example: \"1.0,1.0,1.0\"\n\n"
@ -164,15 +171,7 @@ void ItemData::initPersistFields()
addField("lightOnlyStatic", TypeBool, Offset(lightOnlyStatic, ItemData), addField("lightOnlyStatic", TypeBool, Offset(lightOnlyStatic, ItemData),
"@brief If true, this ItemData will only cast a light if the Item for this ItemData has a static value of true.\n\n" "@brief If true, this ItemData will only cast a light if the Item for this ItemData has a static value of true.\n\n"
"@see lightType\n"); "@see lightType\n");
endGroup("Light Emitter");
addField("simpleServerCollision", TypeBool, Offset(simpleServerCollision, ItemData),
"@brief Determines if only simple server-side collision will be used (for pick ups).\n\n"
"If set to true then only simple, server-side collision detection will be used. This is often the case "
"if the item is used for a pick up object, such as ammo. If set to false then a full collision volume "
"will be used as defined by the shape. The default is true.\n"
"@note Only applies when using a physics library.\n"
"@see TurretShape and ProximityMine for examples that should set this to false to allow them to be "
"shot by projectiles.\n");
Parent::initPersistFields(); Parent::initPersistFields();
} }
@ -262,7 +261,6 @@ ConsoleDocClass( Item,
" mass = 2;\n" " mass = 2;\n"
" friction = 1;\n" " friction = 1;\n"
" elasticity = 0.3;\n" " elasticity = 0.3;\n"
" emap = true;\n\n"
" // Dynamic properties used by the scripts\n" " // Dynamic properties used by the scripts\n"
" pickupName = \"a health patch\";\n" " pickupName = \"a health patch\";\n"
" repairAmount = 50;\n" " repairAmount = 50;\n"

View file

@ -110,7 +110,7 @@ bool PhysicsDebrisData::preload( bool server, String &errorStr )
void PhysicsDebrisData::initPersistFields() void PhysicsDebrisData::initPersistFields()
{ {
addGroup( "Display" ); addGroup( "Shapes" );
addProtectedField( "shapeFile", TypeShapeFilename, Offset( mShapeName, PhysicsDebrisData ), &_setShapeData, &defaultProtectedGetFn, addProtectedField( "shapeFile", TypeShapeFilename, Offset( mShapeName, PhysicsDebrisData ), &_setShapeData, &defaultProtectedGetFn,
"@brief Path to the .DAE or .DTS file to use for this shape.\n\n" "@brief Path to the .DAE or .DTS file to use for this shape.\n\n"
@ -118,11 +118,12 @@ void PhysicsDebrisData::initPersistFields()
INITPERSISTFIELD_SHAPEASSET(Shape, PhysicsDebrisData, "@brief Shape to use with this debris.\n\n" INITPERSISTFIELD_SHAPEASSET(Shape, PhysicsDebrisData, "@brief Shape to use with this debris.\n\n"
"Compatable with Live-Asset Reloading."); "Compatable with Live-Asset Reloading.");
endGroup( "Shapes" );
addGroup("Rendering");
addField( "castShadows", TypeBool, Offset( castShadows, PhysicsDebrisData ), addField( "castShadows", TypeBool, Offset( castShadows, PhysicsDebrisData ),
"@brief Determines if the shape's shadow should be cast onto the environment.\n\n" ); "@brief Determines if the shape's shadow should be cast onto the environment.\n\n" );
endGroup("Rendering");
endGroup( "Display" );
addGroup( "Physical Properties" ); addGroup( "Physical Properties" );

View file

@ -89,7 +89,7 @@ void PhysicsShapeData::initPersistFields()
{ {
Parent::initPersistFields(); Parent::initPersistFields();
addGroup("Media"); addGroup("Shapes");
INITPERSISTFIELD_SHAPEASSET(Shape, PhysicsShapeData, "@brief Shape asset to be used with this physics object.\n\n" INITPERSISTFIELD_SHAPEASSET(Shape, PhysicsShapeData, "@brief Shape asset to be used with this physics object.\n\n"
"Compatable with Live-Asset Reloading. ") "Compatable with Live-Asset Reloading. ")
@ -103,7 +103,7 @@ void PhysicsShapeData::initPersistFields()
addField( "destroyedShape", TYPEID< SimObjectRef<PhysicsShapeData> >(), Offset( destroyedShape, PhysicsShapeData ), addField( "destroyedShape", TYPEID< SimObjectRef<PhysicsShapeData> >(), Offset( destroyedShape, PhysicsShapeData ),
"@brief Name of a PhysicsShapeData to spawn when this shape is destroyed (optional)." ); "@brief Name of a PhysicsShapeData to spawn when this shape is destroyed (optional)." );
endGroup("Media"); endGroup("Shapes");
addGroup( "Physics" ); addGroup( "Physics" );

View file

@ -282,7 +282,6 @@ IMPLEMENT_CALLBACK( PlayerData, onLeaveMissionArea, void, ( Player* obj ), ( obj
PlayerData::PlayerData() PlayerData::PlayerData()
{ {
shadowEnable = true;
shadowSize = 256; shadowSize = 256;
shadowProjectionDistance = 14.0f; shadowProjectionDistance = 14.0f;

View file

@ -232,46 +232,22 @@ ProjectileData::ProjectileData(const ProjectileData& other, bool temp_clone) : G
void ProjectileData::initPersistFields() void ProjectileData::initPersistFields()
{ {
addField("particleEmitter", TYPEID< ParticleEmitterData >(), Offset(particleEmitter, ProjectileData), addGroup("Physics");
"@brief Particle emitter datablock used to generate particles while the projectile is outside of water.\n\n" addProtectedField("lifetime", TypeS32, Offset(lifetime, ProjectileData), &setLifetime, &getScaledValue,
"@note If datablocks are defined for both particleEmitter and particleWaterEmitter, both effects will play " "@brief Amount of time, in milliseconds, before the projectile is removed from the simulation.\n\n"
"as the projectile enters or leaves water.\n\n" "Used with fadeDelay to determine the transparency of the projectile at a given time. "
"@see particleWaterEmitter\n"); "A projectile may exist up to a maximum of 131040ms (or 4095 ticks) as defined by Projectile::MaxLivingTicks in the source code."
addField("particleWaterEmitter", TYPEID< ParticleEmitterData >(), Offset(particleWaterEmitter, ProjectileData), "@see fadeDelay");
"@brief Particle emitter datablock used to generate particles while the projectile is submerged in water.\n\n" addProtectedField("armingDelay", TypeS32, Offset(armingDelay, ProjectileData), &setArmingDelay, &getScaledValue,
"@note If datablocks are defined for both particleWaterEmitter and particleEmitter , both effects will play " "@brief Amount of time, in milliseconds, before the projectile will cause damage or explode on impact.\n\n"
"as the projectile enters or leaves water.\n\n" "This value must be equal to or less than the projectile's lifetime.\n\n"
"@see particleEmitter\n"); "@see lifetime");
addProtectedField("fadeDelay", TypeS32, Offset(fadeDelay, ProjectileData), &setFadeDelay, &getScaledValue,
addProtectedField("projectileShapeName", TypeShapeFilename, Offset(mProjectileShapeName, ProjectileData), &_setProjectileShapeData, &defaultProtectedGetFn, "@brief Amount of time, in milliseconds, before the projectile begins to fade out.\n\n"
"@brief File path to the model of the projectile.\n\n", AbstractClassRep::FIELD_HideInInspectors); "This value must be smaller than the projectile's lifetime to have an affect.");
INITPERSISTFIELD_SHAPEASSET(ProjectileShape, ProjectileData, "@brief The model of the projectile.\n\n");
addField("scale", TypePoint3F, Offset(scale, ProjectileData),
"@brief Scale to apply to the projectile's size.\n\n"
"@note This is applied after SceneObject::scale\n");
INITPERSISTFIELD_SOUNDASSET(ProjectileSound, ProjectileData, "The sound for the projectile.");
addField("explosion", TYPEID< ExplosionData >(), Offset(explosion, ProjectileData),
"@brief Explosion datablock used when the projectile explodes outside of water.\n\n");
addField("waterExplosion", TYPEID< ExplosionData >(), Offset(waterExplosion, ProjectileData),
"@brief Explosion datablock used when the projectile explodes underwater.\n\n");
addField("splash", TYPEID< SplashData >(), Offset(splash, ProjectileData),
"@brief Splash datablock used to create splash effects as the projectile enters or leaves water\n\n");
addField("decal", TYPEID< DecalData >(), Offset(decal, ProjectileData),
"@brief Decal datablock used for decals placed at projectile explosion points.\n\n");
addField("lightDesc", TYPEID< LightDescription >(), Offset(lightDesc, ProjectileData),
"@brief LightDescription datablock used for lights attached to the projectile.\n\n");
addField("isBallistic", TypeBool, Offset(isBallistic, ProjectileData), addField("isBallistic", TypeBool, Offset(isBallistic, ProjectileData),
"@brief Detetmines if the projectile should be affected by gravity and whether or not " "@brief Detetmines if the projectile should be affected by gravity and whether or not "
"it bounces before exploding.\n\n"); "it bounces before exploding.\n\n");
addField("velInheritFactor", TypeF32, Offset(velInheritFactor, ProjectileData), addField("velInheritFactor", TypeF32, Offset(velInheritFactor, ProjectileData),
"@brief Amount of velocity the projectile recieves from the source that created it.\n\n" "@brief Amount of velocity the projectile recieves from the source that created it.\n\n"
"Use an amount between 0 and 1 for the best effect. " "Use an amount between 0 and 1 for the best effect. "
@ -283,23 +259,7 @@ void ProjectileData::initPersistFields()
"This value is never modified by the engine.\n\n" "This value is never modified by the engine.\n\n"
"@note This value by default is not transmitted between the server and the client.\n\n" "@note This value by default is not transmitted between the server and the client.\n\n"
"@see velInheritFactor"); "@see velInheritFactor");
addField("impactForce", TypeF32, Offset(impactForce, ProjectileData)); addField("impactForce", TypeF32, Offset(impactForce, ProjectileData));
addProtectedField("lifetime", TypeS32, Offset(lifetime, ProjectileData), &setLifetime, &getScaledValue,
"@brief Amount of time, in milliseconds, before the projectile is removed from the simulation.\n\n"
"Used with fadeDelay to determine the transparency of the projectile at a given time. "
"A projectile may exist up to a maximum of 131040ms (or 4095 ticks) as defined by Projectile::MaxLivingTicks in the source code."
"@see fadeDelay");
addProtectedField("armingDelay", TypeS32, Offset(armingDelay, ProjectileData), &setArmingDelay, &getScaledValue,
"@brief Amount of time, in milliseconds, before the projectile will cause damage or explode on impact.\n\n"
"This value must be equal to or less than the projectile's lifetime.\n\n"
"@see lifetime");
addProtectedField("fadeDelay", TypeS32, Offset(fadeDelay, ProjectileData), &setFadeDelay, &getScaledValue,
"@brief Amount of time, in milliseconds, before the projectile begins to fade out.\n\n"
"This value must be smaller than the projectile's lifetime to have an affect.");
addField("bounceElasticity", TypeF32, Offset(bounceElasticity, ProjectileData), addField("bounceElasticity", TypeF32, Offset(bounceElasticity, ProjectileData),
"@brief Influences post-bounce velocity of a projectile that does not explode on contact.\n\n" "@brief Influences post-bounce velocity of a projectile that does not explode on contact.\n\n"
"Scales the velocity from a bounce after friction is taken into account. " "Scales the velocity from a bounce after friction is taken into account. "
@ -308,12 +268,54 @@ void ProjectileData::initPersistFields()
"@brief Factor to reduce post-bounce velocity of a projectile that does not explode on contact.\n\n" "@brief Factor to reduce post-bounce velocity of a projectile that does not explode on contact.\n\n"
"Reduces bounce velocity by this factor and a multiple of the tangent to impact. " "Reduces bounce velocity by this factor and a multiple of the tangent to impact. "
"Used to simulate surface friction.\n"); "Used to simulate surface friction.\n");
addField("gravityMod", TypeF32, Offset(gravityMod, ProjectileData ), addField("gravityMod", TypeF32, Offset(gravityMod, ProjectileData),
"@brief Scales the influence of gravity on the projectile.\n\n" "@brief Scales the influence of gravity on the projectile.\n\n"
"The larger this value is, the more that gravity will affect the projectile. " "The larger this value is, the more that gravity will affect the projectile. "
"A value of 1.0 will assume \"normal\" influence upon it.\n" "A value of 1.0 will assume \"normal\" influence upon it.\n"
"The magnitude of gravity is assumed to be 9.81 m/s/s\n\n" "The magnitude of gravity is assumed to be 9.81 m/s/s\n\n"
"@note ProjectileData::isBallistic must be true for this to have any affect."); "@note ProjectileData::isBallistic must be true for this to have any affect.");
endGroup("Physics");
addGroup("Shapes");
addProtectedField("projectileShapeName", TypeShapeFilename, Offset(mProjectileShapeName, ProjectileData), &_setProjectileShapeData, &defaultProtectedGetFn,
"@brief File path to the model of the projectile.\n\n", AbstractClassRep::FIELD_HideInInspectors);
INITPERSISTFIELD_SHAPEASSET(ProjectileShape, ProjectileData, "@brief The model of the projectile.\n\n");
addField("scale", TypePoint3F, Offset(scale, ProjectileData),
"@brief Scale to apply to the projectile's size.\n\n"
"@note This is applied after SceneObject::scale\n");
endGroup("Shapes");
addGroup("Particle Effects");
addField("particleEmitter", TYPEID< ParticleEmitterData >(), Offset(particleEmitter, ProjectileData),
"@brief Particle emitter datablock used to generate particles while the projectile is outside of water.\n\n"
"@note If datablocks are defined for both particleEmitter and particleWaterEmitter, both effects will play "
"as the projectile enters or leaves water.\n\n"
"@see particleWaterEmitter\n");
addField("particleWaterEmitter", TYPEID< ParticleEmitterData >(), Offset(particleWaterEmitter, ProjectileData),
"@brief Particle emitter datablock used to generate particles while the projectile is submerged in water.\n\n"
"@note If datablocks are defined for both particleWaterEmitter and particleEmitter , both effects will play "
"as the projectile enters or leaves water.\n\n"
"@see particleEmitter\n");
addField("explosion", TYPEID< ExplosionData >(), Offset(explosion, ProjectileData),
"@brief Explosion datablock used when the projectile explodes outside of water.\n\n");
addField("waterExplosion", TYPEID< ExplosionData >(), Offset(waterExplosion, ProjectileData),
"@brief Explosion datablock used when the projectile explodes underwater.\n\n");
addField("splash", TYPEID< SplashData >(), Offset(splash, ProjectileData),
"@brief Splash datablock used to create splash effects as the projectile enters or leaves water\n\n");
addField("decal", TYPEID< DecalData >(), Offset(decal, ProjectileData),
"@brief Decal datablock used for decals placed at projectile explosion points.\n\n");
endGroup("Particle Effects");
addGroup("Sounds");
INITPERSISTFIELD_SOUNDASSET(ProjectileSound, ProjectileData, "The sound for the projectile.");
endGroup("Sounds");
addGroup("Light Emitter");
addField("lightDesc", TYPEID< LightDescription >(), Offset(lightDesc, ProjectileData),
"@brief LightDescription datablock used for lights attached to the projectile.\n\n");
endGroup("Light Emitter");
// disallow some field substitutions // disallow some field substitutions
onlyKeepClearSubstitutions("explosion"); onlyKeepClearSubstitutions("explosion");
onlyKeepClearSubstitutions("particleEmitter"); onlyKeepClearSubstitutions("particleEmitter");

View file

@ -61,7 +61,6 @@ ConsoleDocClass( RigidShapeData,
" category = \"RigidShape\";\n" " category = \"RigidShape\";\n"
"\n" "\n"
" shapeFile = \"~/data/shapes/boulder/boulder.dts\";\n" " shapeFile = \"~/data/shapes/boulder/boulder.dts\";\n"
" emap = true;\n"
"\n" "\n"
" // Rigid Body\n" " // Rigid Body\n"
" mass = 500;\n" " mass = 500;\n"
@ -112,7 +111,6 @@ ConsoleDocClass( RigidShape,
" category = \"RigidShape\";\n" " category = \"RigidShape\";\n"
"\n" "\n"
" shapeFile = \"~/data/shapes/boulder/boulder.dts\";\n" " shapeFile = \"~/data/shapes/boulder/boulder.dts\";\n"
" emap = true;\n"
"\n" "\n"
" // Rigid Body\n" " // Rigid Body\n"
" mass = 500;\n" " mass = 500;\n"
@ -232,8 +230,6 @@ EndImplementEnumType;
RigidShapeData::RigidShapeData() RigidShapeData::RigidShapeData()
{ {
shadowEnable = true;
body.friction = 0; body.friction = 0;
body.restitution = 1; body.restitution = 1;
@ -519,67 +515,50 @@ void RigidShapeData::initPersistFields()
addGroup("Physics"); addGroup("Physics");
addField("enablePhysicsRep", TypeBool, Offset(enablePhysicsRep, RigidShapeData), addField("enablePhysicsRep", TypeBool, Offset(enablePhysicsRep, RigidShapeData),
"@brief Creates a representation of the object in the physics plugin.\n"); "@brief Creates a representation of the object in the physics plugin.\n");
endGroup("Physics"); ("massCenter", TypePoint3F, Offset(massCenter, RigidShapeData), "Center of mass for rigid body.");
addField("massCenter", TypePoint3F, Offset(massCenter, RigidShapeData), "Center of mass for rigid body.");
addField("massBox", TypePoint3F, Offset(massBox, RigidShapeData), "Size of inertial box."); addField("massBox", TypePoint3F, Offset(massBox, RigidShapeData), "Size of inertial box.");
addField("bodyRestitution", TypeF32, Offset(body.restitution, RigidShapeData), "The percentage of kinetic energy kept by this object in a collision."); addField("bodyRestitution", TypeF32, Offset(body.restitution, RigidShapeData), "The percentage of kinetic energy kept by this object in a collision.");
addField("bodyFriction", TypeF32, Offset(body.friction, RigidShapeData), "How much friction this object has. Lower values will cause the object to appear to be more slippery."); addField("bodyFriction", TypeF32, Offset(body.friction, RigidShapeData), "How much friction this object has. Lower values will cause the object to appear to be more slippery.");
addField("minImpactSpeed", TypeF32, Offset(minImpactSpeed, RigidShapeData),
"Minimum collision speed to classify collision as impact (triggers onImpact on server object)." );
addField("softImpactSpeed", TypeF32, Offset(softImpactSpeed, RigidShapeData), "Minimum speed at which this object must be travelling for the soft impact sound to be played.");
addField("hardImpactSpeed", TypeF32, Offset(hardImpactSpeed, RigidShapeData), "Minimum speed at which the object must be travelling for the hard impact sound to be played.");
addField("minRollSpeed", TypeF32, Offset(minRollSpeed, RigidShapeData));
addField("maxDrag", TypeF32, Offset(maxDrag, RigidShapeData), "Maximum drag available to this object."); addField("maxDrag", TypeF32, Offset(maxDrag, RigidShapeData), "Maximum drag available to this object.");
addField("minDrag", TypeF32, Offset(minDrag, RigidShapeData), "Minimum drag available to this object."); addField("minDrag", TypeF32, Offset(minDrag, RigidShapeData), "Minimum drag available to this object.");
addField("integration", TypeS32, Offset(integration, RigidShapeData), "Number of physics steps to process per tick."); addField("integration", TypeS32, Offset(integration, RigidShapeData), "Number of physics steps to process per tick.");
addField("collisionTol", TypeF32, Offset(collisionTol, RigidShapeData), "Collision distance tolerance."); addField("collisionTol", TypeF32, Offset(collisionTol, RigidShapeData), "Collision distance tolerance.");
addField("contactTol", TypeF32, Offset(contactTol, RigidShapeData), "Contact velocity tolerance."); addField("contactTol", TypeF32, Offset(contactTol, RigidShapeData), "Contact velocity tolerance.");
addGroup( "Forces" );
addField("dragForce", TypeF32, Offset(dragForce, RigidShapeData), "Used to simulate the constant drag acting on the object"); addField("dragForce", TypeF32, Offset(dragForce, RigidShapeData), "Used to simulate the constant drag acting on the object");
addField("vertFactor", TypeF32, Offset(vertFactor, RigidShapeData), "The scalar applied to the vertical portion of the velocity drag acting on a object."); addField("vertFactor", TypeF32, Offset(vertFactor, RigidShapeData), "The scalar applied to the vertical portion of the velocity drag acting on a object.");
endGroup("Physics");
endGroup( "Forces" ); addGroup("Collision");
addField("minImpactSpeed", TypeF32, Offset(minImpactSpeed, RigidShapeData),
addGroup( "Particle Effects" ); "Minimum collision speed to classify collision as impact (triggers onImpact on server object)." );
addField("softImpactSpeed", TypeF32, Offset(softImpactSpeed, RigidShapeData), "Minimum speed at which this object must be travelling for the soft impact sound to be played.");
addField("dustEmitter", TYPEID< ParticleEmitterData >(), Offset(dustEmitter, RigidShapeData), "Array of pointers to ParticleEmitterData datablocks which will be used to emit particles at object/terrain contact point.\n"); addField("hardImpactSpeed", TypeF32, Offset(hardImpactSpeed, RigidShapeData), "Minimum speed at which the object must be travelling for the hard impact sound to be played.");
addField("triggerDustHeight", TypeF32, Offset(triggerDustHeight, RigidShapeData), "Maximum height from the ground at which the object will generate dust.\n"); addField("minRollSpeed", TypeF32, Offset(minRollSpeed, RigidShapeData));
addField("dustHeight", TypeF32, Offset(dustHeight, RigidShapeData), "Height of dust effects.\n");
addField("dustTrailEmitter", TYPEID< ParticleEmitterData >(), Offset(dustTrailEmitter, RigidShapeData), "Particle emitter used to create a dust trail for the moving object.\n");
addField("splashEmitter", TYPEID< ParticleEmitterData >(), Offset(splashEmitterList, RigidShapeData), VC_NUM_SPLASH_EMITTERS, "Array of pointers to ParticleEmitterData datablocks which will generate splash effects.\n");
addField("splashFreqMod", TypeF32, Offset(splashFreqMod, RigidShapeData), "The simulated frequency modulation of a splash generated by this object. Multiplied along with speed and time elapsed when determining splash emition rate.\n");
addField("splashVelEpsilon", TypeF32, Offset(splashVelEpsilon, RigidShapeData), "The threshold speed at which we consider the object's movement to have stopped when updating splash effects.\n");
endGroup( "Particle Effects" );
addGroup( "Sounds" );
INITPERSISTFIELD_SOUNDASSET_ENUMED(BodySounds, bodySounds, Body::Sounds::MaxSounds, RigidShapeData, "Sounds for body.");
addField("exitSplashSoundVelocity", TypeF32, Offset(exitSplashSoundVel, RigidShapeData), "The minimum velocity at which the exit splash sound will be played when emerging from water.\n"); addField("exitSplashSoundVelocity", TypeF32, Offset(exitSplashSoundVel, RigidShapeData), "The minimum velocity at which the exit splash sound will be played when emerging from water.\n");
addField("softSplashSoundVelocity", TypeF32, Offset(softSplashSoundVel, RigidShapeData),"The minimum velocity at which the soft splash sound will be played when impacting water.\n"); addField("softSplashSoundVelocity", TypeF32, Offset(softSplashSoundVel, RigidShapeData),"The minimum velocity at which the soft splash sound will be played when impacting water.\n");
addField("mediumSplashSoundVelocity", TypeF32, Offset(medSplashSoundVel, RigidShapeData), "The minimum velocity at which the medium splash sound will be played when impacting water.\n"); addField("mediumSplashSoundVelocity", TypeF32, Offset(medSplashSoundVel, RigidShapeData), "The minimum velocity at which the medium splash sound will be played when impacting water.\n");
addField("hardSplashSoundVelocity", TypeF32, Offset(hardSplashSoundVel, RigidShapeData), "The minimum velocity at which the hard splash sound will be played when impacting water.\n"); addField("hardSplashSoundVelocity", TypeF32, Offset(hardSplashSoundVel, RigidShapeData), "The minimum velocity at which the hard splash sound will be played when impacting water.\n");
endGroup("Collision");
INITPERSISTFIELD_SOUNDASSET_ENUMED(WaterSounds, waterSounds, Sounds::MaxSounds, RigidShapeData, "Sounds for interacting with water."); addGroup( "Particle Effects" );
addField("dustEmitter", TYPEID< ParticleEmitterData >(), Offset(dustEmitter, RigidShapeData), "Array of pointers to ParticleEmitterData datablocks which will be used to emit particles at object/terrain contact point.\n");
addField("triggerDustHeight", TypeF32, Offset(triggerDustHeight, RigidShapeData), "Maximum height from the ground at which the object will generate dust.\n");
addField("dustHeight", TypeF32, Offset(dustHeight, RigidShapeData), "Height of dust effects.\n");
addField("dustTrailEmitter", TYPEID< ParticleEmitterData >(), Offset(dustTrailEmitter, RigidShapeData), "Particle emitter used to create a dust trail for the moving object.\n");
addField("splashEmitter", TYPEID< ParticleEmitterData >(), Offset(splashEmitterList, RigidShapeData), VC_NUM_SPLASH_EMITTERS, "Array of pointers to ParticleEmitterData datablocks which will generate splash effects.\n");
addField("splashFreqMod", TypeF32, Offset(splashFreqMod, RigidShapeData), "The simulated frequency modulation of a splash generated by this object. Multiplied along with speed and time elapsed when determining splash emition rate.\n");
addField("splashVelEpsilon", TypeF32, Offset(splashVelEpsilon, RigidShapeData), "The threshold speed at which we consider the object's movement to have stopped when updating splash effects.\n");
endGroup( "Particle Effects" );
addGroup( "Sounds" );
INITPERSISTFIELD_SOUNDASSET_ENUMED(BodySounds, bodySounds, Body::Sounds::MaxSounds, RigidShapeData, "Sounds for body."); INITPERSISTFIELD_SOUNDASSET_ENUMED(WaterSounds, waterSounds, Sounds::MaxSounds, RigidShapeData, "Sounds for interacting with water.");
endGroup( "Sounds" ); endGroup( "Sounds" );
addGroup( "Camera" ); addGroup( "Camera" );
addField("cameraRoll", TypeBool, Offset(cameraRoll, RigidShapeData), "Specifies whether the camera's rotation matrix, and the render eye transform are multiplied during camera updates.\n"); addField("cameraRoll", TypeBool, Offset(cameraRoll, RigidShapeData), "Specifies whether the camera's rotation matrix, and the render eye transform are multiplied during camera updates.\n");
addField("cameraLag", TypeF32, Offset(cameraLag, RigidShapeData), "Scalar amount by which the third person camera lags the object, relative to the object's linear velocity.\n"); addField("cameraLag", TypeF32, Offset(cameraLag, RigidShapeData), "Scalar amount by which the third person camera lags the object, relative to the object's linear velocity.\n");
addField("cameraDecay", TypeF32, Offset(cameraDecay, RigidShapeData), "Scalar rate at which the third person camera offset decays, per tick.\n"); addField("cameraDecay", TypeF32, Offset(cameraDecay, RigidShapeData), "Scalar rate at which the third person camera offset decays, per tick.\n");
addField("cameraOffset", TypeF32, Offset(cameraOffset, RigidShapeData), "The vertical offset of the object's camera.\n"); addField("cameraOffset", TypeF32, Offset(cameraOffset, RigidShapeData), "The vertical offset of the object's camera.\n");
endGroup( "Camera" ); endGroup( "Camera" );
Parent::initPersistFields(); Parent::initPersistFields();

View file

@ -153,7 +153,7 @@ static const char *sDamageStateName[] =
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ShapeBaseData::ShapeBaseData() ShapeBaseData::ShapeBaseData()
: shadowEnable( false ), :
shadowSize( 128 ), shadowSize( 128 ),
shadowMaxVisibleDistance( 80.0f ), shadowMaxVisibleDistance( 80.0f ),
shadowProjectionDistance( 10.0f ), shadowProjectionDistance( 10.0f ),
@ -208,7 +208,6 @@ ShapeBaseData::ShapeBaseData()
ShapeBaseData::ShapeBaseData(const ShapeBaseData& other, bool temp_clone) : GameBaseData(other, temp_clone) ShapeBaseData::ShapeBaseData(const ShapeBaseData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{ {
shadowEnable = other.shadowEnable;
shadowSize = other.shadowSize; shadowSize = other.shadowSize;
shadowMaxVisibleDistance = other.shadowMaxVisibleDistance; shadowMaxVisibleDistance = other.shadowMaxVisibleDistance;
shadowProjectionDistance = other.shadowProjectionDistance; shadowProjectionDistance = other.shadowProjectionDistance;
@ -535,31 +534,14 @@ bool ShapeBaseData::_setMass( void* object, const char* index, const char* data
void ShapeBaseData::initPersistFields() void ShapeBaseData::initPersistFields()
{ {
addGroup( "Shadows" );
addField( "shadowEnable", TypeBool, Offset(shadowEnable, ShapeBaseData),
"Enable shadows for this shape (currently unused, shadows are always enabled)." );
addField( "shadowSize", TypeS32, Offset(shadowSize, ShapeBaseData),
"Size of the projected shadow texture (must be power of 2)." );
addField( "shadowMaxVisibleDistance", TypeF32, Offset(shadowMaxVisibleDistance, ShapeBaseData),
"Maximum distance at which shadow is visible (currently unused)." );
addField( "shadowProjectionDistance", TypeF32, Offset(shadowProjectionDistance, ShapeBaseData),
"Maximum height above ground to project shadow. If the object is higher "
"than this no shadow will be rendered." );
addField( "shadowSphereAdjust", TypeF32, Offset(shadowSphereAdjust, ShapeBaseData),
"Scalar applied to the radius of spot shadows (initial radius is based "
"on the shape bounds but can be adjusted with this field)." );
endGroup( "Shadows" );
addGroup( "Render" );
addGroup( "Shapes" );
INITPERSISTFIELD_SHAPEASSET(Shape, ShapeBaseData, "The source shape asset."); INITPERSISTFIELD_SHAPEASSET(Shape, ShapeBaseData, "The source shape asset.");
addField("silentBBoxValidation", TypeBool, Offset(silent_bbox_check, ShapeBaseData));
INITPERSISTFIELD_SHAPEASSET(DebrisShape, ShapeBaseData, "The shape asset to use for auto-generated breakups via blowup(). @note may not be functional.");
endGroup( "Shapes" );
endGroup( "Render" ); addGroup("Particle Effects");
addGroup( "Destruction", "Parameters related to the destruction effects of this object." );
addField( "explosion", TYPEID< ExplosionData >(), Offset(explosion, ShapeBaseData), addField( "explosion", TYPEID< ExplosionData >(), Offset(explosion, ShapeBaseData),
"%Explosion to generate when this shape is blown up." ); "%Explosion to generate when this shape is blown up." );
addField( "underwaterExplosion", TYPEID< ExplosionData >(), Offset(underwaterExplosion, ShapeBaseData), addField( "underwaterExplosion", TYPEID< ExplosionData >(), Offset(underwaterExplosion, ShapeBaseData),
@ -568,23 +550,17 @@ void ShapeBaseData::initPersistFields()
"%Debris to generate when this shape is blown up." ); "%Debris to generate when this shape is blown up." );
addField( "renderWhenDestroyed", TypeBool, Offset(renderWhenDestroyed, ShapeBaseData), addField( "renderWhenDestroyed", TypeBool, Offset(renderWhenDestroyed, ShapeBaseData),
"Whether to render the shape when it is in the \"Destroyed\" damage state." ); "Whether to render the shape when it is in the \"Destroyed\" damage state." );
endGroup("Particle Effects");
INITPERSISTFIELD_SHAPEASSET(DebrisShape, ShapeBaseData, "The shape asset to use for auto-generated breakups. @note may not be functional.");
endGroup( "Destruction" );
addGroup( "Physics" ); addGroup( "Physics" );
addProtectedField("mass", TypeF32, Offset(mass, ShapeBaseData), &_setMass, &defaultProtectedGetFn, "Shape mass.\nUsed in simulation of moving objects.\n" ); addProtectedField("mass", TypeF32, Offset(mass, ShapeBaseData), &_setMass, &defaultProtectedGetFn, "Shape mass.\nUsed in simulation of moving objects.\n" );
addField( "drag", TypeF32, Offset(drag, ShapeBaseData), addField( "drag", TypeF32, Offset(drag, ShapeBaseData),
"Drag factor.\nReduces velocity of moving objects." ); "Drag factor.\nReduces velocity of moving objects." );
addField( "density", TypeF32, Offset(density, ShapeBaseData), addField( "density", TypeF32, Offset(density, ShapeBaseData),
"Shape density.\nUsed when computing buoyancy when in water.\n" ); "Shape density.\nUsed when computing buoyancy when in water.\n" );
endGroup( "Physics" ); endGroup( "Physics" );
addGroup( "Damage/Energy" ); addGroup( "Damage/Energy" );
addField( "maxEnergy", TypeF32, Offset(maxEnergy, ShapeBaseData), addField( "maxEnergy", TypeF32, Offset(maxEnergy, ShapeBaseData),
"Maximum energy level for this object." ); "Maximum energy level for this object." );
addField( "maxDamage", TypeF32, Offset(maxDamage, ShapeBaseData), addField( "maxDamage", TypeF32, Offset(maxDamage, ShapeBaseData),
@ -605,11 +581,9 @@ void ShapeBaseData::initPersistFields()
addField( "isInvincible", TypeBool, Offset(isInvincible, ShapeBaseData), addField( "isInvincible", TypeBool, Offset(isInvincible, ShapeBaseData),
"Invincible flag; when invincible, the object cannot be damaged or " "Invincible flag; when invincible, the object cannot be damaged or "
"repaired." ); "repaired." );
endGroup( "Damage/Energy" ); endGroup( "Damage/Energy" );
addGroup( "Camera", "The settings used by the shape when it is the camera." ); addGroup( "Camera", "The settings used by the shape when it is the camera." );
addField( "cameraMaxDist", TypeF32, Offset(cameraMaxDist, ShapeBaseData), addField( "cameraMaxDist", TypeF32, Offset(cameraMaxDist, ShapeBaseData),
"The maximum distance from the camera to the object.\n" "The maximum distance from the camera to the object.\n"
"Used when computing a custom camera transform for this object.\n\n" "Used when computing a custom camera transform for this object.\n\n"
@ -638,30 +612,38 @@ void ShapeBaseData::initPersistFields()
"Observe this object through its camera transform and default fov.\n" "Observe this object through its camera transform and default fov.\n"
"If true, when this object is the camera it can provide a custom camera " "If true, when this object is the camera it can provide a custom camera "
"transform and FOV (instead of the default eye transform)." ); "transform and FOV (instead of the default eye transform)." );
endGroup("Camera"); endGroup("Camera");
addGroup( "Misc" ); addGroup( "Misc" );
addField( "computeCRC", TypeBool, Offset(computeCRC, ShapeBaseData), addField( "computeCRC", TypeBool, Offset(computeCRC, ShapeBaseData),
"If true, verify that the CRC of the client's shape model matches the " "If true, verify that the CRC of the client's shape model matches the "
"server's CRC for the shape model when loaded by the client." ); "server's CRC for the shape model when loaded by the client." );
endGroup( "Misc" ); endGroup( "Misc" );
addGroup( "Reflection" ); addGroup( "Reflection" );
addField( "cubeReflectorDesc", TypeRealString, Offset( cubeDescName, ShapeBaseData ), addField( "cubeReflectorDesc", TypeRealString, Offset( cubeDescName, ShapeBaseData ),
"References a ReflectorDesc datablock that defines performance and quality properties for dynamic reflections.\n"); "References a ReflectorDesc datablock that defines performance and quality properties for dynamic reflections.\n");
//addField( "reflectMaxRateMs", TypeS32, Offset( reflectMaxRateMs, ShapeBaseData ), "reflection will not be updated more frequently than this" ); //addField( "reflectMaxRateMs", TypeS32, Offset( reflectMaxRateMs, ShapeBaseData ), "reflection will not be updated more frequently than this" );
//addField( "reflectMaxDist", TypeF32, Offset( reflectMaxDist, ShapeBaseData ), "distance at which reflection is never updated" ); //addField( "reflectMaxDist", TypeF32, Offset( reflectMaxDist, ShapeBaseData ), "distance at which reflection is never updated" );
//addField( "reflectMinDist", TypeF32, Offset( reflectMinDist, ShapeBaseData ), "distance at which reflection is always updated" ); //addField( "reflectMinDist", TypeF32, Offset( reflectMinDist, ShapeBaseData ), "distance at which reflection is always updated" );
//addField( "reflectDetailAdjust", TypeF32, Offset( reflectDetailAdjust, ShapeBaseData ), "scale up or down the detail level for objects rendered in a reflection" ); //addField( "reflectDetailAdjust", TypeF32, Offset( reflectDetailAdjust, ShapeBaseData ), "scale up or down the detail level for objects rendered in a reflection" );
endGroup( "Reflection" ); endGroup( "Reflection" );
addField("remapTextureTags", TypeString, Offset(remap_txr_tags, ShapeBaseData)); addField("remapTextureTags", TypeString, Offset(remap_txr_tags, ShapeBaseData));
addField("silentBBoxValidation", TypeBool, Offset(silent_bbox_check, ShapeBaseData));
addGroup("BL Projected Shadows");
addField("shadowSize", TypeS32, Offset(shadowSize, ShapeBaseData),
"Size of the projected shadow texture (must be power of 2).");
addField("shadowMaxVisibleDistance", TypeF32, Offset(shadowMaxVisibleDistance, ShapeBaseData),
"Maximum distance at which shadow is visible (currently unused).");
addField("shadowProjectionDistance", TypeF32, Offset(shadowProjectionDistance, ShapeBaseData),
"Maximum height above ground to project shadow. If the object is higher "
"than this no shadow will be rendered.");
addField("shadowSphereAdjust", TypeF32, Offset(shadowSphereAdjust, ShapeBaseData),
"Scalar applied to the radius of spot shadows (initial radius is based "
"on the shape bounds but can be adjusted with this field).");
endGroup("BL Projected Shadows");
// disallow some field substitutions // disallow some field substitutions
onlyKeepClearSubstitutions("debris"); // subs resolving to "~~", or "~0" are OK onlyKeepClearSubstitutions("debris"); // subs resolving to "~~", or "~0" are OK
onlyKeepClearSubstitutions("explosion"); onlyKeepClearSubstitutions("explosion");
@ -751,7 +733,6 @@ void ShapeBaseData::packData(BitStream* stream)
if(stream->writeFlag(computeCRC)) if(stream->writeFlag(computeCRC))
stream->write(mCRC); stream->write(mCRC);
stream->writeFlag(shadowEnable);
stream->write(shadowSize); stream->write(shadowSize);
stream->write(shadowMaxVisibleDistance); stream->write(shadowMaxVisibleDistance);
stream->write(shadowProjectionDistance); stream->write(shadowProjectionDistance);
@ -829,7 +810,6 @@ void ShapeBaseData::unpackData(BitStream* stream)
if(computeCRC) if(computeCRC)
stream->read(&mCRC); stream->read(&mCRC);
shadowEnable = stream->readFlag();
stream->read(&shadowSize); stream->read(&shadowSize);
stream->read(&shadowMaxVisibleDistance); stream->read(&shadowMaxVisibleDistance);
stream->read(&shadowProjectionDistance); stream->read(&shadowProjectionDistance);

View file

@ -354,7 +354,6 @@ struct ShapeBaseImageData: public GameBaseData {
bool useRemainderDT; bool useRemainderDT;
// //
bool emap; ///< Environment mapping on?
bool correctMuzzleVector; ///< Adjust 1st person firing vector to eye's LOS point? bool correctMuzzleVector; ///< Adjust 1st person firing vector to eye's LOS point?
bool correctMuzzleVectorTP; ///< Adjust 3rd person firing vector to camera's LOS point? bool correctMuzzleVectorTP; ///< Adjust 3rd person firing vector to camera's LOS point?
bool firstPerson; ///< Render the image when in first person? bool firstPerson; ///< Render the image when in first person?
@ -542,7 +541,6 @@ public:
// TODO: These are only really used in Basic Lighting // TODO: These are only really used in Basic Lighting
// mode... we should probably move them somewhere else. // mode... we should probably move them somewhere else.
bool shadowEnable;
U32 shadowSize; U32 shadowSize;
F32 shadowMaxVisibleDistance; F32 shadowMaxVisibleDistance;
F32 shadowProjectionDistance; F32 shadowProjectionDistance;

View file

@ -166,8 +166,6 @@ static ShapeBaseImageData::StateData gDefaultStateData;
ShapeBaseImageData::ShapeBaseImageData() ShapeBaseImageData::ShapeBaseImageData()
{ {
emap = false;
mountPoint = 0; mountPoint = 0;
mountOffset.identity(); mountOffset.identity();
eyeOffset.identity(); eyeOffset.identity();
@ -631,18 +629,31 @@ S32 ShapeBaseImageData::lookupState(const char* name)
void ShapeBaseImageData::initPersistFields() void ShapeBaseImageData::initPersistFields()
{ {
addField( "emap", TypeBool, Offset(emap, ShapeBaseImageData), addGroup("Shapes");
"@brief Whether to enable environment mapping on this Image.\n\n" );
INITPERSISTFIELD_SHAPEASSET_ARRAY(Shape, MaxShapes, ShapeBaseImageData, "The shape asset to use for this image in the third person") INITPERSISTFIELD_SHAPEASSET_ARRAY(Shape, MaxShapes, ShapeBaseImageData, "The shape asset to use for this image in the third person")
//addProtectedField("shapeFileFP", TypeShapeFilename, Offset(mShapeName[1], ShapeBaseImageData), _setShapeData, defaultProtectedGetFn, "deprecated alias for ShapeFPFile/Asset", AbstractClassRep::FIELD_HideInInspectors); //addProtectedField("shapeFileFP", TypeShapeFilename, Offset(mShapeName[1], ShapeBaseImageData), _setShapeData, defaultProtectedGetFn, "deprecated alias for ShapeFPFile/Asset", AbstractClassRep::FIELD_HideInInspectors);
addField("casing", TYPEID< DebrisData >(), Offset(casing, ShapeBaseImageData),
"@brief DebrisData datablock to use for ejected casings.\n\n"
"@see stateEjectShell");
addField("shellExitDir", TypePoint3F, Offset(shellExitDir, ShapeBaseImageData),
"@brief Vector direction to eject shell casings.\n\n"
"@see casing");
addField("shellExitVariance", TypeF32, Offset(shellExitVariance, ShapeBaseImageData),
"@brief Variance (in degrees) from the shellExitDir vector to eject casings.\n\n"
"@see shellExitDir");
addField("shellVelocity", TypeF32, Offset(shellVelocity, ShapeBaseImageData),
"@brief Speed at which to eject casings.\n\n"
"@see casing");
addField("computeCRC", TypeBool, Offset(computeCRC, ShapeBaseImageData),
"If true, verify that the CRC of the client's Image matches the server's "
"CRC for the Image when loaded by the client.");
endGroup("Shapes");
addGroup("Animation");
addField( "imageAnimPrefix", TypeCaseString, Offset(imageAnimPrefix, ShapeBaseImageData), addField( "imageAnimPrefix", TypeCaseString, Offset(imageAnimPrefix, ShapeBaseImageData),
"@brief Passed along to the mounting shape to modify animation sequences played in third person. [optional]\n\n" ); "@brief Passed along to the mounting shape to modify animation sequences played in third person. [optional]\n\n" );
addField( "imageAnimPrefixFP", TypeCaseString, Offset(imageAnimPrefixFP, ShapeBaseImageData), addField( "imageAnimPrefixFP", TypeCaseString, Offset(imageAnimPrefixFP, ShapeBaseImageData),
"@brief Passed along to the mounting shape to modify animation sequences played in first person. [optional]\n\n" ); "@brief Passed along to the mounting shape to modify animation sequences played in first person. [optional]\n\n" );
addField( "animateAllShapes", TypeBool, Offset(animateAllShapes, ShapeBaseImageData), addField( "animateAllShapes", TypeBool, Offset(animateAllShapes, ShapeBaseImageData),
"@brief Indicates that all shapes should be animated in sync.\n\n" "@brief Indicates that all shapes should be animated in sync.\n\n"
"When multiple shapes are defined for this image datablock, each of them are automatically " "When multiple shapes are defined for this image datablock, each of them are automatically "
@ -655,7 +666,6 @@ void ShapeBaseImageData::initPersistFields()
"should be animated rather than all defined shapes. In those cases, this property is ignored.\n\n" "should be animated rather than all defined shapes. In those cases, this property is ignored.\n\n"
"@note This property is only important if you have more than one shape defined, such as shapeFileFP.\n\n" "@note This property is only important if you have more than one shape defined, such as shapeFileFP.\n\n"
"@see shapeFileFP\n"); "@see shapeFileFP\n");
addField( "animateOnServer", TypeBool, Offset(animateOnServer, ShapeBaseImageData), addField( "animateOnServer", TypeBool, Offset(animateOnServer, ShapeBaseImageData),
"@brief Indicates that the image should be animated on the server.\n\n" "@brief Indicates that the image should be animated on the server.\n\n"
"In most cases you'll want this set if you're using useEyeNode. You may also want to " "In most cases you'll want this set if you're using useEyeNode. You may also want to "
@ -672,7 +682,6 @@ void ShapeBaseImageData::initPersistFields()
"@note Setting this to true causes up to four animation threads to be advanced on the server " "@note Setting this to true causes up to four animation threads to be advanced on the server "
"for each instance in use, although for most images only one or two are actually defined.\n\n" "for each instance in use, although for most images only one or two are actually defined.\n\n"
"@see useEyeNode\n"); "@see useEyeNode\n");
addField( "scriptAnimTransitionTime", TypeF32, Offset(scriptAnimTransitionTime, ShapeBaseImageData), addField( "scriptAnimTransitionTime", TypeF32, Offset(scriptAnimTransitionTime, ShapeBaseImageData),
"@brief The amount of time to transition between the previous sequence and new sequence when the script prefix has changed.\n\n" "@brief The amount of time to transition between the previous sequence and new sequence when the script prefix has changed.\n\n"
"When setImageScriptAnimPrefix() is used on a ShapeBase that has this image mounted, the image " "When setImageScriptAnimPrefix() is used on a ShapeBase that has this image mounted, the image "
@ -680,43 +689,48 @@ void ShapeBaseImageData::initPersistFields()
"the amount of time it takes to transition from the previously playing animation sequence to" "the amount of time it takes to transition from the previously playing animation sequence to"
"the new script prefix-based animation sequence.\n" "the new script prefix-based animation sequence.\n"
"@see ShapeBase::setImageScriptAnimPrefix()"); "@see ShapeBase::setImageScriptAnimPrefix()");
addGroup("Animation");
addField( "projectile", TYPEID< ProjectileData >(), Offset(projectile, ShapeBaseImageData), addField( "projectile", TYPEID< ProjectileData >(), Offset(projectile, ShapeBaseImageData),
"@brief The projectile fired by this Image\n\n" ); "@brief The projectile fired by this Image\n\n" );
addField( "cloakable", TypeBool, Offset(cloakable, ShapeBaseImageData), addField( "cloakable", TypeBool, Offset(cloakable, ShapeBaseImageData),
"@brief Whether this Image can be cloaked.\n\n" "@brief Whether this Image can be cloaked.\n\n"
"Currently unused." ); "Currently unused." );
addField("usesEnergy", TypeBool, Offset(usesEnergy, ShapeBaseImageData),
"@brief Flag indicating whether this Image uses energy instead of ammo. The energy level comes from the ShapeBase object we're mounted to.\n\n"
"@see ShapeBase::setEnergyLevel()");
addField("minEnergy", TypeF32, Offset(minEnergy, ShapeBaseImageData),
"@brief Minimum Image energy for it to be operable.\n\n"
"@see usesEnergy");
addGroup("Mounting");
addField( "mountPoint", TypeS32, Offset(mountPoint, ShapeBaseImageData), addField( "mountPoint", TypeS32, Offset(mountPoint, ShapeBaseImageData),
"@brief Mount node # to mount this Image to.\n\n" "@brief Mount node # to mount this Image to.\n\n"
"This should correspond to a mount# node on the ShapeBase derived object we are mounting to." ); "This should correspond to a mount# node on the ShapeBase derived object we are mounting to." );
addField( "offset", TypeMatrixPosition, Offset(mountOffset, ShapeBaseImageData), addField( "offset", TypeMatrixPosition, Offset(mountOffset, ShapeBaseImageData),
"@brief \"X Y Z\" translation offset from this Image's <i>mountPoint</i> node to " "@brief \"X Y Z\" translation offset from this Image's <i>mountPoint</i> node to "
"attach to.\n\n" "attach to.\n\n"
"Defaults to \"0 0 0\". ie. attach this Image's " "Defaults to \"0 0 0\". ie. attach this Image's "
"<i>mountPoint</i> node to the ShapeBase model's mount# node without any offset.\n" "<i>mountPoint</i> node to the ShapeBase model's mount# node without any offset.\n"
"@see rotation"); "@see rotation");
addField( "rotation", TypeMatrixRotation, Offset(mountOffset, ShapeBaseImageData), addField( "rotation", TypeMatrixRotation, Offset(mountOffset, ShapeBaseImageData),
"@brief \"X Y Z ANGLE\" rotation offset from this Image's <i>mountPoint</i> node " "@brief \"X Y Z ANGLE\" rotation offset from this Image's <i>mountPoint</i> node "
"to attach to.\n\n" "to attach to.\n\n"
"Defaults to \"0 0 0\". ie. attach this Image's " "Defaults to \"0 0 0\". ie. attach this Image's "
"<i>mountPoint</i> node to the ShapeBase model's mount# node without any additional rotation.\n" "<i>mountPoint</i> node to the ShapeBase model's mount# node without any additional rotation.\n"
"@see offset"); "@see offset");
endGroup("Mounting");
addGroup("Camera");
addField( "eyeOffset", TypeMatrixPosition, Offset(eyeOffset, ShapeBaseImageData), addField( "eyeOffset", TypeMatrixPosition, Offset(eyeOffset, ShapeBaseImageData),
"@brief \"X Y Z\" translation offset from the ShapeBase model's eye node.\n\n" "@brief \"X Y Z\" translation offset from the ShapeBase model's eye node.\n\n"
"When in first person view, this is the offset from the eye node to place the gun. This " "When in first person view, this is the offset from the eye node to place the gun. This "
"gives the gun a fixed point in space, typical of a lot of FPS games.\n" "gives the gun a fixed point in space, typical of a lot of FPS games.\n"
"@see eyeRotation"); "@see eyeRotation");
addField( "eyeRotation", TypeMatrixRotation, Offset(eyeOffset, ShapeBaseImageData), addField( "eyeRotation", TypeMatrixRotation, Offset(eyeOffset, ShapeBaseImageData),
"@brief \"X Y Z ANGLE\" rotation offset from the ShapeBase model's eye node.\n\n" "@brief \"X Y Z ANGLE\" rotation offset from the ShapeBase model's eye node.\n\n"
"When in first person view, this is the rotation from the eye node to place the gun.\n" "When in first person view, this is the rotation from the eye node to place the gun.\n"
"@see eyeOffset"); "@see eyeOffset");
addField( "useEyeNode", TypeBool, Offset(useEyeNode, ShapeBaseImageData), addField( "useEyeNode", TypeBool, Offset(useEyeNode, ShapeBaseImageData),
"@brief Mount image using image's eyeMount node and place the camera at the image's eye node (or " "@brief Mount image using image's eyeMount node and place the camera at the image's eye node (or "
"at the eyeMount node if the eye node is missing).\n\n" "at the eyeMount node if the eye node is missing).\n\n"
@ -728,92 +742,62 @@ void ShapeBaseImageData::initPersistFields()
"@note Read about the animateOnServer field as you may want to set it to true if you're using useEyeNode.\n\n" "@note Read about the animateOnServer field as you may want to set it to true if you're using useEyeNode.\n\n"
"@see eyeOffset\n\n" "@see eyeOffset\n\n"
"@see animateOnServer\n\n"); "@see animateOnServer\n\n");
addField("firstPerson", TypeBool, Offset(firstPerson, ShapeBaseImageData),
"@brief Set to true to render the image in first person.");
endGroup("Camera");
addGroup("Camera Shake");
addField( "shakeCamera", TypeBool, Offset(shakeCamera, ShapeBaseImageData),
"@brief Flag indicating whether the camera should shake when this Image fires.\n\n" );
addField( "camShakeFreq", TypePoint3F, Offset(camShakeFreq, ShapeBaseImageData),
"@brief Frequency of the camera shaking effect.\n\n"
"@see shakeCamera" );
addField( "camShakeAmp", TypePoint3F, Offset(camShakeAmp, ShapeBaseImageData),
"@brief Amplitude of the camera shaking effect.\n\n"
"@see shakeCamera" );
addField( "camShakeDuration", TypeF32, Offset(camShakeDuration, ShapeBaseImageData),
"Duration (in seconds) to shake the camera." );
addField( "camShakeRadius", TypeF32, Offset(camShakeRadius, ShapeBaseImageData),
"Radial distance that a camera's position must be within relative to the "
"center of the explosion to be shaken." );
addField( "camShakeFalloff", TypeF32, Offset(camShakeFalloff, ShapeBaseImageData),
"Falloff value for the camera shake." );
endGroup("Camera Shake");
addGroup("Physics");
addField( "correctMuzzleVector", TypeBool, Offset(correctMuzzleVector, ShapeBaseImageData), addField( "correctMuzzleVector", TypeBool, Offset(correctMuzzleVector, ShapeBaseImageData),
"@brief Flag to adjust the aiming vector to the eye's LOS point when in 1st person view.\n\n" "@brief Flag to adjust the aiming vector to the eye's LOS point when in 1st person view.\n\n"
"@see ShapeBase::getMuzzleVector()" ); "@see ShapeBase::getMuzzleVector()" );
addField( "correctMuzzleVectorTP", TypeBool, Offset(correctMuzzleVectorTP, ShapeBaseImageData), addField( "correctMuzzleVectorTP", TypeBool, Offset(correctMuzzleVectorTP, ShapeBaseImageData),
"@brief Flag to adjust the aiming vector to the camera's LOS point when in 3rd person view.\n\n" "@brief Flag to adjust the aiming vector to the camera's LOS point when in 3rd person view.\n\n"
"@see ShapeBase::getMuzzleVector()" ); "@see ShapeBase::getMuzzleVector()" );
addField( "firstPerson", TypeBool, Offset(firstPerson, ShapeBaseImageData),
"@brief Set to true to render the image in first person." );
addField( "mass", TypeF32, Offset(mass, ShapeBaseImageData), addField( "mass", TypeF32, Offset(mass, ShapeBaseImageData),
"@brief Mass of this Image.\n\n" "@brief Mass of this Image.\n\n"
"This is added to the total mass of the ShapeBase object." ); "This is added to the total mass of the ShapeBase object." );
addField( "usesEnergy", TypeBool, Offset(usesEnergy,ShapeBaseImageData),
"@brief Flag indicating whether this Image uses energy instead of ammo. The energy level comes from the ShapeBase object we're mounted to.\n\n"
"@see ShapeBase::setEnergyLevel()");
addField( "minEnergy", TypeF32, Offset(minEnergy, ShapeBaseImageData),
"@brief Minimum Image energy for it to be operable.\n\n"
"@see usesEnergy");
addField( "accuFire", TypeBool, Offset(accuFire, ShapeBaseImageData), addField( "accuFire", TypeBool, Offset(accuFire, ShapeBaseImageData),
"@brief Flag to control whether the Image's aim is automatically converged with " "@brief Flag to control whether the Image's aim is automatically converged with "
"the crosshair.\n\n" "the crosshair.\n\n"
"Currently unused." ); "Currently unused." );
endGroup("Physics");
addGroup("Light Emitter");
addField( "lightType", TYPEID< ShapeBaseImageData::LightType >(), Offset(lightType, ShapeBaseImageData), addField( "lightType", TYPEID< ShapeBaseImageData::LightType >(), Offset(lightType, ShapeBaseImageData),
"@brief The type of light this Image emits.\n\n" "@brief The type of light this Image emits.\n\n"
"@see ShapeBaseImageLightType"); "@see ShapeBaseImageLightType");
addField( "lightColor", TypeColorF, Offset(lightColor, ShapeBaseImageData), addField( "lightColor", TypeColorF, Offset(lightColor, ShapeBaseImageData),
"@brief The color of light this Image emits.\n\n" "@brief The color of light this Image emits.\n\n"
"@see lightType"); "@see lightType");
addField( "lightDuration", TypeS32, Offset(lightDuration, ShapeBaseImageData), addField( "lightDuration", TypeS32, Offset(lightDuration, ShapeBaseImageData),
"@brief Duration in SimTime of Pulsing and WeaponFire type lights.\n\n" "@brief Duration in SimTime of Pulsing and WeaponFire type lights.\n\n"
"@see lightType"); "@see lightType");
addField( "lightRadius", TypeF32, Offset(lightRadius, ShapeBaseImageData), addField( "lightRadius", TypeF32, Offset(lightRadius, ShapeBaseImageData),
"@brief Radius of the light this Image emits.\n\n" "@brief Radius of the light this Image emits.\n\n"
"@see lightType"); "@see lightType");
addField( "lightBrightness", TypeF32, Offset(lightBrightness, ShapeBaseImageData), addField( "lightBrightness", TypeF32, Offset(lightBrightness, ShapeBaseImageData),
"@brief Brightness of the light this Image emits.\n\n" "@brief Brightness of the light this Image emits.\n\n"
"Only valid for WeaponFireLight." "Only valid for WeaponFireLight."
"@see lightType"); "@see lightType");
endGroup("Light Emitter");
addField( "shakeCamera", TypeBool, Offset(shakeCamera, ShapeBaseImageData),
"@brief Flag indicating whether the camera should shake when this Image fires.\n\n" );
addField( "camShakeFreq", TypePoint3F, Offset(camShakeFreq, ShapeBaseImageData),
"@brief Frequency of the camera shaking effect.\n\n"
"@see shakeCamera" );
addField( "camShakeAmp", TypePoint3F, Offset(camShakeAmp, ShapeBaseImageData),
"@brief Amplitude of the camera shaking effect.\n\n"
"@see shakeCamera" );
addField( "camShakeDuration", TypeF32, Offset(camShakeDuration, ShapeBaseImageData),
"Duration (in seconds) to shake the camera." );
addField( "camShakeRadius", TypeF32, Offset(camShakeRadius, ShapeBaseImageData),
"Radial distance that a camera's position must be within relative to the "
"center of the explosion to be shaken." );
addField( "camShakeFalloff", TypeF32, Offset(camShakeFalloff, ShapeBaseImageData),
"Falloff value for the camera shake." );
addField( "casing", TYPEID< DebrisData >(), Offset(casing, ShapeBaseImageData),
"@brief DebrisData datablock to use for ejected casings.\n\n"
"@see stateEjectShell" );
addField( "shellExitDir", TypePoint3F, Offset(shellExitDir, ShapeBaseImageData),
"@brief Vector direction to eject shell casings.\n\n"
"@see casing");
addField( "shellExitVariance", TypeF32, Offset(shellExitVariance, ShapeBaseImageData),
"@brief Variance (in degrees) from the shellExitDir vector to eject casings.\n\n"
"@see shellExitDir");
addField( "shellVelocity", TypeF32, Offset(shellVelocity, ShapeBaseImageData),
"@brief Speed at which to eject casings.\n\n"
"@see casing");
// State arrays // State arrays
addArray( "States", MaxStates ); addArray( "States", MaxStates );
@ -994,18 +978,17 @@ void ShapeBaseImageData::initPersistFields()
endArray( "States" ); endArray( "States" );
addField( "computeCRC", TypeBool, Offset(computeCRC, ShapeBaseImageData), addGroup("Sounds");
"If true, verify that the CRC of the client's Image matches the server's "
"CRC for the Image when loaded by the client." );
addField( "maxConcurrentSounds", TypeS32, Offset(maxConcurrentSounds, ShapeBaseImageData), addField( "maxConcurrentSounds", TypeS32, Offset(maxConcurrentSounds, ShapeBaseImageData),
"@brief Maximum number of sounds this Image can play at a time.\n\n" "@brief Maximum number of sounds this Image can play at a time.\n\n"
"Any value <= 0 indicates that it can play an infinite number of sounds." ); "Any value <= 0 indicates that it can play an infinite number of sounds." );
endGroup("Sounds");
addGroup("Animation");
addField( "useRemainderDT", TypeBool, Offset(useRemainderDT, ShapeBaseImageData), addField( "useRemainderDT", TypeBool, Offset(useRemainderDT, ShapeBaseImageData),
"@brief If true, allow multiple timeout transitions to occur within a single " "@brief If true, allow multiple timeout transitions to occur within a single "
"tick (useful if states have a very small timeout).\n\n" ); "tick (useful if states have a very small timeout).\n\n" );
endGroup("Animation");
Parent::initPersistFields(); Parent::initPersistFields();
} }

View file

@ -95,9 +95,6 @@ ConsoleDocClass( StaticShapeData,
StaticShapeData::StaticShapeData() StaticShapeData::StaticShapeData()
{ {
dynamicTypeField = 0; dynamicTypeField = 0;
shadowEnable = true;
noIndividualDamage = false; noIndividualDamage = false;
} }

View file

@ -176,11 +176,6 @@ FRangeValidator speedValidator(0.0f, AnimSpeedMax);
void TSStatic::initPersistFields() void TSStatic::initPersistFields()
{ {
addFieldV("AnimOffset", TypeF32, Offset(mAnimOffset, TSStatic), &percentValidator,
"Percent Animation Offset.");
addFieldV("AnimSpeed", TypeF32, Offset(mAnimSpeed, TSStatic), &speedValidator,
"Percent Animation Speed.");
addGroup("Shape"); addGroup("Shape");
INITPERSISTFIELD_SHAPEASSET(Shape, TSStatic, "Model to use for this TSStatic"); INITPERSISTFIELD_SHAPEASSET(Shape, TSStatic, "Model to use for this TSStatic");
@ -219,16 +214,21 @@ void TSStatic::initPersistFields()
"name as the new target.\n\n"); "name as the new target.\n\n");
endGroup("Materials"); endGroup("Materials");
addGroup("Rendering"); addGroup("Animation");
addField("playAmbient", TypeBool, Offset(mPlayAmbient, TSStatic), addField("playAmbient", TypeBool, Offset(mPlayAmbient, TSStatic),
"Enables automatic playing of the animation sequence named \"ambient\" (if it exists) when the TSStatic is loaded."); "Enables automatic playing of the animation sequence named \"ambient\" (if it exists) when the TSStatic is loaded.");
addFieldV("AnimOffset", TypeF32, Offset(mAnimOffset, TSStatic), &percentValidator,
"Percent Animation Offset.");
addFieldV("AnimSpeed", TypeF32, Offset(mAnimSpeed, TSStatic), &speedValidator,
"Percent Animation Speed.");
endGroup("Animation");
addGroup("Rendering");
addField("meshCulling", TypeBool, Offset(mMeshCulling, TSStatic), addField("meshCulling", TypeBool, Offset(mMeshCulling, TSStatic),
"Enables detailed culling of meshes within the TSStatic. Should only be used " "Enables detailed culling of meshes within the TSStatic. Should only be used "
"with large complex shapes like buildings which contain many submeshes."); "with large complex shapes like buildings which contain many submeshes.");
addField("originSort", TypeBool, Offset(mUseOriginSort, TSStatic), addField("originSort", TypeBool, Offset(mUseOriginSort, TSStatic),
"Enables translucent sorting of the TSStatic by its origin instead of the bounds."); "Enables translucent sorting of the TSStatic by its origin instead of the bounds.");
endGroup("Rendering"); endGroup("Rendering");
addGroup("Reflection"); addGroup("Reflection");

View file

@ -124,6 +124,7 @@ AITurretShapeData::AITurretShapeData()
void AITurretShapeData::initPersistFields() void AITurretShapeData::initPersistFields()
{ {
addGroup("AI Steering");
addField("maxScanHeading", TypeF32, Offset(maxScanHeading, AITurretShapeData), addField("maxScanHeading", TypeF32, Offset(maxScanHeading, AITurretShapeData),
"@brief Maximum number of degrees to scan left and right.\n\n" "@brief Maximum number of degrees to scan left and right.\n\n"
"@note Maximum scan heading is 90 degrees.\n"); "@note Maximum scan heading is 90 degrees.\n");
@ -134,24 +135,21 @@ void AITurretShapeData::initPersistFields()
"@brief Maximum distance to scan.\n\n" "@brief Maximum distance to scan.\n\n"
"When combined with maxScanHeading and maxScanPitch this forms a 3D scanning wedge used to initially " "When combined with maxScanHeading and maxScanPitch this forms a 3D scanning wedge used to initially "
"locate a target.\n"); "locate a target.\n");
addField("scanTickFrequency", TypeS32, Offset(scanTickFrequency, AITurretShapeData), addField("scanTickFrequency", TypeS32, Offset(scanTickFrequency, AITurretShapeData),
"@brief How often should we perform a full scan when looking for a target.\n\n" "@brief How often should we perform a full scan when looking for a target.\n\n"
"Expressed as the number of ticks between full scans, but no less than 1.\n"); "Expressed as the number of ticks between full scans, but no less than 1.\n");
addField("scanTickFrequencyVariance", TypeS32, Offset(scanTickFrequencyVariance, AITurretShapeData), addField("scanTickFrequencyVariance", TypeS32, Offset(scanTickFrequencyVariance, AITurretShapeData),
"@brief Random amount that should be added to the scan tick frequency each scan period.\n\n" "@brief Random amount that should be added to the scan tick frequency each scan period.\n\n"
"Expressed as the number of ticks to randomly add, but no less than zero.\n"); "Expressed as the number of ticks to randomly add, but no less than zero.\n");
addField("trackLostTargetTime", TypeF32, Offset(trackLostTargetTime, AITurretShapeData), addField("trackLostTargetTime", TypeF32, Offset(trackLostTargetTime, AITurretShapeData),
"@brief How long after the turret has lost the target should it still track it.\n\n" "@brief How long after the turret has lost the target should it still track it.\n\n"
"Expressed in seconds.\n"); "Expressed in seconds.\n");
addField("maxWeaponRange", TypeF32, Offset(maxWeaponRange, AITurretShapeData), addField("maxWeaponRange", TypeF32, Offset(maxWeaponRange, AITurretShapeData),
"@brief Maximum distance that the weapon will fire upon a target.\n\n"); "@brief Maximum distance that the weapon will fire upon a target.\n\n");
addField("weaponLeadVelocity", TypeF32, Offset(weaponLeadVelocity, AITurretShapeData), addField("weaponLeadVelocity", TypeF32, Offset(weaponLeadVelocity, AITurretShapeData),
"@brief Velocity used to lead target.\n\n" "@brief Velocity used to lead target.\n\n"
"If value <= 0, don't lead target.\n"); "If value <= 0, don't lead target.\n");
endGroup("AI Steering");
// State arrays // State arrays
addArray( "States", MaxStates ); addArray( "States", MaxStates );

View file

@ -87,8 +87,6 @@ TurretShapeData::TurretShapeData()
{ {
weaponLinkType = FireTogether; weaponLinkType = FireTogether;
shadowEnable = true;
zRotOnly = false; zRotOnly = false;
startLoaded = true; startLoaded = true;
@ -133,26 +131,11 @@ TurretShapeData::TurretShapeData()
void TurretShapeData::initPersistFields() void TurretShapeData::initPersistFields()
{ {
addGroup("Steering");
addField("zRotOnly", TypeBool, Offset(zRotOnly, TurretShapeData), addField("zRotOnly", TypeBool, Offset(zRotOnly, TurretShapeData),
"@brief Should the turret allow only z rotations.\n\n" "@brief Should the turret allow only z rotations.\n\n"
"True indicates that the turret may only be rotated on its z axis, just like the Item class. " "True indicates that the turret may only be rotated on its z axis, just like the Item class. "
"This keeps the turret always upright regardless of the surface it lands on.\n"); "This keeps the turret always upright regardless of the surface it lands on.\n");
addField( "weaponLinkType", TYPEID< TurretShapeData::FireLinkType >(), Offset(weaponLinkType, TurretShapeData),
"@brief Set how the mounted weapons are linked and triggered.\n\n"
"<ul><li>FireTogether: All weapons fire under trigger 0.</li>"
"<li>GroupedFire: Weapon mounts 0,2 fire under trigger 0, mounts 1,3 fire under trigger 1.</li>"
"<li>IndividualFire: Each weapon mount fires under its own trigger 0-3.</li></ul>\n"
"@see TurretShapeFireLinkType");
addField("startLoaded", TypeBool, Offset(startLoaded, TurretShapeData),
"@brief Does the turret's mounted weapon(s) start in a loaded state.\n\n"
"True indicates that all mounted weapons start in a loaded state.\n"
"@see ShapeBase::setImageLoaded()");
addField("cameraOffset", TypeF32, Offset(cameraOffset, TurretShapeData),
"Vertical (Z axis) height of the camera above the turret." );
addField("maxHeading", TypeF32, Offset(maxHeading, TurretShapeData), addField("maxHeading", TypeF32, Offset(maxHeading, TurretShapeData),
"@brief Maximum number of degrees to rotate from center.\n\n" "@brief Maximum number of degrees to rotate from center.\n\n"
"A value of 180 or more degrees indicates the turret may rotate completely around.\n"); "A value of 180 or more degrees indicates the turret may rotate completely around.\n");
@ -160,13 +143,32 @@ void TurretShapeData::initPersistFields()
"@brief Minimum number of degrees to rotate down from straight ahead.\n\n"); "@brief Minimum number of degrees to rotate down from straight ahead.\n\n");
addField("maxPitch", TypeF32, Offset(maxPitch, TurretShapeData), addField("maxPitch", TypeF32, Offset(maxPitch, TurretShapeData),
"@brief Maximum number of degrees to rotate up from straight ahead.\n\n"); "@brief Maximum number of degrees to rotate up from straight ahead.\n\n");
addField("headingRate", TypeF32, Offset(headingRate, TurretShapeData), addField("headingRate", TypeF32, Offset(headingRate, TurretShapeData),
"@brief Degrees per second rotation.\n\n" "@brief Degrees per second rotation.\n\n"
"A value of 0 means no rotation is allowed. A value less than 0 means the rotation is instantaneous.\n"); "A value of 0 means no rotation is allowed. A value less than 0 means the rotation is instantaneous.\n");
addField("pitchRate", TypeF32, Offset(pitchRate, TurretShapeData), addField("pitchRate", TypeF32, Offset(pitchRate, TurretShapeData),
"@brief Degrees per second rotation.\n\n" "@brief Degrees per second rotation.\n\n"
"A value of 0 means no rotation is allowed. A value less than 0 means the rotation is instantaneous.\n"); "A value of 0 means no rotation is allowed. A value less than 0 means the rotation is instantaneous.\n");
endGroup("Steering");
addGroup("Weapon State");
addField( "weaponLinkType", TYPEID< TurretShapeData::FireLinkType >(), Offset(weaponLinkType, TurretShapeData),
"@brief Set how the mounted weapons are linked and triggered.\n\n"
"<ul><li>FireTogether: All weapons fire under trigger 0.</li>"
"<li>GroupedFire: Weapon mounts 0,2 fire under trigger 0, mounts 1,3 fire under trigger 1.</li>"
"<li>IndividualFire: Each weapon mount fires under its own trigger 0-3.</li></ul>\n"
"@see TurretShapeFireLinkType");
addField("startLoaded", TypeBool, Offset(startLoaded, TurretShapeData),
"@brief Does the turret's mounted weapon(s) start in a loaded state.\n\n"
"True indicates that all mounted weapons start in a loaded state.\n"
"@see ShapeBase::setImageLoaded()");
endGroup("Weapon State");
addGroup("Camera", "The settings used by the shape when it is the camera.");
addField("cameraOffset", TypeF32, Offset(cameraOffset, TurretShapeData),
"Vertical (Z axis) height of the camera above the turret." );
endGroup("Camera");
Parent::initPersistFields(); Parent::initPersistFields();
} }

View file

@ -50,6 +50,15 @@ const static U32 sCollisionMoveMask = ( TerrainObjectType | WaterObjectType
static U32 sServerCollisionMask = sCollisionMoveMask; // ItemObjectType static U32 sServerCollisionMask = sCollisionMoveMask; // ItemObjectType
static U32 sClientCollisionMask = sCollisionMoveMask; static U32 sClientCollisionMask = sCollisionMoveMask;
typedef FlyingVehicleData::Sounds engineSounds;
DefineEnumType(engineSounds);
ImplementEnumType(engineSounds, "enum types.\n"
"@ingroup VehicleData\n\n")
{ engineSounds::JetSound, "JetSound", "..." },
{ engineSounds::EngineSound, "EngineSound", "..." },
EndImplementEnumType;
// //
const char* FlyingVehicle::sJetSequence[FlyingVehicle::JetAnimCount] = const char* FlyingVehicle::sJetSequence[FlyingVehicle::JetAnimCount] =
{ {
@ -166,15 +175,27 @@ bool FlyingVehicleData::preload(bool server, String &errorStr)
void FlyingVehicleData::initPersistFields() void FlyingVehicleData::initPersistFields()
{ {
addGroup("Physics");
INITPERSISTFIELD_SOUNDASSET_ARRAY(FlyingSounds, Sounds::MaxSounds, FlyingVehicleData, "Sounds for flying vehicle"); addField( "rollForce", TypeF32, Offset(rollForce, FlyingVehicleData),
"@brief Damping torque against rolling maneuvers (rotation about the y-axis), "
addField( "maneuveringForce", TypeF32, Offset(maneuveringForce, FlyingVehicleData), "proportional to linear velocity.\n\n"
"@brief Maximum X and Y (horizontal plane) maneuvering force.\n\n" "Acts to adjust roll to a stable position over time as the vehicle moves." );
"The actual force applied depends on the current thrust." ); addField( "rotationalDrag", TypeF32, Offset(rotationalDrag, FlyingVehicleData),
"Rotational drag factor (slows vehicle rotation speed in all axes)." );
addField( "horizontalSurfaceForce", TypeF32, Offset(horizontalSurfaceForce, FlyingVehicleData), addField( "horizontalSurfaceForce", TypeF32, Offset(horizontalSurfaceForce, FlyingVehicleData),
"@brief Damping force in the opposite direction to sideways velocity.\n\n" "@brief Damping force in the opposite direction to sideways velocity.\n\n"
"Provides \"bite\" into the wind for climbing/diving and turning)." ); "Provides \"bite\" into the wind for climbing/diving and turning)." );
addField( "hoverHeight", TypeF32, Offset(hoverHeight, FlyingVehicleData),
"The vehicle's height off the ground when at rest." );
addField( "createHoverHeight", TypeF32, Offset(createHoverHeight, FlyingVehicleData),
"@brief The vehicle's height off the ground when useCreateHeight is active.\n\n"
"This can help avoid problems with spawning the vehicle." );
endGroup("Physics");
addGroup("Steering");
addField( "maneuveringForce", TypeF32, Offset(maneuveringForce, FlyingVehicleData),
"@brief Maximum X and Y (horizontal plane) maneuvering force.\n\n"
"The actual force applied depends on the current thrust." );
addField( "verticalSurfaceForce", TypeF32, Offset(verticalSurfaceForce, FlyingVehicleData), addField( "verticalSurfaceForce", TypeF32, Offset(verticalSurfaceForce, FlyingVehicleData),
"@brief Damping force in the opposite direction to vertical velocity.\n\n" "@brief Damping force in the opposite direction to vertical velocity.\n\n"
"Controls side slip; lower numbers give more slide." ); "Controls side slip; lower numbers give more slide." );
@ -186,13 +207,9 @@ void FlyingVehicleData::initPersistFields()
addField( "steeringRollForce", TypeF32, Offset(steeringRollForce, FlyingVehicleData), addField( "steeringRollForce", TypeF32, Offset(steeringRollForce, FlyingVehicleData),
"Roll force induced by sideways steering input value (controls how much " "Roll force induced by sideways steering input value (controls how much "
"the vehicle rolls when turning)." ); "the vehicle rolls when turning)." );
addField( "rollForce", TypeF32, Offset(rollForce, FlyingVehicleData), endGroup("Steering");
"@brief Damping torque against rolling maneuvers (rotation about the y-axis), "
"proportional to linear velocity.\n\n"
"Acts to adjust roll to a stable position over time as the vehicle moves." );
addField( "rotationalDrag", TypeF32, Offset(rotationalDrag, FlyingVehicleData),
"Rotational drag factor (slows vehicle rotation speed in all axes)." );
addGroup("AutoCorrection");
addField( "maxAutoSpeed", TypeF32, Offset(maxAutoSpeed, FlyingVehicleData), addField( "maxAutoSpeed", TypeF32, Offset(maxAutoSpeed, FlyingVehicleData),
"Maximum speed for automatic vehicle control assistance - vehicles " "Maximum speed for automatic vehicle control assistance - vehicles "
"travelling at speeds above this value do not get control assitance." ); "travelling at speeds above this value do not get control assitance." );
@ -208,13 +225,9 @@ void FlyingVehicleData::initPersistFields()
"@brief Corrective torque applied to level out the vehicle when moving at less " "@brief Corrective torque applied to level out the vehicle when moving at less "
"than maxAutoSpeed.\n\n" "than maxAutoSpeed.\n\n"
"The torque is inversely proportional to vehicle speed." ); "The torque is inversely proportional to vehicle speed." );
endGroup("AutoCorrection");
addField( "hoverHeight", TypeF32, Offset(hoverHeight, FlyingVehicleData), addGroup("Particle Effects");
"The vehicle's height off the ground when at rest." );
addField( "createHoverHeight", TypeF32, Offset(createHoverHeight, FlyingVehicleData),
"@brief The vehicle's height off the ground when useCreateHeight is active.\n\n"
"This can help avoid problems with spawning the vehicle." );
addField( "forwardJetEmitter",TYPEID< ParticleEmitterData >(), Offset(jetEmitter[ForwardJetEmitter], FlyingVehicleData), addField( "forwardJetEmitter",TYPEID< ParticleEmitterData >(), Offset(jetEmitter[ForwardJetEmitter], FlyingVehicleData),
"@brief Emitter to generate particles for forward jet thrust.\n\n" "@brief Emitter to generate particles for forward jet thrust.\n\n"
"Forward jet thrust particles are emitted from model nodes JetNozzle0 " "Forward jet thrust particles are emitted from model nodes JetNozzle0 "
@ -231,7 +244,11 @@ void FlyingVehicleData::initPersistFields()
"Emitter to generate contrail particles from model nodes contrail0 - contrail3." ); "Emitter to generate contrail particles from model nodes contrail0 - contrail3." );
addField( "minTrailSpeed", TypeF32, Offset(minTrailSpeed, FlyingVehicleData), addField( "minTrailSpeed", TypeF32, Offset(minTrailSpeed, FlyingVehicleData),
"Minimum speed at which to start generating contrail particles." ); "Minimum speed at which to start generating contrail particles." );
endGroup("Particle Effects");
addGroup("Sounds");
INITPERSISTFIELD_SOUNDASSET_ENUMED(FlyingSounds, engineSounds, Sounds::MaxSounds, FlyingVehicleData, "EngineSounds.");
endGroup("Sounds");
Parent::initPersistFields(); Parent::initPersistFields();
} }
@ -404,8 +421,17 @@ void FlyingVehicle::onRemove()
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void FlyingVehicle::interpolateTick(F32 dt)
{
PROFILE_SCOPE(FlyingVehicle_InterpolateTick);
Parent::interpolateTick(dt);
updateEngineSound(1);
updateJet(dt);
}
void FlyingVehicle::advanceTime(F32 dt) void FlyingVehicle::advanceTime(F32 dt)
{ {
PROFILE_SCOPE(FlyingVehicle_AdvanceTime);
Parent::advanceTime(dt); Parent::advanceTime(dt);
updateEngineSound(1); updateEngineSound(1);

View file

@ -187,6 +187,7 @@ class FlyingVehicle: public Vehicle
bool onAdd(); bool onAdd();
void onRemove(); void onRemove();
void interpolateTick(F32 dt);
void advanceTime(F32 dt); void advanceTime(F32 dt);
void writePacketData(GameConnection *conn, BitStream *stream); void writePacketData(GameConnection *conn, BitStream *stream);

View file

@ -174,20 +174,52 @@ HoverVehicleData::~HoverVehicleData()
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
void HoverVehicleData::initPersistFields() void HoverVehicleData::initPersistFields()
{ {
addField( "dragForce", TypeF32, Offset(dragForce, HoverVehicleData), addGroup("Physics");
"Drag force factor that acts opposite to the vehicle velocity.\nAlso " addField( "normalForce", TypeF32, Offset(normalForce, HoverVehicleData),
"used to determnine the vehicle's maxThrustSpeed.\n@see mainThrustForce" ); "Force generated in the ground normal direction when the vehicle is not "
addField( "vertFactor", TypeF32, Offset(vertFactor, HoverVehicleData), "floating (within stabalizer length from the ground).\n\n"
"@see stabLenMin" );
addField( "stabLenMin", TypeF32, Offset(stabLenMin, HoverVehicleData),
"Length of the base stabalizer when travelling at minimum speed (0).\n"
"Each tick, the vehicle performs 2 raycasts (from the center back and "
"center front of the vehicle) to check for contact with the ground. The "
"base stabalizer length determines the length of that raycast; if "
"neither raycast hit the ground, the vehicle is floating, stabalizer "
"spring and ground normal forces are not applied.\n\n"
"<img src=\"images/hoverVehicle_forces.png\">\n"
"@see stabSpringConstant" );
addField( "stabLenMax", TypeF32, Offset(stabLenMax, HoverVehicleData),
"Length of the base stabalizer when travelling at maximum speed "
"(maxThrustSpeed).\n\n@see stabLenMin\n\n@see mainThrustForce" );
addField("vertFactor", TypeF32, Offset(vertFactor, HoverVehicleData),
"Scalar applied to the vertical portion of the velocity drag acting on " "Scalar applied to the vertical portion of the velocity drag acting on "
"the vehicle.\nFor the horizontal (X and Y) components of velocity drag, " "the vehicle.\nFor the horizontal (X and Y) components of velocity drag, "
"a factor of 0.25 is applied when the vehicle is floating, and a factor " "a factor of 0.25 is applied when the vehicle is floating, and a factor "
"of 1.0 is applied when the vehicle is not floating. This velocity drag " "of 1.0 is applied when the vehicle is not floating. This velocity drag "
"is multiplied by the vehicle's dragForce, as defined above, and the " "is multiplied by the vehicle's dragForce, as defined above, and the "
"result is subtracted from it's movement force.\n" "result is subtracted from it's movement force.\n"
"@note The vertFactor must be between 0.0 and 1.0 (inclusive)." ); "@note The vertFactor must be between 0.0 and 1.0 (inclusive).");
addField( "floatingThrustFactor", TypeF32, Offset(floatingThrustFactor, HoverVehicleData), addField("stabSpringConstant", TypeF32, Offset(stabSpringConstant, HoverVehicleData),
"Scalar applied to the vehicle's thrust force when the vehicle is floating.\n" "Value used to generate stabalizer spring force. The force generated "
"@note The floatingThrustFactor must be between 0.0 and 1.0 (inclusive)." ); "depends on stabilizer compression, that is how close the vehicle is "
"to the ground proportional to current stabalizer length.\n\n"
"@see stabLenMin");
addField("stabDampingConstant", TypeF32, Offset(stabDampingConstant, HoverVehicleData),
"Damping spring force acting against changes in the stabalizer length.\n\n"
"@see stabLenMin");
endGroup("Physics");
addGroup("Steering");
addField( "steeringForce", TypeF32, Offset(steeringForce, HoverVehicleData),
"Yaw (rotation about the Z-axis) force applied when steering in the x-axis direction."
"about the vehicle's Z-axis)" );
addField( "rollForce", TypeF32, Offset(rollForce, HoverVehicleData),
"Roll (rotation about the Y-axis) force applied when steering in the x-axis direction." );
addField( "pitchForce", TypeF32, Offset(pitchForce, HoverVehicleData),
"Pitch (rotation about the X-axis) force applied when steering in the y-axis direction." );
addField( "dragForce", TypeF32, Offset(dragForce, HoverVehicleData),
"Drag force factor that acts opposite to the vehicle velocity.\nAlso "
"used to determnine the vehicle's maxThrustSpeed.\n@see mainThrustForce" );
addField( "mainThrustForce", TypeF32, Offset(mainThrustForce, HoverVehicleData), addField( "mainThrustForce", TypeF32, Offset(mainThrustForce, HoverVehicleData),
"Force generated by thrusting the vehicle forward.\nAlso used to determine " "Force generated by thrusting the vehicle forward.\nAlso used to determine "
"the maxThrustSpeed:\n\n" "the maxThrustSpeed:\n\n"
@ -201,52 +233,27 @@ void HoverVehicleData::initPersistFields()
"determine the vehicle's maxThrustSpeed.\n@see mainThrustForce" ); "determine the vehicle's maxThrustSpeed.\n@see mainThrustForce" );
addField( "turboFactor", TypeF32, Offset(turboFactor, HoverVehicleData), addField( "turboFactor", TypeF32, Offset(turboFactor, HoverVehicleData),
"Scale factor applied to the vehicle's thrust force when jetting." ); "Scale factor applied to the vehicle's thrust force when jetting." );
addField( "floatingThrustFactor", TypeF32, Offset(floatingThrustFactor, HoverVehicleData),
"Scalar applied to the vehicle's thrust force when the vehicle is floating.\n"
"@note The floatingThrustFactor must be between 0.0 and 1.0 (inclusive)." );
endGroup("Steering");
addField( "stabLenMin", TypeF32, Offset(stabLenMin, HoverVehicleData), addGroup("AutoCorrection");
"Length of the base stabalizer when travelling at minimum speed (0).\n"
"Each tick, the vehicle performs 2 raycasts (from the center back and "
"center front of the vehicle) to check for contact with the ground. The "
"base stabalizer length determines the length of that raycast; if "
"neither raycast hit the ground, the vehicle is floating, stabalizer "
"spring and ground normal forces are not applied.\n\n"
"<img src=\"images/hoverVehicle_forces.png\">\n"
"@see stabSpringConstant" );
addField( "stabLenMax", TypeF32, Offset(stabLenMax, HoverVehicleData),
"Length of the base stabalizer when travelling at maximum speed "
"(maxThrustSpeed).\n\n@see stabLenMin\n\n@see mainThrustForce" );
addField( "stabSpringConstant", TypeF32, Offset(stabSpringConstant, HoverVehicleData),
"Value used to generate stabalizer spring force. The force generated "
"depends on stabilizer compression, that is how close the vehicle is "
"to the ground proportional to current stabalizer length.\n\n"
"@see stabLenMin" );
addField( "stabDampingConstant", TypeF32, Offset(stabDampingConstant, HoverVehicleData),
"Damping spring force acting against changes in the stabalizer length.\n\n"
"@see stabLenMin" );
addField( "gyroDrag", TypeF32, Offset(gyroDrag, HoverVehicleData), addField( "gyroDrag", TypeF32, Offset(gyroDrag, HoverVehicleData),
"Damping torque that acts against the vehicle's current angular momentum." ); "Damping torque that acts against the vehicle's current angular momentum." );
addField( "normalForce", TypeF32, Offset(normalForce, HoverVehicleData),
"Force generated in the ground normal direction when the vehicle is not "
"floating (within stabalizer length from the ground).\n\n"
"@see stabLenMin" );
addField( "restorativeForce", TypeF32, Offset(restorativeForce, HoverVehicleData), addField( "restorativeForce", TypeF32, Offset(restorativeForce, HoverVehicleData),
"Force generated to stabalize the vehicle (return it to neutral pitch/roll) " "Force generated to stabalize the vehicle (return it to neutral pitch/roll) "
"when the vehicle is floating (more than stabalizer length from the " "when the vehicle is floating (more than stabalizer length from the "
"ground.\n\n@see stabLenMin" ); "ground.\n\n@see stabLenMin" );
addField( "steeringForce", TypeF32, Offset(steeringForce, HoverVehicleData), endGroup("AutoCorrection");
"Yaw (rotation about the Z-axis) force applied when steering in the x-axis direction."
"about the vehicle's Z-axis)" );
addField( "rollForce", TypeF32, Offset(rollForce, HoverVehicleData),
"Roll (rotation about the Y-axis) force applied when steering in the x-axis direction." );
addField( "pitchForce", TypeF32, Offset(pitchForce, HoverVehicleData),
"Pitch (rotation about the X-axis) force applied when steering in the y-axis direction." );
INITPERSISTFIELD_SOUNDASSET_ENUMED(HoverSounds, hoverSoundsEnum, Sounds::MaxSounds, HoverVehicleData, "Sounds for hover vehicle.");
addGroup("Particle Effects");
addField( "dustTrailEmitter", TYPEID< ParticleEmitterData >(), Offset(dustTrailEmitter, HoverVehicleData), addField( "dustTrailEmitter", TYPEID< ParticleEmitterData >(), Offset(dustTrailEmitter, HoverVehicleData),
"Emitter to generate particles for the vehicle's dust trail.\nThe trail " "Emitter to generate particles for the vehicle's dust trail.\nThe trail "
"of dust particles is generated only while the vehicle is moving." ); "of dust particles is generated only while the vehicle is moving." );
addField( "forwardJetEmitter", TYPEID< ParticleEmitterData >(), Offset(jetEmitter[ForwardJetEmitter], HoverVehicleData),
"Emitter to generate particles for forward jet thrust.\nForward jet "
"thrust particles are emitted from model nodes JetNozzle0 and JetNozzle1." );
addField( "dustTrailOffset", TypePoint3F, Offset(dustTrailOffset, HoverVehicleData), addField( "dustTrailOffset", TypePoint3F, Offset(dustTrailOffset, HoverVehicleData),
"\"X Y Z\" offset from the vehicle's origin from which to generate dust " "\"X Y Z\" offset from the vehicle's origin from which to generate dust "
"trail particles.\nBy default particles are emitted directly beneath the " "trail particles.\nBy default particles are emitted directly beneath the "
@ -261,21 +268,13 @@ void HoverVehicleData::initPersistFields()
"vehicle's speed is divided by this value to determine how many particles " "vehicle's speed is divided by this value to determine how many particles "
"to generate each frame. Lower values give a more dense trail, higher " "to generate each frame. Lower values give a more dense trail, higher "
"values a more sparse trail." ); "values a more sparse trail." );
endGroup("Sounds");
addGroup("Particle Effects");
INITPERSISTFIELD_SOUNDASSET_ENUMED(HoverSounds, hoverSoundsEnum, Sounds::MaxSounds, HoverVehicleData, "Sounds for hover vehicle.");
endGroup("Sounds");
addField( "floatingGravMag", TypeF32, Offset(floatingGravMag, HoverVehicleData),
"Scale factor applied to the vehicle gravitational force when the vehicle "
"is floating.\n\n@see stabLenMin" );
addField( "brakingForce", TypeF32, Offset(brakingForce, HoverVehicleData),
"Force generated by braking.\nThe vehicle is considered to be braking if "
"it is moving, but the throttle is off, and no left or right thrust is "
"being applied. This force is only applied when the vehicle's velocity is "
"less than brakingActivationSpeed." );
addField( "brakingActivationSpeed", TypeF32, Offset(brakingActivationSpeed, HoverVehicleData),
"Maximum speed below which a braking force is applied.\n\n@see brakingForce" );
addField( "forwardJetEmitter", TYPEID< ParticleEmitterData >(), Offset(jetEmitter[ForwardJetEmitter], HoverVehicleData),
"Emitter to generate particles for forward jet thrust.\nForward jet "
"thrust particles are emitted from model nodes JetNozzle0 and JetNozzle1." );
Parent::initPersistFields(); Parent::initPersistFields();
} }

View file

@ -127,7 +127,6 @@ ConsoleDocClass( VehicleData,
VehicleData::VehicleData() VehicleData::VehicleData()
{ {
shadowEnable = true;
shadowSize = 256; shadowSize = 256;
shadowProjectionDistance = 14.0f; shadowProjectionDistance = 14.0f;
maxSteeringAngle = M_PI_F/4.0f; // 45 deg. maxSteeringAngle = M_PI_F/4.0f; // 45 deg.
@ -280,6 +279,15 @@ void VehicleData::initPersistFields()
"@brief Creates a representation of the object in the physics plugin.\n"); "@brief Creates a representation of the object in the physics plugin.\n");
endGroup("Physics"); endGroup("Physics");
addGroup("Collision");
addField( "collDamageThresholdVel", TypeF32, Offset(collDamageThresholdVel, VehicleData),
"Minimum collision velocity to cause damage to this vehicle.\nCurrently unused." );
addField( "collDamageMultiplier", TypeF32, Offset(collDamageMultiplier, VehicleData),
"@brief Damage to this vehicle after a collision (multiplied by collision "
"velocity).\n\nCurrently unused." );
endGroup("Collision");
addGroup("Steering");
addField( "jetForce", TypeF32, Offset(jetForce, VehicleData), addField( "jetForce", TypeF32, Offset(jetForce, VehicleData),
"@brief Additional force applied to the vehicle when it is jetting.\n\n" "@brief Additional force applied to the vehicle when it is jetting.\n\n"
"For WheeledVehicles, the force is applied in the forward direction. For " "For WheeledVehicles, the force is applied in the forward direction. For "
@ -289,16 +297,20 @@ void VehicleData::initPersistFields()
"Once the vehicle's energy level reaches 0, it will no longer be able to jet." ); "Once the vehicle's energy level reaches 0, it will no longer be able to jet." );
addField( "minJetEnergy", TypeF32, Offset(minJetEnergy, VehicleData), addField( "minJetEnergy", TypeF32, Offset(minJetEnergy, VehicleData),
"Minimum vehicle energy level to begin jetting." ); "Minimum vehicle energy level to begin jetting." );
addField( "maxSteeringAngle", TypeF32, Offset(maxSteeringAngle, VehicleData),
"Maximum yaw (horizontal) and pitch (vertical) steering angle in radians." );
endGroup("Steering");
addGroup("AutoCorrection");
addField( "powerSteering", TypeBool, Offset(powerSteering, VehicleData),
"If true, steering does not auto-centre while the vehicle is being steered by its driver." );
addField( "steeringReturn", TypeF32, Offset(steeringReturn, VehicleData), addField( "steeringReturn", TypeF32, Offset(steeringReturn, VehicleData),
"Rate at which the vehicle's steering returns to forwards when it is moving." ); "Rate at which the vehicle's steering returns to forwards when it is moving." );
addField( "steeringReturnSpeedScale", TypeF32, Offset(steeringReturnSpeedScale, VehicleData), addField( "steeringReturnSpeedScale", TypeF32, Offset(steeringReturnSpeedScale, VehicleData),
"Amount of effect the vehicle's speed has on its rate of steering return." ); "Amount of effect the vehicle's speed has on its rate of steering return." );
addField( "powerSteering", TypeBool, Offset(powerSteering, VehicleData), endGroup("AutoCorrection");
"If true, steering does not auto-centre while the vehicle is being steered by its driver." );
addField( "maxSteeringAngle", TypeF32, Offset(maxSteeringAngle, VehicleData),
"Maximum yaw (horizontal) and pitch (vertical) steering angle in radians." );
addGroup("Particle Effects");
addField( "damageEmitter", TYPEID< ParticleEmitterData >(), Offset(damageEmitterList, VehicleData), VC_NUM_DAMAGE_EMITTERS, addField( "damageEmitter", TYPEID< ParticleEmitterData >(), Offset(damageEmitterList, VehicleData), VC_NUM_DAMAGE_EMITTERS,
"@brief Array of particle emitters used to generate damage (dust, smoke etc) " "@brief Array of particle emitters used to generate damage (dust, smoke etc) "
"effects.\n\n" "effects.\n\n"
@ -326,11 +338,7 @@ void VehicleData::initPersistFields()
addField( "numDmgEmitterAreas", TypeF32, Offset(numDmgEmitterAreas, VehicleData), addField( "numDmgEmitterAreas", TypeF32, Offset(numDmgEmitterAreas, VehicleData),
"Number of damageEmitterOffset values to use for each damageEmitter.\n\n" "Number of damageEmitterOffset values to use for each damageEmitter.\n\n"
"@see damageEmitterOffset" ); "@see damageEmitterOffset" );
addField( "collDamageThresholdVel", TypeF32, Offset(collDamageThresholdVel, VehicleData), endGroup("Particle Effects");
"Minimum collision velocity to cause damage to this vehicle.\nCurrently unused." );
addField( "collDamageMultiplier", TypeF32, Offset(collDamageMultiplier, VehicleData),
"@brief Damage to this vehicle after a collision (multiplied by collision "
"velocity).\n\nCurrently unused." );
Parent::initPersistFields(); Parent::initPersistFields();
} }

View file

@ -448,13 +448,7 @@ bool WheeledVehicleData::mirrorWheel(Wheel* we)
void WheeledVehicleData::initPersistFields() void WheeledVehicleData::initPersistFields()
{ {
addGroup("Sounds"); addGroup("Steering");
INITPERSISTFIELD_SOUNDASSET_ENUMED(WheeledVehicleSounds, WheeledVehicleSoundsEnum, MaxSounds, WheeledVehicleData, "Sounds related to wheeled vehicle.");
endGroup("Sounds");
addField("tireEmitter",TYPEID< ParticleEmitterData >(), Offset(tireEmitter, WheeledVehicleData),
"ParticleEmitterData datablock used to generate particles from each wheel "
"when the vehicle is moving and the wheel is in contact with the ground.");
addField("maxWheelSpeed", TypeF32, Offset(maxWheelSpeed, WheeledVehicleData), addField("maxWheelSpeed", TypeF32, Offset(maxWheelSpeed, WheeledVehicleData),
"@brief Maximum linear velocity of each wheel.\n\n" "@brief Maximum linear velocity of each wheel.\n\n"
"This caps the maximum speed of the vehicle." ); "This caps the maximum speed of the vehicle." );
@ -468,6 +462,17 @@ void WheeledVehicleData::initPersistFields()
addField("brakeTorque", TypeF32, Offset(brakeTorque, WheeledVehicleData), addField("brakeTorque", TypeF32, Offset(brakeTorque, WheeledVehicleData),
"@brief Torque applied when braking.\n\n" "@brief Torque applied when braking.\n\n"
"This controls how fast the vehicle will stop when the brakes are applied." ); "This controls how fast the vehicle will stop when the brakes are applied." );
endGroup("Steering");
addGroup("Particle Effects");
addField("tireEmitter",TYPEID< ParticleEmitterData >(), Offset(tireEmitter, WheeledVehicleData),
"ParticleEmitterData datablock used to generate particles from each wheel "
"when the vehicle is moving and the wheel is in contact with the ground.");
endGroup("Particle Effects");
addGroup("Sounds");
INITPERSISTFIELD_SOUNDASSET_ENUMED(WheeledVehicleSounds, WheeledVehicleSoundsEnum, MaxSounds, WheeledVehicleData, "Sounds related to wheeled vehicle.");
endGroup("Sounds");
Parent::initPersistFields(); Parent::initPersistFields();
} }

View file

@ -35,7 +35,6 @@ VActorData::VActorData( void ) :
mSubmergeCoverage( 0.25f ) mSubmergeCoverage( 0.25f )
{ {
// Setup Shadowing. // Setup Shadowing.
shadowEnable = true;
shadowSize = 256; shadowSize = 256;
shadowProjectionDistance = 14.0f; shadowProjectionDistance = 14.0f;

View file

@ -331,11 +331,15 @@ void afxMagicMissileData::initPersistFields()
{ {
static IRangeValidatorScaled ticksFromMS(TickMs, 0, MaxLifetimeTicks); static IRangeValidatorScaled ticksFromMS(TickMs, 0, MaxLifetimeTicks);
addGroup("Particle Effects");
addField("particleEmitter", TYPEID<ParticleEmitterData>(), Offset(particleEmitter, afxMagicMissileData)); addField("particleEmitter", TYPEID<ParticleEmitterData>(), Offset(particleEmitter, afxMagicMissileData));
addField("particleWaterEmitter", TYPEID<ParticleEmitterData>(), Offset(particleWaterEmitter, afxMagicMissileData)); addField("particleWaterEmitter", TYPEID<ParticleEmitterData>(), Offset(particleWaterEmitter, afxMagicMissileData));
endGroup("Particle Effects");
addGroup("Shapes");
INITPERSISTFIELD_SHAPEASSET(ProjectileShape, afxMagicMissileData, "Shape for the projectile"); INITPERSISTFIELD_SHAPEASSET(ProjectileShape, afxMagicMissileData, "Shape for the projectile");
addField("scale", TypePoint3F, Offset(scale, afxMagicMissileData)); addField("scale", TypePoint3F, Offset(scale, afxMagicMissileData));
endGroup("Shapes");
INITPERSISTFIELD_SOUNDASSET(ProjectileSound, afxMagicMissileData, "sound for the projectile"); INITPERSISTFIELD_SOUNDASSET(ProjectileSound, afxMagicMissileData, "sound for the projectile");

View file

@ -74,7 +74,6 @@ afxModelData::afxModelData()
useCustomAmbientLighting = false; useCustomAmbientLighting = false;
customAmbientForSelfIllumination = false; customAmbientForSelfIllumination = false;
customAmbientLighting = LinearColorF(0.0f, 0.0f, 0.0f); customAmbientLighting = LinearColorF(0.0f, 0.0f, 0.0f);
shadowEnable = false;
shadowSize = 128; shadowSize = 128;
shadowMaxVisibleDistance = 80.0f; shadowMaxVisibleDistance = 80.0f;
@ -103,7 +102,6 @@ afxModelData::afxModelData(const afxModelData& other, bool temp_clone) : GameBas
useCustomAmbientLighting = other.useCustomAmbientLighting; useCustomAmbientLighting = other.useCustomAmbientLighting;
customAmbientForSelfIllumination = other.customAmbientForSelfIllumination; customAmbientForSelfIllumination = other.customAmbientForSelfIllumination;
customAmbientLighting = other.customAmbientLighting; customAmbientLighting = other.customAmbientLighting;
shadowEnable = other.shadowEnable;
shadowSize = other.shadowSize; shadowSize = other.shadowSize;
shadowMaxVisibleDistance = other.shadowMaxVisibleDistance; shadowMaxVisibleDistance = other.shadowMaxVisibleDistance;
@ -174,7 +172,11 @@ bool afxModelData::preload(bool server, String &errorStr)
void afxModelData::initPersistFields() void afxModelData::initPersistFields()
{ {
addGroup("Shapes");
INITPERSISTFIELD_SHAPEASSET(Shape, afxModelData, "The name of a .dts format file to use for the model."); INITPERSISTFIELD_SHAPEASSET(Shape, afxModelData, "The name of a .dts format file to use for the model.");
addGroup("Shapes");
addGroup("Rendering");
addField("sequence", TypeString, myOffset(sequence), addField("sequence", TypeString, myOffset(sequence),
"The name of an animation sequence to play in the model."); "The name of an animation sequence to play in the model.");
addField("sequenceRate", TypeF32, myOffset(seq_rate), addField("sequenceRate", TypeF32, myOffset(seq_rate),
@ -185,9 +187,7 @@ void afxModelData::initPersistFields()
"to convert from seconds to the thread offset."); "to convert from seconds to the thread offset.");
addField("alphaMult", TypeF32, myOffset(alpha_mult), addField("alphaMult", TypeF32, myOffset(alpha_mult),
"An alpha multiplier used to set maximum opacity of the model."); "An alpha multiplier used to set maximum opacity of the model.");
addField("fogMult", TypeF32, myOffset(fog_mult), "");
addField("fogMult", TypeF32, myOffset(fog_mult),
"");
addField("remapTextureTags", TypeString, myOffset(remap_txr_tags), addField("remapTextureTags", TypeString, myOffset(remap_txr_tags),
"Rename one or more texture tags in the model. Texture tags are what link a " "Rename one or more texture tags in the model. Texture tags are what link a "
"model's textures to materials.\n" "model's textures to materials.\n"
@ -196,9 +196,9 @@ void afxModelData::initPersistFields()
"that exists in the model, while the second is a new name to replace it. The string " "that exists in the model, while the second is a new name to replace it. The string "
"can have any number of remapping tokens as long as the total string length does not " "can have any number of remapping tokens as long as the total string length does not "
"exceed 255."); "exceed 255.");
addField("shadowEnable", TypeBool, myOffset(shadowEnable), addGroup("Rendering");
"Sets whether the model casts a shadow.");
addGroup("Deprecated");
addField("useVertexAlpha", TypeBool, myOffset(use_vertex_alpha), addField("useVertexAlpha", TypeBool, myOffset(use_vertex_alpha),
"deprecated"); "deprecated");
addField("forceOnMaterialFlags", TypeS32, myOffset(force_on_material_flags), addField("forceOnMaterialFlags", TypeS32, myOffset(force_on_material_flags),
@ -229,6 +229,7 @@ void afxModelData::initPersistFields()
"deprecated"); "deprecated");
addField("shadowSphereAdjust", TypeF32, myOffset(shadowSphereAdjust), addField("shadowSphereAdjust", TypeF32, myOffset(shadowSphereAdjust),
"deprecated"); "deprecated");
endGroup("Deprecated");
Parent::initPersistFields(); Parent::initPersistFields();
@ -273,7 +274,6 @@ void afxModelData::packData(BitStream* stream)
stream->writeFlag(customAmbientForSelfIllumination); stream->writeFlag(customAmbientForSelfIllumination);
stream->write(customAmbientLighting); stream->write(customAmbientLighting);
stream->writeFlag(receiveLMLighting); stream->writeFlag(receiveLMLighting);
stream->writeFlag(shadowEnable);
stream->write(shadowSize); stream->write(shadowSize);
stream->write(shadowMaxVisibleDistance); stream->write(shadowMaxVisibleDistance);
@ -305,7 +305,6 @@ void afxModelData::unpackData(BitStream* stream)
customAmbientForSelfIllumination = stream->readFlag(); customAmbientForSelfIllumination = stream->readFlag();
stream->read(&customAmbientLighting); stream->read(&customAmbientLighting);
receiveLMLighting = stream->readFlag(); receiveLMLighting = stream->readFlag();
shadowEnable = stream->readFlag();
stream->read(&shadowSize); stream->read(&shadowSize);
stream->read(&shadowMaxVisibleDistance); stream->read(&shadowMaxVisibleDistance);

View file

@ -74,7 +74,6 @@ struct afxModelData : public GameBaseData
bool useCustomAmbientLighting; bool useCustomAmbientLighting;
bool customAmbientForSelfIllumination; bool customAmbientForSelfIllumination;
LinearColorF customAmbientLighting; LinearColorF customAmbientLighting;
bool shadowEnable;
U32 shadowSize; U32 shadowSize;
F32 shadowMaxVisibleDistance; F32 shadowMaxVisibleDistance;

View file

@ -165,10 +165,11 @@ VolumetricFog::~VolumetricFog()
void VolumetricFog::initPersistFields() void VolumetricFog::initPersistFields()
{ {
addGroup("VolumetricFogData"); addGroup("Shapes");
INITPERSISTFIELD_SHAPEASSET(Shape, VolumetricFog, "The source shape asset."); INITPERSISTFIELD_SHAPEASSET(Shape, VolumetricFog, "The source shape asset.");
endGroup("Shapes");
addGroup("VolumetricFogData");
addField("FogColor", TypeColorI, Offset(mFogColor, VolumetricFog), addField("FogColor", TypeColorI, Offset(mFogColor, VolumetricFog),
"Fog color RGBA (Alpha is ignored)"); "Fog color RGBA (Alpha is ignored)");
addField("FogDensity", TypeF32, Offset(mFogDensity, VolumetricFog), addField("FogDensity", TypeF32, Offset(mFogDensity, VolumetricFog),

View file

@ -60,20 +60,20 @@ void ForestItemData::initPersistFields()
{ {
Parent::initPersistFields(); Parent::initPersistFields();
addGroup( "Media" ); addGroup( "Shapes" );
INITPERSISTFIELD_SHAPEASSET(Shape, ForestItemData, "Shape asset for this item type"); INITPERSISTFIELD_SHAPEASSET(Shape, ForestItemData, "Shape asset for this item type");
addProtectedField( "shapeFile", TypeShapeFilename, Offset( mShapeName, ForestItemData ), &_setShapeData, &defaultProtectedGetFn, addProtectedField( "shapeFile", TypeShapeFilename, Offset( mShapeName, ForestItemData ), &_setShapeData, &defaultProtectedGetFn,
"Shape file for this item type", AbstractClassRep::FIELD_HideInInspectors ); "Shape file for this item type", AbstractClassRep::FIELD_HideInInspectors );
endGroup( "Shape(s)" );
addGroup("Physics");
addField( "collidable", TypeBool, Offset( mCollidable, ForestItemData ), addField( "collidable", TypeBool, Offset( mCollidable, ForestItemData ),
"Can other objects or spacial queries hit items of this type." ); "Can other objects or spacial queries hit items of this type." );
addField( "radius", TypeF32, Offset( mRadius, ForestItemData ), addField( "radius", TypeF32, Offset( mRadius, ForestItemData ),
"Radius used during placement to ensure items are not crowded." ); "Radius used during placement to ensure items are not crowded." );
endGroup("Physics");
endGroup( "Media" );
addGroup( "Wind" ); addGroup( "Wind" );