Browse Source

fill in the validated variables

AzaezelX 7 months ago
parent
commit
f633ef3a3d
100 changed files with 859 additions and 816 deletions
  1. 4 4
      Engine/source/T3D/aiPlayer.cpp
  2. 4 3
      Engine/source/T3D/assets/ShapeAnimationAsset.cpp
  3. 21 21
      Engine/source/T3D/assets/SoundAsset.cpp
  4. 4 4
      Engine/source/T3D/assets/assetImporter.cpp
  5. 1 1
      Engine/source/T3D/camera.cpp
  6. 19 14
      Engine/source/T3D/debris.cpp
  7. 10 10
      Engine/source/T3D/decal/decalData.cpp
  8. 2 2
      Engine/source/T3D/fps/guiHealthBarHud.cpp
  9. 3 3
      Engine/source/T3D/fps/guiHealthTextHud.cpp
  10. 2 2
      Engine/source/T3D/fps/guiShapeNameHud.cpp
  11. 42 38
      Engine/source/T3D/fx/explosion.cpp
  12. 28 28
      Engine/source/T3D/fx/fxFoliageReplicator.cpp
  13. 25 25
      Engine/source/T3D/fx/fxShapeReplicator.cpp
  14. 30 30
      Engine/source/T3D/fx/groundCover.cpp
  15. 5 5
      Engine/source/T3D/fx/lightning.cpp
  16. 39 26
      Engine/source/T3D/fx/particle.cpp
  17. 16 18
      Engine/source/T3D/fx/particleEmitter.cpp
  18. 1 1
      Engine/source/T3D/fx/particleEmitter.h
  19. 3 2
      Engine/source/T3D/fx/particleEmitterNode.cpp
  20. 17 17
      Engine/source/T3D/fx/precipitation.cpp
  21. 7 7
      Engine/source/T3D/fx/ribbon.cpp
  22. 16 16
      Engine/source/T3D/fx/splash.cpp
  23. 1 1
      Engine/source/T3D/gameBase/gameBase.cpp
  24. 4 4
      Engine/source/T3D/groundPlane.cpp
  25. 4 4
      Engine/source/T3D/guiObjectView.cpp
  26. 17 14
      Engine/source/T3D/item.cpp
  27. 9 11
      Engine/source/T3D/levelInfo.cpp
  28. 24 21
      Engine/source/T3D/lightAnimData.cpp
  29. 8 3
      Engine/source/T3D/lightAnimData.h
  30. 5 5
      Engine/source/T3D/lightBase.cpp
  31. 8 6
      Engine/source/T3D/lightDescription.cpp
  32. 4 4
      Engine/source/T3D/lightFlareData.cpp
  33. 0 1
      Engine/source/T3D/lighting/boxEnvironmentProbe.cpp
  34. 2 2
      Engine/source/T3D/lighting/reflectionProbe.cpp
  35. 3 2
      Engine/source/T3D/missionArea.cpp
  36. 1 1
      Engine/source/T3D/missionMarker.cpp
  37. 4 2
      Engine/source/T3D/physicalZone.cpp
  38. 12 12
      Engine/source/T3D/physics/physicsDebris.cpp
  39. 10 10
      Engine/source/T3D/physics/physicsShape.cpp
  40. 82 81
      Engine/source/T3D/player.cpp
  41. 1 1
      Engine/source/T3D/pointLight.cpp
  42. 9 9
      Engine/source/T3D/projectile.cpp
  43. 6 6
      Engine/source/T3D/proximityMine.cpp
  44. 24 24
      Engine/source/T3D/rigidShape.cpp
  45. 9 9
      Engine/source/T3D/sfx/sfxEmitter.cpp
  46. 15 14
      Engine/source/T3D/shapeBase.cpp
  47. 26 26
      Engine/source/T3D/shapeImage.cpp
  48. 3 3
      Engine/source/T3D/spotLight.cpp
  49. 6 6
      Engine/source/T3D/tsStatic.cpp
  50. 9 9
      Engine/source/T3D/turret/aiTurretShape.cpp
  51. 6 6
      Engine/source/T3D/turret/turretShape.cpp
  52. 15 15
      Engine/source/T3D/vehicles/flyingVehicle.cpp
  53. 6 6
      Engine/source/T3D/vehicles/guiSpeedometer.cpp
  54. 19 19
      Engine/source/T3D/vehicles/hoverVehicle.cpp
  55. 10 10
      Engine/source/T3D/vehicles/vehicle.cpp
  56. 19 19
      Engine/source/T3D/vehicles/wheeledVehicle.cpp
  57. 5 5
      Engine/source/afx/afxEffectGroup.cpp
  58. 15 14
      Engine/source/afx/afxEffectWrapper.cpp
  59. 2 2
      Engine/source/afx/afxEffectron.cpp
  60. 21 20
      Engine/source/afx/afxMagicMissile.cpp
  61. 10 10
      Engine/source/afx/afxMagicSpell.cpp
  62. 9 9
      Engine/source/afx/afxSelectron.cpp
  63. 2 2
      Engine/source/afx/ce/afxAnimClip.cpp
  64. 3 3
      Engine/source/afx/ce/afxAreaDamage.cpp
  65. 2 1
      Engine/source/afx/ce/afxAudioBank.cpp
  66. 2 2
      Engine/source/afx/ce/afxCameraShake.cpp
  67. 4 4
      Engine/source/afx/ce/afxDamage.cpp
  68. 5 5
      Engine/source/afx/ce/afxLightBase_T3D.cpp
  69. 2 1
      Engine/source/afx/ce/afxMachineGun.cpp
  70. 4 4
      Engine/source/afx/ce/afxModel.cpp
  71. 5 5
      Engine/source/afx/ce/afxParticleEmitter.cpp
  72. 2 2
      Engine/source/afx/ce/afxPhraseEffect.cpp
  73. 4 2
      Engine/source/afx/ce/afxPhysicalZone.cpp
  74. 1 1
      Engine/source/afx/ce/afxPlayerMovement.cpp
  75. 1 1
      Engine/source/afx/ce/afxPointLight_T3D.cpp
  76. 3 3
      Engine/source/afx/ce/afxSpotLight_T3D.cpp
  77. 10 10
      Engine/source/afx/ce/afxZodiac.cpp
  78. 6 6
      Engine/source/afx/ce/afxZodiacPlane.cpp
  79. 1 1
      Engine/source/afx/ea/afxEA_Zodiac.cpp
  80. 2 2
      Engine/source/afx/forces/afxF_Drag.cpp
  81. 1 1
      Engine/source/afx/forces/afxF_Gravity.cpp
  82. 3 3
      Engine/source/afx/rpg/afxRPGMagicSpell.cpp
  83. 2 2
      Engine/source/afx/ui/afxGuiTextHud.cpp
  84. 1 1
      Engine/source/afx/util/afxParticlePool.cpp
  85. 4 4
      Engine/source/afx/util/afxPath.cpp
  86. 1 1
      Engine/source/afx/xm/afxXM_AltitudeConform.cpp
  87. 1 1
      Engine/source/afx/xm/afxXM_BoxAdapt.cpp
  88. 1 1
      Engine/source/afx/xm/afxXM_Freeze.cpp
  89. 1 1
      Engine/source/afx/xm/afxXM_GroundConform.cpp
  90. 1 1
      Engine/source/afx/xm/afxXM_Oscillate.cpp
  91. 1 1
      Engine/source/afx/xm/afxXM_OscillateZodiacColor.cpp
  92. 4 4
      Engine/source/afx/xm/afxXM_RandomRot.cpp
  93. 1 1
      Engine/source/afx/xm/afxXM_Shockwave.cpp
  94. 4 4
      Engine/source/afx/xm/afxXM_Spin.cpp
  95. 1 1
      Engine/source/afx/xm/afxXM_VelocityOffset.cpp
  96. 9 9
      Engine/source/afx/xm/afxXM_WaveBase.cpp
  97. 5 5
      Engine/source/afx/xm/afxXfmMod.cpp
  98. 8 8
      Engine/source/environment/VolumetricFog.cpp
  99. 3 3
      Engine/source/environment/basicClouds.cpp
  100. 6 6
      Engine/source/environment/cloudLayer.cpp

+ 4 - 4
Engine/source/T3D/aiPlayer.cpp

@@ -136,27 +136,27 @@ void AIPlayer::initPersistFields()
    docsURL;
    docsURL;
    addGroup( "AI" );
    addGroup( "AI" );
 
 
-      addField( "mMoveTolerance", TypeF32, Offset( mMoveTolerance, AIPlayer ), 
+      addFieldV( "mMoveTolerance", TypeRangedF32, Offset( mMoveTolerance, AIPlayer ), &CommonValidators::PositiveFloat,
          "@brief Distance from destination before stopping.\n\n"
          "@brief Distance from destination before stopping.\n\n"
          "When the AIPlayer is moving to a given destination it will move to within "
          "When the AIPlayer is moving to a given destination it will move to within "
          "this distance of the destination and then stop.  By providing this tolerance "
          "this distance of the destination and then stop.  By providing this tolerance "
          "it helps the AIPlayer from never reaching its destination due to minor obstacles, "
          "it helps the AIPlayer from never reaching its destination due to minor obstacles, "
          "rounding errors on its position calculation, etc.  By default it is set to 0.25.\n");
          "rounding errors on its position calculation, etc.  By default it is set to 0.25.\n");
 
 
-      addField( "moveStuckTolerance", TypeF32, Offset( mMoveStuckTolerance, AIPlayer ), 
+      addFieldV( "moveStuckTolerance", TypeRangedF32, Offset( mMoveStuckTolerance, AIPlayer ), &CommonValidators::PositiveFloat,
          "@brief Distance tolerance on stuck check.\n\n"
          "@brief Distance tolerance on stuck check.\n\n"
          "When the AIPlayer is moving to a given destination, if it ever moves less than "
          "When the AIPlayer is moving to a given destination, if it ever moves less than "
          "this tolerance during a single tick, the AIPlayer is considered stuck.  At this point "
          "this tolerance during a single tick, the AIPlayer is considered stuck.  At this point "
          "the onMoveStuck() callback is called on the datablock.\n");
          "the onMoveStuck() callback is called on the datablock.\n");
 
 
-      addField( "moveStuckTestDelay", TypeS32, Offset( mMoveStuckTestDelay, AIPlayer ), 
+      addFieldV( "moveStuckTestDelay", TypeRangedS32, Offset( mMoveStuckTestDelay, AIPlayer ), &CommonValidators::PositiveInt,
          "@brief The number of ticks to wait before testing if the AIPlayer is stuck.\n\n"
          "@brief The number of ticks to wait before testing if the AIPlayer is stuck.\n\n"
          "When the AIPlayer is asked to move, this property is the number of ticks to wait "
          "When the AIPlayer is asked to move, this property is the number of ticks to wait "
          "before the AIPlayer starts to check if it is stuck.  This delay allows the AIPlayer "
          "before the AIPlayer starts to check if it is stuck.  This delay allows the AIPlayer "
          "to accelerate to full speed without its initial slow start being considered as stuck.\n"
          "to accelerate to full speed without its initial slow start being considered as stuck.\n"
          "@note Set to zero to have the stuck test start immediately.\n");
          "@note Set to zero to have the stuck test start immediately.\n");
 
 
-      addField( "AttackRadius", TypeF32, Offset( mAttackRadius, AIPlayer ), 
+      addFieldV( "AttackRadius", TypeRangedF32, Offset( mAttackRadius, AIPlayer ), &CommonValidators::PositiveFloat,
          "@brief Distance considered in firing range for callback purposes.");
          "@brief Distance considered in firing range for callback purposes.");
            
            
    endGroup( "AI" );
    endGroup( "AI" );

+ 4 - 3
Engine/source/T3D/assets/ShapeAnimationAsset.cpp

@@ -45,6 +45,7 @@
 // Debug Profiling.
 // Debug Profiling.
 #include "platform/profiler.h"
 #include "platform/profiler.h"
 
 
+#include "console/typeValidators.h"
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 IMPLEMENT_CONOBJECT(ShapeAnimationAsset);
 IMPLEMENT_CONOBJECT(ShapeAnimationAsset);
@@ -133,10 +134,10 @@ void ShapeAnimationAsset::initPersistFields()
 
 
    addField("isBlend", TypeBool, Offset(mIsBlend, ShapeAnimationAsset), "Is this animation blended with another?");
    addField("isBlend", TypeBool, Offset(mIsBlend, ShapeAnimationAsset), "Is this animation blended with another?");
    addField("blendRefAnimation", TypeString, Offset(mBlendAnimAssetName, ShapeAnimationAsset), "AssetID of the animation to reference for our blending");
    addField("blendRefAnimation", TypeString, Offset(mBlendAnimAssetName, ShapeAnimationAsset), "AssetID of the animation to reference for our blending");
-   addField("blendFrame", TypeS32, Offset(mBlendFrame, ShapeAnimationAsset), "Which frame of the reference animation do we use for our blending");
+   addFieldV("blendFrame", TypeRangedS32, Offset(mBlendFrame, ShapeAnimationAsset), &CommonValidators::PositiveInt, "Which frame of the reference animation do we use for our blending");
 
 
-   addField("startFrame", TypeS32, Offset(mStartFrame, ShapeAnimationAsset), "What frame does this animation clip start on");
-   addField("endFrame", TypeS32, Offset(mEndFrame, ShapeAnimationAsset), "What fram does this animation clip end on");
+   addFieldV("startFrame", TypeRangedS32, Offset(mStartFrame, ShapeAnimationAsset), &CommonValidators::PositiveInt, "What frame does this animation clip start on");
+   addFieldV("endFrame", TypeRangedS32, Offset(mEndFrame, ShapeAnimationAsset), &CommonValidators::PositiveInt, "What fram does this animation clip end on");
    addField("padRotation", TypeBool, Offset(mPadRotation, ShapeAnimationAsset), "Are the rotation values padded");
    addField("padRotation", TypeBool, Offset(mPadRotation, ShapeAnimationAsset), "Are the rotation values padded");
    addField("padTransforms", TypeBool, Offset(mPadTransforms, ShapeAnimationAsset), "Are the transform values padded");
    addField("padTransforms", TypeBool, Offset(mPadTransforms, ShapeAnimationAsset), "Are the transform values padded");
 }
 }

+ 21 - 21
Engine/source/T3D/assets/SoundAsset.cpp

@@ -53,6 +53,7 @@
 #include "sfx/sfxTypes.h"
 #include "sfx/sfxTypes.h"
 
 
 #include "SoundAssetInspectors.h"
 #include "SoundAssetInspectors.h"
+#include "console/typeValidators.h"
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
@@ -184,7 +185,6 @@ SoundAsset::~SoundAsset()
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-
 void SoundAsset::initPersistFields()
 void SoundAsset::initPersistFields()
 {
 {
    docsURL;
    docsURL;
@@ -207,55 +207,55 @@ void SoundAsset::initPersistFields()
          "Behavior when moving out of this slot.\n"
          "Behavior when moving out of this slot.\n"
          "After the #detailTimeOut has expired (if any), this slot determines what the controller "
          "After the #detailTimeOut has expired (if any), this slot determines what the controller "
          "will do before moving on to the next slot.");
          "will do before moving on to the next slot.");
-      addField("delayTimeIn", TypeF32, Offset(mPlaylist.mSlots.mDelayTimeIn.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+      addFieldV("delayTimeIn", TypeRangedF32, Offset(mPlaylist.mSlots.mDelayTimeIn.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Seconds to wait after moving into slot before #transitionIn.");
          "Seconds to wait after moving into slot before #transitionIn.");
       addField("delayTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeIn.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
       addField("delayTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeIn.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Bounds on randomization of #delayTimeIn.\n\n"
          "Bounds on randomization of #delayTimeIn.\n\n"
          "@ref SFXPlayList_randomization\n");
          "@ref SFXPlayList_randomization\n");
-      addField("delayTimeOut", TypeF32, Offset(mPlaylist.mSlots.mDelayTimeOut.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+      addFieldV("delayTimeOut", TypeRangedF32, Offset(mPlaylist.mSlots.mDelayTimeOut.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Seconds to wait before moving out of slot after #transitionOut.");
          "Seconds to wait before moving out of slot after #transitionOut.");
       addField("delayTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeOut.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
       addField("delayTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeOut.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Bounds on randomization of #delayTimeOut.\n\n"
          "Bounds on randomization of #delayTimeOut.\n\n"
          "@ref SFXPlayList_randomization\n");
          "@ref SFXPlayList_randomization\n");
-      addField("fadeTimeIn", TypeF32, Offset(mPlaylist.mSlots.mFadeTimeIn.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+      addFieldV("fadeTimeIn", TypeRangedF32, Offset(mPlaylist.mSlots.mFadeTimeIn.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Seconds to fade sound in (-1 to use the track's own fadeInTime.)\n"
          "Seconds to fade sound in (-1 to use the track's own fadeInTime.)\n"
          "@see SFXDescription::fadeTimeIn");
          "@see SFXDescription::fadeTimeIn");
       addField("fadeTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeIn.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
       addField("fadeTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeIn.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Bounds on randomization of #fadeInTime.\n\n"
          "Bounds on randomization of #fadeInTime.\n\n"
          "@ref SFXPlayList_randomization\n");
          "@ref SFXPlayList_randomization\n");
-      addField("fadeTimeOut", TypeF32, Offset(mPlaylist.mSlots.mFadeTimeOut.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+      addFieldV("fadeTimeOut", TypeRangedF32, Offset(mPlaylist.mSlots.mFadeTimeOut.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Seconds to fade sound out (-1 to use the track's own fadeOutTime.)\n"
          "Seconds to fade sound out (-1 to use the track's own fadeOutTime.)\n"
          "@see SFXDescription::fadeTimeOut");
          "@see SFXDescription::fadeTimeOut");
       addField("fadeTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeOut.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
       addField("fadeTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeOut.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Bounds on randomization of #fadeOutTime\n\n"
          "Bounds on randomization of #fadeOutTime\n\n"
          "@ref SFXPlayList_randomization\n");
          "@ref SFXPlayList_randomization\n");
-      addField("referenceDistance", TypeF32, Offset(mPlaylist.mSlots.mMinDistance.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+      addFieldV("referenceDistance", TypeRangedF32, Offset(mPlaylist.mSlots.mMinDistance.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "@c referenceDistance to set for 3D sounds in this slot (<1 to use @c referenceDistance of track's own description).\n"
          "@c referenceDistance to set for 3D sounds in this slot (<1 to use @c referenceDistance of track's own description).\n"
          "@see SFXDescription::referenceDistance");
          "@see SFXDescription::referenceDistance");
       addField("referenceDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMinDistance.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
       addField("referenceDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMinDistance.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Bounds on randomization of #referenceDistance.\n\n"
          "Bounds on randomization of #referenceDistance.\n\n"
          "@ref SFXPlayList_randomization\n");
          "@ref SFXPlayList_randomization\n");
-      addField("maxDistance", TypeF32, Offset(mPlaylist.mSlots.mMaxDistance.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+      addFieldV("maxDistance", TypeRangedF32, Offset(mPlaylist.mSlots.mMaxDistance.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "@c maxDistance to apply to 3D sounds in this slot (<1 to use @c maxDistance of track's own description).\n"
          "@c maxDistance to apply to 3D sounds in this slot (<1 to use @c maxDistance of track's own description).\n"
          "@see SFXDescription::maxDistance");
          "@see SFXDescription::maxDistance");
       addField("maxDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMaxDistance.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
       addField("maxDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMaxDistance.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Bounds on randomization of #maxDistance.\n\n"
          "Bounds on randomization of #maxDistance.\n\n"
          "@ref SFXPlayList_randomization\n");
          "@ref SFXPlayList_randomization\n");
-      addField("volumeScale", TypeF32, Offset(mPlaylist.mSlots.mVolumeScale.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+      addFieldV("volumeScale", TypeRangedF32, Offset(mPlaylist.mSlots.mVolumeScale.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Scale factor to apply to volume of sounds played on this list slot.\n"
          "Scale factor to apply to volume of sounds played on this list slot.\n"
          "This value will scale the actual volume level set on the track assigned to the slot, i.e. a value of 0.5 will "
          "This value will scale the actual volume level set on the track assigned to the slot, i.e. a value of 0.5 will "
          "cause the track to play at half-volume.");
          "cause the track to play at half-volume.");
       addField("volumeScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mVolumeScale.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
       addField("volumeScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mVolumeScale.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Bounds on randomization of #volumeScale.\n\n"
          "Bounds on randomization of #volumeScale.\n\n"
          "@ref SFXPlayList_randomization\n");
          "@ref SFXPlayList_randomization\n");
-      addField("pitchScale", TypeF32, Offset(mPlaylist.mSlots.mPitchScale.mValue, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+      addFieldV("pitchScale", TypeRangedF32, Offset(mPlaylist.mSlots.mPitchScale.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Scale factor to apply to pitch of sounds played on this list slot.\n"
          "Scale factor to apply to pitch of sounds played on this list slot.\n"
          "This value will scale the actual pitch set on the track assigned to the slot, i.e. a value of 0.5 will "
          "This value will scale the actual pitch set on the track assigned to the slot, i.e. a value of 0.5 will "
          "cause the track to play at half its assigned speed.");
          "cause the track to play at half its assigned speed.");
       addField("pitchScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mPitchScale.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
       addField("pitchScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mPitchScale.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Bounds on randomization of #pitchScale.\n\n"
          "Bounds on randomization of #pitchScale.\n\n"
          "@ref SFXPlayList_randomization\n");
          "@ref SFXPlayList_randomization\n");
-      addField("repeatCount", TypeS32, Offset(mPlaylist.mSlots.mRepeatCount, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
+      addFieldV("repeatCount", TypeRangedS32, Offset(mPlaylist.mSlots.mRepeatCount, SoundAsset), &CommonValidators::PositiveInt, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "Number of times to loop this slot.");
          "Number of times to loop this slot.");
       addField("state", TypeSFXStateName, Offset(mPlaylist.mSlots.mState, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
       addField("state", TypeSFXStateName, Offset(mPlaylist.mSlots.mState, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
          "State that must be active for this slot to play.\n\n"
          "State that must be active for this slot to play.\n\n"
@@ -267,8 +267,8 @@ void SoundAsset::initPersistFields()
    endGroup("SoundSlots");
    endGroup("SoundSlots");
 
 
    addGroup("General Profile");
    addGroup("General Profile");
-   addField("pitchAdjust", TypeF32, Offset(mProfileDesc.mPitch, SoundAsset), "Adjustment of the pitch value 1 is default.");
-   addField("volumeAdjust", TypeF32, Offset(mProfileDesc.mVolume, SoundAsset), "Adjustment to the volume.");
+   addFieldV("pitchAdjust", TypeRangedF32, Offset(mProfileDesc.mPitch, SoundAsset), &CommonValidators::PositiveFloat, "Adjustment of the pitch value 1 is default.");
+   addFieldV("volumeAdjust", TypeRangedF32, Offset(mProfileDesc.mVolume, SoundAsset), &CommonValidators::PositiveFloat, "Adjustment to the volume.");
    addField("is3D", TypeBool, Offset(mProfileDesc.mIs3D, SoundAsset), "Set this sound to 3D.");
    addField("is3D", TypeBool, Offset(mProfileDesc.mIs3D, SoundAsset), "Set this sound to 3D.");
    addField("isLooping", TypeBool, Offset(mProfileDesc.mIsLooping, SoundAsset), "Does this sound loop.");
    addField("isLooping", TypeBool, Offset(mProfileDesc.mIsLooping, SoundAsset), "Does this sound loop.");
    // if streaming, a default packet size should be chosen for all sounds.
    // if streaming, a default packet size should be chosen for all sounds.
@@ -280,27 +280,27 @@ void SoundAsset::initPersistFields()
    endGroup("General Profile");
    endGroup("General Profile");
 
 
    addGroup("Fading");
    addGroup("Fading");
-      addField("fadeInTime", TypeF32, Offset(mProfileDesc.mFadeInTime, SoundAsset), "Number of seconds to gradually fade in volume from zero when playback starts.");
-      addField("fadeOutTime", TypeF32, Offset(mProfileDesc.mFadeOutTime, SoundAsset), "Number of seconds to gradually fade out volume down to zero when playback is stopped or paused.");
+      addFieldV("fadeInTime", TypeRangedF32, Offset(mProfileDesc.mFadeInTime, SoundAsset), &CommonValidators::PositiveFloat, "Number of seconds to gradually fade in volume from zero when playback starts.");
+      addFieldV("fadeOutTime", TypeRangedF32, Offset(mProfileDesc.mFadeOutTime, SoundAsset), &CommonValidators::PositiveFloat, "Number of seconds to gradually fade out volume down to zero when playback is stopped or paused.");
       addField("fadeInEase", TypeEaseF, Offset(mProfileDesc.mFadeInEase, SoundAsset), "Easing curve for fade-in transition.");
       addField("fadeInEase", TypeEaseF, Offset(mProfileDesc.mFadeInEase, SoundAsset), "Easing curve for fade-in transition.");
       addField("fadeOutEase", TypeEaseF, Offset(mProfileDesc.mFadeOutEase, SoundAsset), "Easing curve for fade-out transition.");
       addField("fadeOutEase", TypeEaseF, Offset(mProfileDesc.mFadeOutEase, SoundAsset), "Easing curve for fade-out transition.");
       addField("fadeLoops", TypeBool, Offset(mProfileDesc.mFadeLoops, SoundAsset), "Fade each cycle of a loop in and/or out; otherwise only fade-in first cycle.");
       addField("fadeLoops", TypeBool, Offset(mProfileDesc.mFadeLoops, SoundAsset), "Fade each cycle of a loop in and/or out; otherwise only fade-in first cycle.");
    endGroup("Fading");
    endGroup("Fading");
 
 
    addGroup("3D");
    addGroup("3D");
-      addField("minDistance", TypeF32, Offset(mProfileDesc.mMinDistance, SoundAsset), "Minimum distance for sound.");
-      addField("maxDistance", TypeF32, Offset(mProfileDesc.mMaxDistance, SoundAsset), "Max distance for sound.");
-      addField("coneInsideAngle", TypeS32, Offset(mProfileDesc.mConeInsideAngle, SoundAsset), "Cone inside angle.");
-      addField("coneOutsideAngle", TypeS32, Offset(mProfileDesc.mConeOutsideAngle, SoundAsset), "Cone outside angle.");
-      addField("coneOutsideVolume", TypeF32, Offset(mProfileDesc.mConeOutsideVolume, SoundAsset), "Cone outside volume.");
-      addField("rolloffFactor", TypeF32, Offset(mProfileDesc.mRolloffFactor, SoundAsset), "Rolloff factor.");
+      addFieldV("minDistance", TypeRangedF32, Offset(mProfileDesc.mMinDistance, SoundAsset), &CommonValidators::PositiveFloat, "Minimum distance for sound.");
+      addFieldV("maxDistance", TypeRangedF32, Offset(mProfileDesc.mMaxDistance, SoundAsset), &CommonValidators::PositiveFloat, "Max distance for sound.");
+      addFieldV("coneInsideAngle", TypeRangedS32, Offset(mProfileDesc.mConeInsideAngle, SoundAsset), &CommonValidators::S32_PosDegreeRange, "Cone inside angle.");
+      addFieldV("coneOutsideAngle", TypeRangedS32, Offset(mProfileDesc.mConeOutsideAngle, SoundAsset), &CommonValidators::S32_PosDegreeRange, "Cone outside angle.");
+      addFieldV("coneOutsideVolume", TypeRangedF32, Offset(mProfileDesc.mConeOutsideVolume, SoundAsset), &CommonValidators::NormalizedFloat, "Cone outside volume.");
+      addFieldV("rolloffFactor", TypeRangedF32, Offset(mProfileDesc.mRolloffFactor, SoundAsset), &CommonValidators::PositiveFloat, "Rolloff factor.");
       addField("scatterDistance", TypePoint3F, Offset(mProfileDesc.mScatterDistance, SoundAsset), "Randomization to the spacial position of the sound.");
       addField("scatterDistance", TypePoint3F, Offset(mProfileDesc.mScatterDistance, SoundAsset), "Randomization to the spacial position of the sound.");
    endGroup("3D");
    endGroup("3D");
 
 
    addGroup("Playlist settings");
    addGroup("Playlist settings");
       addField("random", TYPEID< SFXPlayList::ERandomMode >(), Offset(mPlaylist.mRandomMode, SoundAsset), "Slot playback order randomization pattern.");
       addField("random", TYPEID< SFXPlayList::ERandomMode >(), Offset(mPlaylist.mRandomMode, SoundAsset), "Slot playback order randomization pattern.");
       addField("loopMode", TYPEID< SFXPlayList::ELoopMode >(), Offset(mPlaylist.mLoopMode, SoundAsset), "Behavior when description has looping enabled.");
       addField("loopMode", TYPEID< SFXPlayList::ELoopMode >(), Offset(mPlaylist.mLoopMode, SoundAsset), "Behavior when description has looping enabled.");
-      addField("numSlotsToPlay", TypeS32, Offset(mPlaylist.mNumSlotsToPlay, SoundAsset), "Number of slots to play.");
+      addFieldV("numSlotsToPlay", TypeRangedS32, Offset(mPlaylist.mNumSlotsToPlay, SoundAsset), &playlistSlotRange, "Number of slots to play.");
       addField("trace", TypeBool, Offset(mPlaylist.mTrace, SoundAsset), "Enable/disable execution tracing for this playlist (local only).");
       addField("trace", TypeBool, Offset(mPlaylist.mTrace, SoundAsset), "Enable/disable execution tracing for this playlist (local only).");
    endGroup("Playlist settings");
    endGroup("Playlist settings");
 }
 }

+ 4 - 4
Engine/source/T3D/assets/assetImporter.cpp

@@ -153,7 +153,7 @@ void AssetImportConfig::initPersistFields()
       addField("DoUpAxisOverride", TypeBool, Offset(DoUpAxisOverride, AssetImportConfig), "Indicates if the up axis in the model file should be overridden");
       addField("DoUpAxisOverride", TypeBool, Offset(DoUpAxisOverride, AssetImportConfig), "Indicates if the up axis in the model file should be overridden");
       addField("UpAxisOverride", TypeRealString, Offset(UpAxisOverride, AssetImportConfig), "If overriding, what axis should be used as up. Options are X_AXIS, Y_AXIS, Z_AXIS");
       addField("UpAxisOverride", TypeRealString, Offset(UpAxisOverride, AssetImportConfig), "If overriding, what axis should be used as up. Options are X_AXIS, Y_AXIS, Z_AXIS");
       addField("DoScaleOverride", TypeBool, Offset(DoScaleOverride, AssetImportConfig), "Indicates if the scale in the model file should be overridden");
       addField("DoScaleOverride", TypeBool, Offset(DoScaleOverride, AssetImportConfig), "Indicates if the scale in the model file should be overridden");
-      addField("ScaleOverride", TypeF32, Offset(ScaleOverride, AssetImportConfig), "If overriding, what scale should be used");
+      addFieldV("ScaleOverride", TypeRangedF32, Offset(ScaleOverride, AssetImportConfig), &CommonValidators::PositiveFloat, "If overriding, what scale should be used");
       addField("IgnoreNodeScale", TypeBool, Offset(IgnoreNodeScale, AssetImportConfig), "Indicates if scale of nodes should be ignored");
       addField("IgnoreNodeScale", TypeBool, Offset(IgnoreNodeScale, AssetImportConfig), "Indicates if scale of nodes should be ignored");
       addField("AdjustCenter", TypeBool, Offset(AdjustCenter, AssetImportConfig), "Indicates if the center of the model file should be automatically recentered");
       addField("AdjustCenter", TypeBool, Offset(AdjustCenter, AssetImportConfig), "Indicates if the center of the model file should be automatically recentered");
       addField("AdjustFloor", TypeBool, Offset(AdjustFloor, AssetImportConfig), "Indicates if the floor height of the model file should be automatically zero'd");
       addField("AdjustFloor", TypeBool, Offset(AdjustFloor, AssetImportConfig), "Indicates if the floor height of the model file should be automatically zero'd");
@@ -223,15 +223,15 @@ void AssetImportConfig::initPersistFields()
       addField("UseMips", TypeBool, Offset(UseMips, AssetImportConfig), "Indicates if images imported with this configuration utilize mipmaps");
       addField("UseMips", TypeBool, Offset(UseMips, AssetImportConfig), "Indicates if images imported with this configuration utilize mipmaps");
 
 
       addField("IsHDR", TypeBool, Offset(IsHDR, AssetImportConfig), "Indicates if images imported with this configuration are in an HDR format");
       addField("IsHDR", TypeBool, Offset(IsHDR, AssetImportConfig), "Indicates if images imported with this configuration are in an HDR format");
-      addField("Scaling", TypeF32, Offset(Scaling, AssetImportConfig), "Indicates what amount of scaling images imported with this configuration use");
+      addFieldV("Scaling", TypeRangedF32, Offset(Scaling, AssetImportConfig), &CommonValidators::PositiveFloat, "Indicates what amount of scaling images imported with this configuration use");
       addField("ImagesCompressed", TypeBool, Offset(ImagesCompressed, AssetImportConfig), "Indicates if images imported with this configuration are compressed");
       addField("ImagesCompressed", TypeBool, Offset(ImagesCompressed, AssetImportConfig), "Indicates if images imported with this configuration are compressed");
       addField("GenerateMaterialOnImport", TypeBool, Offset(GenerateMaterialOnImport, AssetImportConfig), "Indicates if images imported with this configuration generate a parent material for it as well");
       addField("GenerateMaterialOnImport", TypeBool, Offset(GenerateMaterialOnImport, AssetImportConfig), "Indicates if images imported with this configuration generate a parent material for it as well");
    endGroup("Images");
    endGroup("Images");
 
 
    addGroup("Sounds");
    addGroup("Sounds");
       addField("importSounds", TypeBool, Offset(importSounds, AssetImportConfig), "Indicates if sounds are imported with this configuration");
       addField("importSounds", TypeBool, Offset(importSounds, AssetImportConfig), "Indicates if sounds are imported with this configuration");
-      addField("VolumeAdjust", TypeF32, Offset(VolumeAdjust, AssetImportConfig), "Indicates what amount the volume is adjusted on sounds imported with this configuration");
-      addField("PitchAdjust", TypeF32, Offset(PitchAdjust, AssetImportConfig), "Indicates what amount the pitch is adjusted on sounds imported with this configuration");
+      addFieldV("VolumeAdjust", TypeRangedF32, Offset(VolumeAdjust, AssetImportConfig), &CommonValidators::PositiveFloat, "Indicates what amount the volume is adjusted on sounds imported with this configuration");
+      addFieldV("PitchAdjust", TypeRangedF32, Offset(PitchAdjust, AssetImportConfig), &CommonValidators::PositiveFloat, "Indicates what amount the pitch is adjusted on sounds imported with this configuration");
       addField("SoundsCompressed", TypeBool, Offset(SoundsCompressed, AssetImportConfig), "Indicates if sounds imported with this configuration are compressed");
       addField("SoundsCompressed", TypeBool, Offset(SoundsCompressed, AssetImportConfig), "Indicates if sounds imported with this configuration are compressed");
    endGroup("Sounds");
    endGroup("Sounds");
 }
 }

+ 1 - 1
Engine/source/T3D/camera.cpp

@@ -1322,7 +1322,7 @@ void Camera::initPersistFields()
          "Apply smoothing (acceleration and damping) to camera rotations." );
          "Apply smoothing (acceleration and damping) to camera rotations." );
       addProtectedField( "mass",            TypeF32,    Offset(mMass, Camera),            &_setNewtonField, &defaultProtectedGetFn,
       addProtectedField( "mass",            TypeF32,    Offset(mMass, Camera),            &_setNewtonField, &defaultProtectedGetFn,
          "The camera's mass (Newton mode only).  Default value is 10." );
          "The camera's mass (Newton mode only).  Default value is 10." );
-      addProtectedField( "drag",            TypeF32,    Offset(mDrag, Camera),            &_setNewtonField, &defaultProtectedGetFn,
+      addProtectedFieldV( "drag",            TypeRangedF32,    Offset(mDrag, Camera),            &_setNewtonField, &defaultProtectedGetFn, &CommonValidators::PositiveNonZeroFloat,
          "Drag on camera when moving (Newton mode only).  Default value is 2." );
          "Drag on camera when moving (Newton mode only).  Default value is 2." );
       addProtectedField( "force",           TypeF32,    Offset(mFlyForce, Camera),        &_setNewtonField, &defaultProtectedGetFn,
       addProtectedField( "force",           TypeF32,    Offset(mFlyForce, Camera),        &_setNewtonField, &defaultProtectedGetFn,
          "Force applied on camera when asked to move (Newton mode only).  Default value is 500." );
          "Force applied on camera when asked to move (Newton mode only).  Default value is 500." );

+ 19 - 14
Engine/source/T3D/debris.cpp

@@ -293,6 +293,11 @@ bool DebrisData::preload(bool server, String &errorStr)
    return true;
    return true;
 }
 }
 
 
+FRangeValidator debElasticityRange(-10.0f, 10.0f);
+FRangeValidator debFrictionRange(-10.0f, 10.0f);
+IRangeValidator debBounceRange(0, 10000);
+FRangeValidator debSpinSpeedRange(-10000.0f, 10000.0f);
+FRangeValidator debLifetimeRange(0.0f, 1000.0f);
 void DebrisData::initPersistFields()
 void DebrisData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
@@ -312,33 +317,33 @@ void DebrisData::initPersistFields()
    endGroup("Datablocks");
    endGroup("Datablocks");
 
 
    addGroup("Physics");
    addGroup("Physics");
-   addField("elasticity",           TypeF32,                     Offset(elasticity,          DebrisData), 
+   addFieldV("elasticity",           TypeRangedF32,                     Offset(elasticity,          DebrisData), &debElasticityRange,
       "@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), 
+   addFieldV("friction", TypeRangedF32,                     Offset(friction,            DebrisData), &debFrictionRange,
       "@brief A floating-point value specifying how much velocity is lost to impact and sliding friction.\n\nMust be in the range of -10 to 10.\n");
       "@brief A floating-point value specifying how much velocity is lost to impact and sliding friction.\n\nMust be in the range of -10 to 10.\n");
-   addField("numBounces",           TypeS32,                     Offset(numBounces,          DebrisData), 
+   addFieldV("numBounces",           TypeRangedS32,                     Offset(numBounces,          DebrisData), &debBounceRange,
       "@brief How many times to allow this debris object to bounce until it either explodes, becomes static or snaps (defined in explodeOnMaxBounce, staticOnMaxBounce, snapOnMaxBounce).\n\n"
       "@brief How many times to allow this debris object to bounce until it either explodes, becomes static or snaps (defined in explodeOnMaxBounce, staticOnMaxBounce, snapOnMaxBounce).\n\n"
       "Must be within the range of 0 to 10000.\n"
       "Must be within the range of 0 to 10000.\n"
       "@see bounceVariance\n");
       "@see bounceVariance\n");
-   addField("bounceVariance",       TypeS32,                     Offset(bounceVariance,      DebrisData), 
+   addFieldV("bounceVariance", TypeRangedS32,                     Offset(bounceVariance,      DebrisData), &debBounceRange,
       "@brief Allowed variance in the value of numBounces.\n\nMust be less than numBounces.\n@see numBounces\n");
       "@brief Allowed variance in the value of numBounces.\n\nMust be less than numBounces.\n@see numBounces\n");
-   addField("minSpinSpeed",         TypeF32,                     Offset(minSpinSpeed,        DebrisData), 
+   addFieldV("minSpinSpeed", TypeRangedF32,                     Offset(minSpinSpeed,        DebrisData),&debSpinSpeedRange,
       "@brief Minimum speed that this debris object will rotate.\n\nMust be in the range of -10000 to 1000, and must be less than maxSpinSpeed.\n@see maxSpinSpeed\n");
       "@brief Minimum speed that this debris object will rotate.\n\nMust be in the range of -10000 to 1000, and must be less than maxSpinSpeed.\n@see maxSpinSpeed\n");
-   addField("maxSpinSpeed",         TypeF32,                     Offset(maxSpinSpeed,        DebrisData), 
+   addFieldV("maxSpinSpeed", TypeRangedF32,                     Offset(maxSpinSpeed,        DebrisData), &debSpinSpeedRange,
       "@brief Maximum speed that this debris object will rotate.\n\nMust be in the range of -10000 to 10000.\n@see minSpinSpeed\n");
       "@brief Maximum speed that this debris object will rotate.\n\nMust be in the range of -10000 to 10000.\n@see minSpinSpeed\n");
-   addField("gravModifier",         TypeF32,                     Offset(gravModifier,        DebrisData), "How much gravity affects debris.");
-   addField("terminalVelocity",     TypeF32,                     Offset(terminalVelocity,    DebrisData), "Max velocity magnitude.");
-   addField("velocity",             TypeF32,                     Offset(velocity,            DebrisData), 
+   addFieldV("gravModifier", TypeRangedF32,                     Offset(gravModifier,        DebrisData), &CommonValidators::F32Range, "How much gravity affects debris.");
+   addFieldV("terminalVelocity", TypeRangedF32,                     Offset(terminalVelocity,    DebrisData), &CommonValidators::PositiveFloat, "Max velocity magnitude.");
+   addFieldV("velocity", TypeRangedF32,                     Offset(velocity,            DebrisData), &CommonValidators::PositiveFloat,
       "@brief Speed at which this debris object will move.\n\n@see velocityVariance\n");
       "@brief Speed at which this debris object will move.\n\n@see velocityVariance\n");
-   addField("velocityVariance",     TypeF32,                     Offset(velocityVariance,    DebrisData), 
+   addFieldV("velocityVariance", TypeRangedF32,                     Offset(velocityVariance,    DebrisData), &CommonValidators::PositiveFloat,
       "@brief Allowed variance in the value of velocity\n\nMust be less than velocity.\n@see velocity\n");
       "@brief Allowed variance in the value of velocity\n\nMust be less than velocity.\n@see velocity\n");
-   addField("lifetime",             TypeF32,                     Offset(lifetime,            DebrisData), 
+   addFieldV("lifetime",             TypeRangedF32,                     Offset(lifetime,            DebrisData), &debLifetimeRange,
       "@brief Amount of time until this debris object is destroyed.\n\nMust be in the range of 0 to 1000.\n@see lifetimeVariance");
       "@brief Amount of time until this debris object is destroyed.\n\nMust be in the range of 0 to 1000.\n@see lifetimeVariance");
-   addField("lifetimeVariance",     TypeF32,                     Offset(lifetimeVariance,    DebrisData), 
+   addFieldV("lifetimeVariance", TypeRangedF32,                     Offset(lifetimeVariance,    DebrisData), &debLifetimeRange,
       "@brief Allowed variance in the value of lifetime.\n\nMust be less than lifetime.\n@see lifetime\n");
       "@brief Allowed variance in the value of lifetime.\n\nMust be less than lifetime.\n@see lifetime\n");
    addField("useRadiusMass",        TypeBool,                    Offset(useRadiusMass,       DebrisData), 
    addField("useRadiusMass",        TypeBool,                    Offset(useRadiusMass,       DebrisData), 
       "@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), 
+   addFieldV("baseRadius", TypeRangedF32,                     Offset(baseRadius,          DebrisData), &CommonValidators::PositiveFloat,
       "@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("Physics");
    endGroup("Physics");
 
 
@@ -571,7 +576,7 @@ void Debris::initPersistFields()
    docsURL;
    docsURL;
    addGroup( "Debris" );	
    addGroup( "Debris" );	
    
    
-      addField( "lifetime", TypeF32, Offset(mLifetime, Debris), 
+      addFieldV( "lifetime", TypeRangedF32, Offset(mLifetime, Debris), &CommonValidators::PositiveFloat,
          "@brief Length of time for this debris object to exist. When expired, the object will be deleted.\n\n"
          "@brief Length of time for this debris object to exist. When expired, the object will be deleted.\n\n"
          "The initial lifetime value comes from the DebrisData datablock.\n"
          "The initial lifetime value comes from the DebrisData datablock.\n"
          "@see DebrisData::lifetime\n"
          "@see DebrisData::lifetime\n"

+ 10 - 10
Engine/source/T3D/decal/decalData.cpp

@@ -141,15 +141,15 @@ void DecalData::initPersistFields()
    docsURL;
    docsURL;
    addGroup( "Decal" );
    addGroup( "Decal" );
 
 
-      addField( "size", TypeF32, Offset( size, DecalData ), 
+      addFieldV( "size", TypeRangedF32, Offset( size, DecalData ), &CommonValidators::PositiveFloat,
          "Width and height of the decal in meters before scale is applied." );
          "Width and height of the decal in meters before scale is applied." );
 
 
       INITPERSISTFIELD_MATERIALASSET(Material, DecalData, "Material to use for this decal.");
       INITPERSISTFIELD_MATERIALASSET(Material, DecalData, "Material to use for this decal.");
 
 
-      addField( "lifeSpan", TypeS32, Offset( lifeSpan, DecalData ),
+      addFieldV( "lifeSpan", TypeRangedS32, Offset( lifeSpan, DecalData ), &CommonValidators::PositiveInt,
          "Time (in milliseconds) before this decal will be automatically deleted." );
          "Time (in milliseconds) before this decal will be automatically deleted." );
 
 
-      addField( "fadeTime", TypeS32, Offset( fadeTime, DecalData ),
+      addFieldV( "fadeTime", TypeRangedS32, Offset( fadeTime, DecalData ), &CommonValidators::PositiveInt,
          "@brief Time (in milliseconds) over which to fade out the decal before "
          "@brief Time (in milliseconds) over which to fade out the decal before "
          "deleting it at the end of its lifetime.\n\n"
          "deleting it at the end of its lifetime.\n\n"
          "@see lifeSpan" );
          "@see lifeSpan" );
@@ -158,13 +158,13 @@ void DecalData::initPersistFields()
 
 
    addGroup( "Rendering" );
    addGroup( "Rendering" );
 
 
-      addField( "fadeStartPixelSize", TypeF32, Offset( fadeStartPixelSize, DecalData ), 
+      addFieldV( "fadeStartPixelSize", TypeRangedF32, Offset( fadeStartPixelSize, DecalData ), &CommonValidators::NegDefaultF32,
          "@brief LOD value - size in pixels at which decals of this type begin "
          "@brief LOD value - size in pixels at which decals of this type begin "
          "to fade out.\n\n"
          "to fade out.\n\n"
          "This should be a larger value than #fadeEndPixelSize. However, you may "
          "This should be a larger value than #fadeEndPixelSize. However, you may "
          "also set this to a negative value to disable lod-based fading." );
          "also set this to a negative value to disable lod-based fading." );
 
 
-      addField( "fadeEndPixelSize", TypeF32, Offset( fadeEndPixelSize, DecalData ), 
+      addFieldV( "fadeEndPixelSize", TypeRangedF32, Offset( fadeEndPixelSize, DecalData ), &CommonValidators::PositiveFloat,
          "@brief LOD value - size in pixels at which decals of this type are "
          "@brief LOD value - size in pixels at which decals of this type are "
          "fully faded out.\n\n"
          "fully faded out.\n\n"
          "This should be a smaller value than #fadeStartPixelSize." );
          "This should be a smaller value than #fadeStartPixelSize." );
@@ -173,7 +173,7 @@ void DecalData::initPersistFields()
          "Default renderPriority for decals of this type (determines draw "
          "Default renderPriority for decals of this type (determines draw "
          "order when decals overlap)." );
          "order when decals overlap)." );
 
 
-      addField( "clippingAngle", TypeF32, Offset( clippingAngle, DecalData ),
+      addFieldV( "clippingAngle", TypeRangedF32, Offset( clippingAngle, DecalData ), &CommonValidators::PosDegreeRangeQuarter,
          "The angle in degrees used to clip geometry that faces away from the "
          "The angle in degrees used to clip geometry that faces away from the "
          "decal projection direction." );
          "decal projection direction." );
 
 
@@ -181,23 +181,23 @@ void DecalData::initPersistFields()
 
 
    addGroup( "Texturing" );
    addGroup( "Texturing" );
 
 
-      addField( "frame", TypeS32, Offset( frame, DecalData ),
+      addFieldV( "frame", TypeRangedS32, Offset( frame, DecalData ), &CommonValidators::PositiveInt,
          "Index of the texture rectangle within the imagemap to use for this decal." );
          "Index of the texture rectangle within the imagemap to use for this decal." );
 
 
       addField( "randomize", TypeBool, Offset( randomize, DecalData ),
       addField( "randomize", TypeBool, Offset( randomize, DecalData ),
          "If true, a random frame from the imagemap is selected for each "
          "If true, a random frame from the imagemap is selected for each "
          "instance of the decal." );
          "instance of the decal." );
 
 
-      addField( "textureCoordCount", TypeS32, Offset( texCoordCount, DecalData ),
+      addFieldV( "textureCoordCount", TypeRangedS32, Offset( texCoordCount, DecalData ), &CommonValidators::PositiveInt,
          "Number of individual frames in the imagemap (maximum 16)." );
          "Number of individual frames in the imagemap (maximum 16)." );
 
 
-      addField( "texRows", TypeS32, Offset( texRows, DecalData ),
+      addFieldV( "texRows", TypeRangedS32, Offset( texRows, DecalData ), &CommonValidators::PositiveInt,
          "@brief Number of rows in the supplied imagemap.\n\n"
          "@brief Number of rows in the supplied imagemap.\n\n"
          "Use #texRows and #texCols if the imagemap frames are arranged in a "
          "Use #texRows and #texCols if the imagemap frames are arranged in a "
          "grid; use #textureCoords to manually specify UV coordinates for "
          "grid; use #textureCoords to manually specify UV coordinates for "
          "irregular sized frames." );
          "irregular sized frames." );
 
 
-      addField( "texCols", TypeS32, Offset( texCols, DecalData ),
+      addFieldV( "texCols", TypeRangedS32, Offset( texCols, DecalData ), &CommonValidators::PositiveInt,
          "@brief Number of columns in the supplied imagemap.\n\n"
          "@brief Number of columns in the supplied imagemap.\n\n"
          "Use #texRows and #texCols if the imagemap frames are arranged in a "
          "Use #texRows and #texCols if the imagemap frames are arranged in a "
          "grid; use #textureCoords to manually specify UV coordinates for "
          "grid; use #textureCoords to manually specify UV coordinates for "

+ 2 - 2
Engine/source/T3D/fps/guiHealthBarHud.cpp

@@ -120,8 +120,8 @@ void GuiHealthBarHud::initPersistFields()
    endGroup("Colors");		
    endGroup("Colors");		
 
 
    addGroup("Pulse");		
    addGroup("Pulse");		
-   addField( "pulseRate", TypeS32, Offset( mPulseRate, GuiHealthBarHud ), "Speed at which the control will pulse." );
-   addField( "pulseThreshold", TypeF32, Offset( mPulseThreshold, GuiHealthBarHud ), "Health level the control must be under before the control will pulse." );
+   addFieldV( "pulseRate", TypeRangedS32, Offset( mPulseRate, GuiHealthBarHud ), &CommonValidators::PositiveInt, "Speed at which the control will pulse." );
+   addFieldV( "pulseThreshold", TypeRangedF32, Offset( mPulseThreshold, GuiHealthBarHud ), &CommonValidators::PositiveFloat, "Health level the control must be under before the control will pulse." );
    endGroup("Pulse");		
    endGroup("Pulse");		
 
 
    addGroup("Misc");		
    addGroup("Misc");		

+ 3 - 3
Engine/source/T3D/fps/guiHealthTextHud.cpp

@@ -132,9 +132,9 @@ void GuiHealthTextHud::initPersistFields()
    endGroup("View");    
    endGroup("View");    
   
   
    addGroup("Alert");  
    addGroup("Alert");  
-   addField("warnThreshold", TypeF32, Offset(mWarnLevel, GuiHealthTextHud), "The health level at which to use the warningColor.");    
-   addField("pulseThreshold", TypeF32, Offset(mPulseThreshold, GuiHealthTextHud), "Health level at which to begin pulsing.");  
-   addField("pulseRate", TypeS32, Offset(mPulseRate, GuiHealthTextHud), "Speed at which the control will pulse.");  
+   addFieldV("warnThreshold", TypeRangedF32, Offset(mWarnLevel, GuiHealthTextHud), &CommonValidators::PositiveFloat, "The health level at which to use the warningColor.");
+   addFieldV("pulseThreshold", TypeRangedF32, Offset(mPulseThreshold, GuiHealthTextHud), &CommonValidators::PositiveFloat, "Health level at which to begin pulsing.");
+   addFieldV("pulseRate", TypeRangedS32, Offset(mPulseRate, GuiHealthTextHud), &CommonValidators::PositiveInt, "Speed at which the control will pulse.");
    endGroup("Alert");  
    endGroup("Alert");  
   
   
    Parent::initPersistFields();  
    Parent::initPersistFields();  

+ 2 - 2
Engine/source/T3D/fps/guiShapeNameHud.cpp

@@ -141,8 +141,8 @@ void GuiShapeNameHud::initPersistFields()
    addField( "showLabelFill",  TypeBool, Offset( mShowLabelFill, GuiShapeNameHud ), "If true, we draw a background for each shape name label." );
    addField( "showLabelFill",  TypeBool, Offset( mShowLabelFill, GuiShapeNameHud ), "If true, we draw a background for each shape name label." );
    addField( "showLabelFrame", TypeBool, Offset( mShowLabelFrame, GuiShapeNameHud ), "If true, we draw a frame around each shape name label."  );
    addField( "showLabelFrame", TypeBool, Offset( mShowLabelFrame, GuiShapeNameHud ), "If true, we draw a frame around each shape name label."  );
    addField( "labelPadding", TypePoint2I, Offset( mLabelPadding, GuiShapeNameHud ), "The padding (in pixels) between the label text and the frame." );
    addField( "labelPadding", TypePoint2I, Offset( mLabelPadding, GuiShapeNameHud ), "The padding (in pixels) between the label text and the frame." );
-   addField( "verticalOffset", TypeF32, Offset( mVerticalOffset, GuiShapeNameHud ), "Amount to vertically offset the control in relation to the ShapeBase object in focus." );
-   addField( "distanceFade", TypeF32, Offset( mDistanceFade, GuiShapeNameHud ), "Visibility distance (how far the player must be from the ShapeBase object in focus) for this control to render." );
+   addFieldV( "verticalOffset", TypeRangedF32, Offset( mVerticalOffset, GuiShapeNameHud ), &CommonValidators::F32Range, "Amount to vertically offset the control in relation to the ShapeBase object in focus." );
+   addFieldV( "distanceFade", TypeRangedF32, Offset( mDistanceFade, GuiShapeNameHud ), &CommonValidators::PositiveFloat, "Visibility distance (how far the player must be from the ShapeBase object in focus) for this control to render." );
    endGroup("Misc");
    endGroup("Misc");
    Parent::initPersistFields();
    Parent::initPersistFields();
 }
 }

+ 42 - 38
Engine/source/T3D/fx/explosion.cpp

@@ -384,7 +384,11 @@ ExplosionData* ExplosionData::cloneAndPerformSubstitutions(const SimObject* owne
 
 
    return sub_explosion_db;
    return sub_explosion_db;
 }
 }
-
+IRangeValidator expPartDensityRange(0, 1<<14);
+IRangeValidator expDebrisNumRange(0, 1000);
+FRangeValidator expPlaySpeedRange(0.05f, FLT_MAX);
+FRangeValidator expLightRadiusRange(0.0f, MaxLightRadius,1<<8);
+FRangeValidator expTimeRange(0.0f, 1.0f, 1 << 8);
 void ExplosionData::initPersistFields()
 void ExplosionData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
@@ -409,10 +413,10 @@ void ExplosionData::initPersistFields()
          "The second effect spawns the list of ParticleEmitters given by the emitter[] "
          "The second effect spawns the list of ParticleEmitters given by the emitter[] "
          "field. These emitters generate particles in the normal way throughout the "
          "field. These emitters generate particles in the normal way throughout the "
          "lifetime of the explosion." );
          "lifetime of the explosion." );
-      addField( "particleDensity", TypeS32, Offset(particleDensity, ExplosionData),
+      addFieldV( "particleDensity", TypeRangedS32, Offset(particleDensity, ExplosionData), &expPartDensityRange,
          "@brief Density of the particle cloud created at the start of the explosion.\n\n"
          "@brief Density of the particle cloud created at the start of the explosion.\n\n"
          "@see particleEmitter" );
          "@see particleEmitter" );
-      addField( "particleRadius", TypeF32, Offset(particleRadius, ExplosionData),
+      addFieldV( "particleRadius", TypeRangedF32, Offset(particleRadius, ExplosionData),&CommonValidators::PositiveFloat,
          "@brief Radial distance from the explosion center at which cloud particles "
          "@brief Radial distance from the explosion center at which cloud particles "
          "are emitted.\n\n"
          "are emitted.\n\n"
          "@see particleEmitter" );
          "@see particleEmitter" );
@@ -425,21 +429,21 @@ void ExplosionData::initPersistFields()
    addGroup("Debris");
    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),
+      addFieldV( "debrisThetaMin", TypeRangedF32, Offset(debrisThetaMin, ExplosionData), &CommonValidators::PosDegreeRangeHalf,
          "Minimum angle, from the horizontal plane, to eject debris from." );
          "Minimum angle, from the horizontal plane, to eject debris from." );
-      addField( "debrisThetaMax", TypeF32, Offset(debrisThetaMax, ExplosionData),
+      addFieldV( "debrisThetaMax", TypeRangedF32, Offset(debrisThetaMax, ExplosionData), &CommonValidators::PosDegreeRangeHalf,
          "Maximum angle, from the horizontal plane, to eject debris from." );
          "Maximum angle, from the horizontal plane, to eject debris from." );
-      addField( "debrisPhiMin", TypeF32, Offset(debrisPhiMin, ExplosionData),
+      addFieldV( "debrisPhiMin", TypeRangedF32, Offset(debrisPhiMin, ExplosionData), &CommonValidators::PosDegreeRange,
          "Minimum reference angle, from the vertical plane, to eject debris from." );
          "Minimum reference angle, from the vertical plane, to eject debris from." );
-      addField( "debrisPhiMax", TypeF32, Offset(debrisPhiMax, ExplosionData),
+      addFieldV( "debrisPhiMax", TypeRangedF32, Offset(debrisPhiMax, ExplosionData), &CommonValidators::PosDegreeRange,
          "Maximum reference angle, from the vertical plane, to eject debris from." );
          "Maximum reference angle, from the vertical plane, to eject debris from." );
-      addField( "debrisNum", TypeS32, Offset(debrisNum, ExplosionData),
+      addFieldV( "debrisNum", TypeRangedS32, Offset(debrisNum, ExplosionData), &expDebrisNumRange,
          "Number of debris objects to create." );
          "Number of debris objects to create." );
-      addField( "debrisNumVariance", TypeS32, Offset(debrisNumVariance, ExplosionData),
+      addFieldV( "debrisNumVariance", TypeRangedS32, Offset(debrisNumVariance, ExplosionData), &expDebrisNumRange,
          "Variance in the number of debris objects to create (must be from 0 - debrisNum)." );
          "Variance in the number of debris objects to create (must be from 0 - debrisNum)." );
-      addField( "debrisVelocity", TypeF32, Offset(debrisVelocity, ExplosionData),
+      addFieldV( "debrisVelocity", TypeRangedF32, Offset(debrisVelocity, ExplosionData), &CommonValidators::PositiveFloat,
          "Velocity to toss debris at." );
          "Velocity to toss debris at." );
-      addField( "debrisVelocityVariance", TypeF32, Offset(debrisVelocityVariance, ExplosionData),
+      addFieldV( "debrisVelocityVariance", TypeRangedF32, Offset(debrisVelocityVariance, ExplosionData), &CommonValidators::PositiveFloat,
          "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 explosion." );
          "List of additional ExplosionData objects to create at the start of the explosion." );
@@ -450,27 +454,27 @@ void ExplosionData::initPersistFields()
       addField("explosionScale", TypePoint3F, Offset(explosionScale, ExplosionData),
       addField("explosionScale", TypePoint3F, Offset(explosionScale, ExplosionData),
       "\"X Y Z\" scale factor applied to the explosionShape model at the start "
       "\"X Y Z\" scale factor applied to the explosionShape model at the start "
       "of the explosion.");
       "of the explosion.");
-       addField("playSpeed", TypeF32, Offset(playSpeed, ExplosionData),
+       addFieldV("playSpeed", TypeRangedF32, Offset(playSpeed, ExplosionData),&expPlaySpeedRange,
           "Time scale at which to play the explosionShape <i>ambient</i> sequence.");
           "Time scale at which to play the explosionShape <i>ambient</i> sequence.");
 
 
-      addField( "delayMS", TypeS32, Offset(delayMS, ExplosionData),
+      addFieldV( "delayMS", TypeRangedS32, Offset(delayMS, ExplosionData), &CommonValidators::PositiveInt,
          "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 "
          "from the creation of the Explosion object." );
          "from the creation of the Explosion object." );
-      addField( "delayVariance", TypeS32, Offset(delayVariance, ExplosionData),
+      addFieldV( "delayVariance", TypeRangedS32, Offset(delayVariance, ExplosionData), &CommonValidators::PositiveInt,
          "Variance, in milliseconds, of delayMS." );
          "Variance, in milliseconds, of delayMS." );
-      addField( "lifetimeMS", TypeS32, Offset(lifetimeMS, ExplosionData),
+      addFieldV( "lifetimeMS", TypeRangedS32, Offset(lifetimeMS, ExplosionData), &CommonValidators::PositiveInt,
          "@brief Lifetime, in milliseconds, of the Explosion object.\n\n"
          "@brief Lifetime, in milliseconds, of the Explosion object.\n\n"
          "@note If explosionShape is defined and contains an <i>ambient</i> animation, "
          "@note If explosionShape is defined and contains an <i>ambient</i> animation, "
          "this field is ignored, and the playSpeed scaled duration of the animation "
          "this field is ignored, and the playSpeed scaled duration of the animation "
          "is used instead." );
          "is used instead." );
-      addField( "lifetimeVariance", TypeS32, Offset(lifetimeVariance, ExplosionData),
+      addFieldV( "lifetimeVariance", TypeRangedS32, Offset(lifetimeVariance, ExplosionData), &CommonValidators::PositiveInt,
          "Variance, in milliseconds, of the lifetimeMS of the Explosion object.\n" );
          "Variance, in milliseconds, of the lifetimeMS of the Explosion object.\n" );
-      addField( "offset", TypeF32, Offset(offset, ExplosionData),
+      addFieldV( "offset", TypeRangedF32, Offset(offset, ExplosionData), &CommonValidators::PositiveFloat,
          "@brief Offset distance (in a random direction) of the center of the explosion "
          "@brief Offset distance (in a random direction) of the center of the explosion "
          "from the Explosion object position.\n\n"
          "from the Explosion object position.\n\n"
          "Most often used to create some variance in position for subExplosion effects." );
          "Most often used to create some variance in position for subExplosion effects." );
 
 
-      addField( "times", TypeF32, Offset(times, ExplosionData), EC_NUM_TIME_KEYS,
+      addFieldV( "times", TypeRangedF32, Offset(times, ExplosionData), &expTimeRange, EC_NUM_TIME_KEYS,
          "@brief Time keyframes used to scale the explosionShape model.\n\n"
          "@brief Time keyframes used to scale the explosionShape model.\n\n"
          "Values should be in increasing order from 0.0 - 1.0, and correspond to "
          "Values should be in increasing order from 0.0 - 1.0, and correspond to "
          "the life of the Explosion where 0 is the beginning and 1 is the end of "
          "the life of the Explosion where 0 is the beginning and 1 is the end of "
@@ -491,22 +495,22 @@ void ExplosionData::initPersistFields()
       addField( "camShakeAmp", TypePoint3F, Offset(camShakeAmp, ExplosionData),
       addField( "camShakeAmp", TypePoint3F, Offset(camShakeAmp, ExplosionData),
          "@brief Amplitude of camera shaking, defined in the \"X Y Z\" axes.\n\n"
          "@brief Amplitude of camera shaking, defined in the \"X Y Z\" axes.\n\n"
          "Set any value to 0 to disable shaking in that axis." );
          "Set any value to 0 to disable shaking in that axis." );
-      addField( "camShakeDuration", TypeF32, Offset(camShakeDuration, ExplosionData),
+      addFieldV( "camShakeDuration", TypeRangedF32, Offset(camShakeDuration, ExplosionData), &CommonValidators::PositiveFloat,
          "Duration (in seconds) to shake the camera." );
          "Duration (in seconds) to shake the camera." );
-      addField( "camShakeRadius", TypeF32, Offset(camShakeRadius, ExplosionData),
+      addFieldV( "camShakeRadius", TypeRangedF32, Offset(camShakeRadius, ExplosionData), &CommonValidators::PositiveFloat,
          "Radial distance that a camera's position must be within relative to the "
          "Radial distance that a camera's position must be within relative to the "
          "center of the explosion to be shaken." );
          "center of the explosion to be shaken." );
-      addField( "camShakeFalloff", TypeF32, Offset(camShakeFalloff, ExplosionData),
+      addFieldV( "camShakeFalloff", TypeRangedF32, Offset(camShakeFalloff, ExplosionData), &CommonValidators::PositiveFloat,
          "Falloff value for the camera shake." );
          "Falloff value for the camera shake." );
    endGroup("Camera Shake");
    endGroup("Camera Shake");
 
 
    addGroup("Light Emitter");
    addGroup("Light Emitter");
-      addField( "lightStartRadius", TypeF32, Offset(lightStartRadius, ExplosionData),
+      addFieldV( "lightStartRadius", TypeRangedF32, Offset(lightStartRadius, ExplosionData), &expLightRadiusRange,
          "@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 "
          "over the lifetime of the explosion.\n"
          "over the lifetime of the explosion.\n"
          "@see lifetimeMS" );
          "@see lifetimeMS" );
-      addField( "lightEndRadius", TypeF32, Offset(lightEndRadius, ExplosionData),
+      addFieldV( "lightEndRadius", TypeRangedF32, Offset(lightEndRadius, ExplosionData), &expLightRadiusRange,
          "@brief Final radius of the PointLight created by this explosion.\n\n"
          "@brief Final radius of the PointLight created by this explosion.\n\n"
          "@see lightStartRadius" );
          "@see lightStartRadius" );
       addField( "lightStartColor", TypeColorF, Offset(lightStartColor, ExplosionData),
       addField( "lightStartColor", TypeColorF, Offset(lightStartColor, ExplosionData),
@@ -517,15 +521,15 @@ void ExplosionData::initPersistFields()
       addField( "lightEndColor", TypeColorF, Offset(lightEndColor, ExplosionData),
       addField( "lightEndColor", TypeColorF, Offset(lightEndColor, ExplosionData),
          "@brief Final color of the PointLight created by this explosion.\n\n"
          "@brief Final color of the PointLight created by this explosion.\n\n"
          "@see lightStartColor" );
          "@see lightStartColor" );
-      addField( "lightStartBrightness", TypeF32, Offset(lightStartBrightness, ExplosionData),
+      addFieldV( "lightStartBrightness", TypeRangedF32, Offset(lightStartBrightness, ExplosionData), &expLightRadiusRange,
          "@brief Initial brightness of the PointLight created by this explosion.\n\n"
          "@brief Initial brightness of the PointLight created by this explosion.\n\n"
          "Brightness is linearly interpolated from lightStartBrightness to "
          "Brightness is linearly interpolated from lightStartBrightness to "
          "lightEndBrightness over the lifetime of the explosion.\n"
          "lightEndBrightness over the lifetime of the explosion.\n"
          "@see lifetimeMS" );
          "@see lifetimeMS" );
-      addField("lightEndBrightness", TypeF32, Offset(lightEndBrightness, ExplosionData),
+      addFieldV("lightEndBrightness", TypeRangedF32, Offset(lightEndBrightness, ExplosionData), &expLightRadiusRange,
          "@brief Final brightness of the PointLight created by this explosion.\n\n"
          "@brief Final brightness of the PointLight created by this explosion.\n\n"
          "@see lightStartBrightness" );
          "@see lightStartBrightness" );
-      addField( "lightNormalOffset", TypeF32, Offset(lightNormalOffset, ExplosionData),
+      addFieldV( "lightNormalOffset", TypeRangedF32, Offset(lightNormalOffset, ExplosionData), &CommonValidators::PositiveFloat,
          "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");
    endGroup("Light Emitter");
@@ -754,12 +758,12 @@ void ExplosionData::packData(BitStream* stream)
    // Dynamic light info
    // Dynamic light info
    stream->writeFloat(lightStartRadius/MaxLightRadius, 8);
    stream->writeFloat(lightStartRadius/MaxLightRadius, 8);
    stream->writeFloat(lightEndRadius/MaxLightRadius, 8);
    stream->writeFloat(lightEndRadius/MaxLightRadius, 8);
-   stream->writeFloat(lightStartColor.red,7);
-   stream->writeFloat(lightStartColor.green,7);
-   stream->writeFloat(lightStartColor.blue,7);
-   stream->writeFloat(lightEndColor.red,7);
-   stream->writeFloat(lightEndColor.green,7);
-   stream->writeFloat(lightEndColor.blue,7);
+   stream->writeFloat(lightStartColor.red,8);
+   stream->writeFloat(lightStartColor.green,8);
+   stream->writeFloat(lightStartColor.blue,8);
+   stream->writeFloat(lightEndColor.red,8);
+   stream->writeFloat(lightEndColor.green,8);
+   stream->writeFloat(lightEndColor.blue,8);
    stream->writeFloat(lightStartBrightness/MaxLightRadius, 8);
    stream->writeFloat(lightStartBrightness/MaxLightRadius, 8);
    stream->writeFloat(lightEndBrightness/MaxLightRadius, 8);
    stream->writeFloat(lightEndBrightness/MaxLightRadius, 8);
    stream->write(lightNormalOffset);
    stream->write(lightNormalOffset);
@@ -858,12 +862,12 @@ void ExplosionData::unpackData(BitStream* stream)
    //
    //
    lightStartRadius = stream->readFloat(8) * MaxLightRadius;
    lightStartRadius = stream->readFloat(8) * MaxLightRadius;
    lightEndRadius = stream->readFloat(8) * MaxLightRadius;
    lightEndRadius = stream->readFloat(8) * MaxLightRadius;
-   lightStartColor.red = stream->readFloat(7);
-   lightStartColor.green = stream->readFloat(7);
-   lightStartColor.blue = stream->readFloat(7);
-   lightEndColor.red = stream->readFloat(7);
-   lightEndColor.green = stream->readFloat(7);
-   lightEndColor.blue = stream->readFloat(7);
+   lightStartColor.red = stream->readFloat(8);
+   lightStartColor.green = stream->readFloat(8);
+   lightStartColor.blue = stream->readFloat(8);
+   lightEndColor.red = stream->readFloat(8);
+   lightEndColor.green = stream->readFloat(8);
+   lightEndColor.blue = stream->readFloat(8);
    lightStartBrightness = stream->readFloat(8) * MaxLightRadius;
    lightStartBrightness = stream->readFloat(8) * MaxLightRadius;
    lightEndBrightness = stream->readFloat(8) * MaxLightRadius;
    lightEndBrightness = stream->readFloat(8) * MaxLightRadius;
    stream->read( &lightNormalOffset );
    stream->read( &lightNormalOffset );

+ 28 - 28
Engine/source/T3D/fx/fxFoliageReplicator.cpp

@@ -349,35 +349,35 @@ void fxFoliageReplicator::initPersistFields()
    // Add out own persistent fields.
    // Add out own persistent fields.
    addGroup( "Debugging" );	// MM: Added Group Header.
    addGroup( "Debugging" );	// MM: Added Group Header.
       addField( "UseDebugInfo",        TypeBool,      Offset( mFieldData.mUseDebugInfo,         fxFoliageReplicator ), "Culling bins are drawn when set to true." );
       addField( "UseDebugInfo",        TypeBool,      Offset( mFieldData.mUseDebugInfo,         fxFoliageReplicator ), "Culling bins are drawn when set to true." );
-      addField( "DebugBoxHeight",      TypeF32,       Offset( mFieldData.mDebugBoxHeight,       fxFoliageReplicator ), "Height multiplier for drawn culling bins.");
+      addFieldV( "DebugBoxHeight",      TypeRangedF32,       Offset( mFieldData.mDebugBoxHeight,       fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Height multiplier for drawn culling bins.");
       addField( "HideFoliage",         TypeBool,      Offset( mFieldData.mHideFoliage,          fxFoliageReplicator ), "Foliage is hidden when set to true." );
       addField( "HideFoliage",         TypeBool,      Offset( mFieldData.mHideFoliage,          fxFoliageReplicator ), "Foliage is hidden when set to true." );
       addField( "ShowPlacementArea",   TypeBool,      Offset( mFieldData.mShowPlacementArea,    fxFoliageReplicator ), "Draw placement rings when set to true." );
       addField( "ShowPlacementArea",   TypeBool,      Offset( mFieldData.mShowPlacementArea,    fxFoliageReplicator ), "Draw placement rings when set to true." );
-      addField( "PlacementAreaHeight", TypeS32,       Offset( mFieldData.mPlacementBandHeight,  fxFoliageReplicator ), "Height of the placement ring in world units." );
+      addFieldV( "PlacementAreaHeight", TypeRangedS32,       Offset( mFieldData.mPlacementBandHeight,  fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Height of the placement ring in world units." );
       addField( "PlacementColour",     TypeColorF,    Offset( mFieldData.mPlaceAreaColour,      fxFoliageReplicator ), "Color of the placement ring." );
       addField( "PlacementColour",     TypeColorF,    Offset( mFieldData.mPlaceAreaColour,      fxFoliageReplicator ), "Color of the placement ring." );
    endGroup( "Debugging" );	// MM: Added Group Footer.
    endGroup( "Debugging" );	// MM: Added Group Footer.
 
 
    addGroup( "Media" );	// MM: Added Group Header.
    addGroup( "Media" );	// MM: Added Group Header.
       addField( "Seed",                TypeS32,       Offset( mFieldData.mSeed,                 fxFoliageReplicator ), "Random seed for foliage placement." );
       addField( "Seed",                TypeS32,       Offset( mFieldData.mSeed,                 fxFoliageReplicator ), "Random seed for foliage placement." );
       addField( "FoliageFile",         TypeFilename,  Offset( mFieldData.mFoliageFile,          fxFoliageReplicator ), "Image file for the foliage texture." );
       addField( "FoliageFile",         TypeFilename,  Offset( mFieldData.mFoliageFile,          fxFoliageReplicator ), "Image file for the foliage texture." );
-      addField( "FoliageCount",        TypeS32,       Offset( mFieldData.mFoliageCount,         fxFoliageReplicator ), "Maximum foliage instance count." );
-      addField( "FoliageRetries",      TypeS32,       Offset( mFieldData.mFoliageRetries,       fxFoliageReplicator ), "Number of times to try placing a foliage instance before giving up." );
+      addFieldV( "FoliageCount", TypeRangedS32,       Offset( mFieldData.mFoliageCount,         fxFoliageReplicator ), &CommonValidators::NaturalNumber, "Maximum foliage instance count." );
+      addFieldV( "FoliageRetries", TypeRangedS32,       Offset( mFieldData.mFoliageRetries,       fxFoliageReplicator ), &CommonValidators::PositiveInt, "Number of times to try placing a foliage instance before giving up." );
    endGroup( "Media" );	// MM: Added Group Footer.
    endGroup( "Media" );	// MM: Added Group Footer.
 
 
    addGroup( "Area" );	// MM: Added Group Header.
    addGroup( "Area" );	// MM: Added Group Header.
-      addField( "InnerRadiusX",        TypeS32,       Offset( mFieldData.mInnerRadiusX,         fxFoliageReplicator ), "Placement area inner radius on the X axis" );
-      addField( "InnerRadiusY",        TypeS32,       Offset( mFieldData.mInnerRadiusY,         fxFoliageReplicator ), "Placement area inner radius on the Y axis" );
-      addField( "OuterRadiusX",        TypeS32,       Offset( mFieldData.mOuterRadiusX,         fxFoliageReplicator ), "Placement area outer radius on the X axis" );
-      addField( "OuterRadiusY",        TypeS32,       Offset( mFieldData.mOuterRadiusY,         fxFoliageReplicator ), "Placement area outer radius on the Y axis" );
+      addFieldV( "InnerRadiusX",        TypeRangedS32,       Offset( mFieldData.mInnerRadiusX,         fxFoliageReplicator ), &CommonValidators::PositiveInt, "Placement area inner radius on the X axis" );
+      addFieldV( "InnerRadiusY", TypeRangedS32,       Offset( mFieldData.mInnerRadiusY,         fxFoliageReplicator ), &CommonValidators::PositiveInt, "Placement area inner radius on the Y axis" );
+      addFieldV( "OuterRadiusX", TypeRangedS32,       Offset( mFieldData.mOuterRadiusX,         fxFoliageReplicator ), &CommonValidators::PositiveInt, "Placement area outer radius on the X axis" );
+      addFieldV( "OuterRadiusY", TypeRangedS32,       Offset( mFieldData.mOuterRadiusY,         fxFoliageReplicator ), &CommonValidators::PositiveInt, "Placement area outer radius on the Y axis" );
    endGroup( "Area" );	// MM: Added Group Footer.
    endGroup( "Area" );	// MM: Added Group Footer.
 
 
    addGroup( "Dimensions" );	// MM: Added Group Header.
    addGroup( "Dimensions" );	// MM: Added Group Header.
-      addField( "MinWidth",            TypeF32,       Offset( mFieldData.mMinWidth,             fxFoliageReplicator ), "Minimum width of foliage billboards" );
-      addField( "MaxWidth",            TypeF32,       Offset( mFieldData.mMaxWidth,             fxFoliageReplicator ), "Maximum width of foliage billboards" );
-      addField( "MinHeight",           TypeF32,       Offset( mFieldData.mMinHeight,            fxFoliageReplicator ), "Minimum height of foliage billboards" );
-      addField( "MaxHeight",           TypeF32,       Offset( mFieldData.mMaxHeight,            fxFoliageReplicator ), "Maximum height of foliage billboards" );
+      addFieldV( "MinWidth", TypeRangedF32,       Offset( mFieldData.mMinWidth,             fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Minimum width of foliage billboards" );
+      addFieldV( "MaxWidth", TypeRangedF32,       Offset( mFieldData.mMaxWidth,             fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Maximum width of foliage billboards" );
+      addFieldV( "MinHeight", TypeRangedF32,       Offset( mFieldData.mMinHeight,            fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Minimum height of foliage billboards" );
+      addFieldV( "MaxHeight", TypeRangedF32,       Offset( mFieldData.mMaxHeight,            fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Maximum height of foliage billboards" );
       addField( "FixAspectRatio",      TypeBool,      Offset( mFieldData.mFixAspectRatio,       fxFoliageReplicator ), "Maintain aspect ratio of image if true. This option ignores MaxWidth." );
       addField( "FixAspectRatio",      TypeBool,      Offset( mFieldData.mFixAspectRatio,       fxFoliageReplicator ), "Maintain aspect ratio of image if true. This option ignores MaxWidth." );
       addField( "FixSizeToMax",        TypeBool,      Offset( mFieldData.mFixSizeToMax,         fxFoliageReplicator ), "Use only MaxWidth and MaxHeight for billboard size. Ignores MinWidth and MinHeight." );
       addField( "FixSizeToMax",        TypeBool,      Offset( mFieldData.mFixSizeToMax,         fxFoliageReplicator ), "Use only MaxWidth and MaxHeight for billboard size. Ignores MinWidth and MinHeight." );
-      addField( "OffsetZ",             TypeF32,       Offset( mFieldData.mOffsetZ,              fxFoliageReplicator ), "Offset billboards by this amount vertically." );
+      addFieldV( "OffsetZ", TypeRangedF32,       Offset( mFieldData.mOffsetZ,              fxFoliageReplicator ), &CommonValidators::F32Range, "Offset billboards by this amount vertically." );
       addField( "RandomFlip",          TypeBool,      Offset( mFieldData.mRandomFlip,           fxFoliageReplicator ), "Randomly flip billboards left-to-right." );
       addField( "RandomFlip",          TypeBool,      Offset( mFieldData.mRandomFlip,           fxFoliageReplicator ), "Randomly flip billboards left-to-right." );
       addField( "UseTrueBillboards",   TypeBool,      Offset( mFieldData.mUseTrueBillboards,    fxFoliageReplicator ), "Use camera facing billboards ( including the z axis )." );
       addField( "UseTrueBillboards",   TypeBool,      Offset( mFieldData.mUseTrueBillboards,    fxFoliageReplicator ), "Use camera facing billboards ( including the z axis )." );
    endGroup( "Dimensions" );	// MM: Added Group Footer.
    endGroup( "Dimensions" );	// MM: Added Group Footer.
@@ -385,29 +385,29 @@ void fxFoliageReplicator::initPersistFields()
    addGroup( "Culling" );	// MM: Added Group Header.
    addGroup( "Culling" );	// MM: Added Group Header.
       addField( "UseCulling",          TypeBool,      Offset( mFieldData.mUseCulling,           fxFoliageReplicator ), "Use culling bins when enabled." );
       addField( "UseCulling",          TypeBool,      Offset( mFieldData.mUseCulling,           fxFoliageReplicator ), "Use culling bins when enabled." );
       addField( "CullResolution",      TypeS32,       Offset( mFieldData.mCullResolution,       fxFoliageReplicator ), "Minimum size of culling bins.  Must be >= 8 and <= OuterRadius." );
       addField( "CullResolution",      TypeS32,       Offset( mFieldData.mCullResolution,       fxFoliageReplicator ), "Minimum size of culling bins.  Must be >= 8 and <= OuterRadius." );
-      addField( "ViewDistance",        TypeF32,       Offset( mFieldData.mViewDistance,         fxFoliageReplicator ), "Maximum distance from camera where foliage appears." );
-      addField( "ViewClosest",         TypeF32,       Offset( mFieldData.mViewClosest,          fxFoliageReplicator ), "Minimum distance from camera where foliage appears." );
-      addField( "FadeInRegion",        TypeF32,       Offset( mFieldData.mFadeInRegion,         fxFoliageReplicator ), "Region beyond ViewDistance where foliage fades in/out." );
-      addField( "FadeOutRegion",       TypeF32,       Offset( mFieldData.mFadeOutRegion,        fxFoliageReplicator ), "Region before ViewClosest where foliage fades in/out." );
-      addField( "AlphaCutoff",         TypeF32,       Offset( mFieldData.mAlphaCutoff,          fxFoliageReplicator ), "Minimum alpha value allowed on foliage instances." );
-      addField( "GroundAlpha",         TypeF32,       Offset( mFieldData.mGroundAlpha,          fxFoliageReplicator ), "Alpha of the foliage at ground level. 0 = transparent, 1 = opaque." );
+      addFieldV( "ViewDistance", TypeRangedF32,       Offset( mFieldData.mViewDistance,         fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Maximum distance from camera where foliage appears." );
+      addFieldV( "ViewClosest", TypeRangedF32,       Offset( mFieldData.mViewClosest,          fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Minimum distance from camera where foliage appears." );
+      addFieldV( "FadeInRegion", TypeRangedF32,       Offset( mFieldData.mFadeInRegion,         fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Region beyond ViewDistance where foliage fades in/out." );
+      addFieldV( "FadeOutRegion", TypeRangedF32,       Offset( mFieldData.mFadeOutRegion,        fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Region before ViewClosest where foliage fades in/out." );
+      addFieldV( "AlphaCutoff", TypeRangedF32,       Offset( mFieldData.mAlphaCutoff,          fxFoliageReplicator ),&CommonValidators::NormalizedFloat, "Minimum alpha value allowed on foliage instances.");
+      addFieldV( "GroundAlpha", TypeRangedF32,       Offset( mFieldData.mGroundAlpha,          fxFoliageReplicator ), &CommonValidators::NormalizedFloat, "Alpha of the foliage at ground level. 0 = transparent, 1 = opaque." );
    endGroup( "Culling" );	// MM: Added Group Footer.
    endGroup( "Culling" );	// MM: Added Group Footer.
 
 
    addGroup( "Animation" );	// MM: Added Group Header.
    addGroup( "Animation" );	// MM: Added Group Header.
       addField( "SwayOn",              TypeBool,      Offset( mFieldData.mSwayOn,               fxFoliageReplicator ), "Foliage should sway randomly when true." );
       addField( "SwayOn",              TypeBool,      Offset( mFieldData.mSwayOn,               fxFoliageReplicator ), "Foliage should sway randomly when true." );
       addField( "SwaySync",            TypeBool,      Offset( mFieldData.mSwaySync,             fxFoliageReplicator ), "Foliage instances should sway together when true and SwayOn is enabled." );
       addField( "SwaySync",            TypeBool,      Offset( mFieldData.mSwaySync,             fxFoliageReplicator ), "Foliage instances should sway together when true and SwayOn is enabled." );
-      addField( "SwayMagSide",         TypeF32,       Offset( mFieldData.mSwayMagnitudeSide,    fxFoliageReplicator ), "Left-to-right sway magnitude." );
-      addField( "SwayMagFront",        TypeF32,       Offset( mFieldData.mSwayMagnitudeFront,   fxFoliageReplicator ), "Front-to-back sway magnitude." );
-      addField( "MinSwayTime",         TypeF32,       Offset( mFieldData.mMinSwayTime,          fxFoliageReplicator ), "Minumum sway cycle time in seconds." );
-      addField( "MaxSwayTime",         TypeF32,       Offset( mFieldData.mMaxSwayTime,          fxFoliageReplicator ), "Maximum sway cycle time in seconds." );
+      addFieldV( "SwayMagSide", TypeRangedF32,       Offset( mFieldData.mSwayMagnitudeSide,    fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Left-to-right sway magnitude." );
+      addFieldV( "SwayMagFront", TypeRangedF32,       Offset( mFieldData.mSwayMagnitudeFront,   fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Front-to-back sway magnitude." );
+      addFieldV( "MinSwayTime", TypeRangedF32,       Offset( mFieldData.mMinSwayTime,          fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Minumum sway cycle time in seconds." );
+      addFieldV( "MaxSwayTime", TypeRangedF32,       Offset( mFieldData.mMaxSwayTime,          fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Maximum sway cycle time in seconds." );
    endGroup( "Animation" );	// MM: Added Group Footer.
    endGroup( "Animation" );	// MM: Added Group Footer.
 
 
    addGroup( "Lighting" );	// MM: Added Group Header.
    addGroup( "Lighting" );	// MM: Added Group Header.
       addField( "LightOn",             TypeBool,      Offset( mFieldData.mLightOn,              fxFoliageReplicator ), "Foliage should be illuminated with changing lights when true." );
       addField( "LightOn",             TypeBool,      Offset( mFieldData.mLightOn,              fxFoliageReplicator ), "Foliage should be illuminated with changing lights when true." );
       addField( "LightSync",           TypeBool,      Offset( mFieldData.mLightSync,            fxFoliageReplicator ), "Foliage instances have the same lighting when set and LightOn is set." );
       addField( "LightSync",           TypeBool,      Offset( mFieldData.mLightSync,            fxFoliageReplicator ), "Foliage instances have the same lighting when set and LightOn is set." );
-      addField( "MinLuminance",        TypeF32,       Offset( mFieldData.mMinLuminance,         fxFoliageReplicator ), "Minimum luminance for foliage instances." );
-      addField( "MaxLuminance",        TypeF32,       Offset( mFieldData.mMaxLuminance,         fxFoliageReplicator ), "Maximum luminance for foliage instances." );
-      addField( "LightTime",           TypeF32,       Offset( mFieldData.mLightTime,            fxFoliageReplicator ), "Time before foliage illumination cycle repeats." );
+      addFieldV( "MinLuminance", TypeRangedF32,       Offset( mFieldData.mMinLuminance,         fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Minimum luminance for foliage instances." );
+      addFieldV( "MaxLuminance", TypeRangedF32,       Offset( mFieldData.mMaxLuminance,         fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Maximum luminance for foliage instances." );
+      addFieldV( "LightTime", TypeRangedF32,       Offset( mFieldData.mLightTime,            fxFoliageReplicator ), &CommonValidators::PositiveFloat, "Time before foliage illumination cycle repeats." );
    endGroup( "Lighting" );	// MM: Added Group Footer.
    endGroup( "Lighting" );	// MM: Added Group Footer.
 
 
    addGroup( "Restrictions" );	// MM: Added Group Header.
    addGroup( "Restrictions" );	// MM: Added Group Header.
@@ -415,11 +415,11 @@ void fxFoliageReplicator::initPersistFields()
       addField( "AllowOnStatics",      TypeBool,      Offset( mFieldData.mAllowStatics,         fxFoliageReplicator ), "Foliage will be placed on Static shapes when set." );
       addField( "AllowOnStatics",      TypeBool,      Offset( mFieldData.mAllowStatics,         fxFoliageReplicator ), "Foliage will be placed on Static shapes when set." );
       addField( "AllowOnWater",        TypeBool,      Offset( mFieldData.mAllowOnWater,         fxFoliageReplicator ), "Foliage will be placed on/under water when set." );
       addField( "AllowOnWater",        TypeBool,      Offset( mFieldData.mAllowOnWater,         fxFoliageReplicator ), "Foliage will be placed on/under water when set." );
       addField( "AllowWaterSurface",   TypeBool,      Offset( mFieldData.mAllowWaterSurface,    fxFoliageReplicator ), "Foliage will be placed on water when set. Requires AllowOnWater." );
       addField( "AllowWaterSurface",   TypeBool,      Offset( mFieldData.mAllowWaterSurface,    fxFoliageReplicator ), "Foliage will be placed on water when set. Requires AllowOnWater." );
-      addField( "AllowedTerrainSlope", TypeS32,       Offset( mFieldData.mAllowedTerrainSlope,  fxFoliageReplicator ), "Maximum surface angle allowed for foliage instances." );
+      addFieldV( "AllowedTerrainSlope", TypeRangedS32,       Offset( mFieldData.mAllowedTerrainSlope,  fxFoliageReplicator ), &CommonValidators::S32_PosDegreeRangeQuarter, "Maximum surface angle allowed for foliage instances." );
    endGroup( "Restrictions" );	// MM: Added Group Footer.
    endGroup( "Restrictions" );	// MM: Added Group Footer.
 
 
    addGroup( "AFX" );
    addGroup( "AFX" );
-      addField( "AmbientModulationBias", TypeF32,     Offset( mFieldData.mAmbientModulationBias,fxFoliageReplicator ), "Multiplier controling amount foliage is modulated by sun's ambient." );
+      addFieldV( "AmbientModulationBias", TypeRangedF32,     Offset( mFieldData.mAmbientModulationBias,fxFoliageReplicator ), &CommonValidators::NormalizedFloat, "Multiplier controling amount foliage is modulated by sun's ambient." );
    endGroup( "AFX" );
    endGroup( "AFX" );
    // Initialise parents' persistent fields.
    // Initialise parents' persistent fields.
    Parent::initPersistFields();
    Parent::initPersistFields();

+ 25 - 25
Engine/source/T3D/fx/fxShapeReplicator.cpp

@@ -680,30 +680,30 @@ U32 fxShapeReplicator::packUpdate(NetConnection * con, U32 mask, BitStream * str
    {
    {
       stream->writeAffineTransform(mObjToWorld);						// Replicator Position.
       stream->writeAffineTransform(mObjToWorld);						// Replicator Position.
 
 
-      stream->writeInt(mFieldData.mSeed, 32);							// Replicator Seed.
-      stream->writeInt(mFieldData.mShapeCount, 32);					// Shapes Count.
-      stream->writeInt(mFieldData.mShapeRetries, 32);					// Shapes Retries.
+      stream->write(mFieldData.mSeed);							// Replicator Seed.
+      stream->write(mFieldData.mShapeCount);					// Shapes Count.
+      stream->write(mFieldData.mShapeRetries);					// Shapes Retries.
       stream->writeString(mFieldData.mShapeFile);
       stream->writeString(mFieldData.mShapeFile);
-      stream->writeInt(mFieldData.mInnerRadiusX, 32);					// Shapes Inner Radius X.
-      stream->writeInt(mFieldData.mInnerRadiusY, 32);					// Shapes Inner Radius Y.
-      stream->writeInt(mFieldData.mOuterRadiusX, 32);					// Shapes Outer Radius X.
-      stream->writeInt(mFieldData.mOuterRadiusY, 32);					// Shapes Outer Radius Y.
+      stream->write(mFieldData.mInnerRadiusX);					// Shapes Inner Radius X.
+      stream->write(mFieldData.mInnerRadiusY);					// Shapes Inner Radius Y.
+      stream->write(mFieldData.mOuterRadiusX);					// Shapes Outer Radius X.
+      stream->write(mFieldData.mOuterRadiusY);					// Shapes Outer Radius Y.
       mathWrite(*stream, mFieldData.mShapeScaleMin);					// Shapes Scale Min.
       mathWrite(*stream, mFieldData.mShapeScaleMin);					// Shapes Scale Min.
       mathWrite(*stream, mFieldData.mShapeScaleMax);					// Shapes Scale Max.
       mathWrite(*stream, mFieldData.mShapeScaleMax);					// Shapes Scale Max.
       mathWrite(*stream, mFieldData.mShapeRotateMin);					// Shapes Rotate Min.
       mathWrite(*stream, mFieldData.mShapeRotateMin);					// Shapes Rotate Min.
       mathWrite(*stream, mFieldData.mShapeRotateMax);					// Shapes Rotate Max.
       mathWrite(*stream, mFieldData.mShapeRotateMax);					// Shapes Rotate Max.
-      stream->writeSignedInt(mFieldData.mOffsetZ, 32);				// Shapes Offset Z.
+      stream->write(mFieldData.mOffsetZ);				// Shapes Offset Z.
       stream->writeFlag(mFieldData.mAllowOnTerrain);					// Allow on Terrain.
       stream->writeFlag(mFieldData.mAllowOnTerrain);					// Allow on Terrain.
       stream->writeFlag(mFieldData.mAllowStatics);					// Allow on Statics.
       stream->writeFlag(mFieldData.mAllowStatics);					// Allow on Statics.
       stream->writeFlag(mFieldData.mAllowOnWater);					// Allow on Water.
       stream->writeFlag(mFieldData.mAllowOnWater);					// Allow on Water.
       stream->writeFlag(mFieldData.mAllowWaterSurface);				// Allow on Water Surface.
       stream->writeFlag(mFieldData.mAllowWaterSurface);				// Allow on Water Surface.
-      stream->writeSignedInt(mFieldData.mAllowedTerrainSlope, 32);	// Shapes Offset Z.
+      stream->write(mFieldData.mAllowedTerrainSlope);	// Shapes Offset Z.
       stream->writeFlag(mFieldData.mAlignToTerrain);					// Shapes AlignToTerrain.
       stream->writeFlag(mFieldData.mAlignToTerrain);					// Shapes AlignToTerrain.
       mathWrite(*stream, mFieldData.mTerrainAlignment);				// Write Terrain Alignment.
       mathWrite(*stream, mFieldData.mTerrainAlignment);				// Write Terrain Alignment.
       stream->writeFlag(mFieldData.mHideReplications);				// Hide Replications.
       stream->writeFlag(mFieldData.mHideReplications);				// Hide Replications.
       stream->writeFlag(mFieldData.mInteractions);					// Shape Interactions.
       stream->writeFlag(mFieldData.mInteractions);					// Shape Interactions.
       stream->writeFlag(mFieldData.mShowPlacementArea);				// Show Placement Area Flag.
       stream->writeFlag(mFieldData.mShowPlacementArea);				// Show Placement Area Flag.
-      stream->writeInt(mFieldData.mPlacementBandHeight, 32);			// Placement Area Height.
+      stream->write(mFieldData.mPlacementBandHeight);			// Placement Area Height.
       stream->write(mFieldData.mPlaceAreaColour);
       stream->write(mFieldData.mPlaceAreaColour);
    }
    }
 
 
@@ -725,30 +725,30 @@ void fxShapeReplicator::unpackUpdate(NetConnection * con, BitStream * stream)
 
 
       stream->readAffineTransform(&ReplicatorObjectMatrix);				// Replication Position.
       stream->readAffineTransform(&ReplicatorObjectMatrix);				// Replication Position.
 
 
-      mFieldData.mSeed					= stream->readInt(32);			// Replicator Seed.
-      mFieldData.mShapeCount				= stream->readInt(32);			// Shapes Count.
-      mFieldData.mShapeRetries			= stream->readInt(32);			// Shapes Retries.
+      stream->read(&mFieldData.mSeed);			               // Replicator Seed.
+      stream->read(&mFieldData.mShapeCount);			         // Shapes Count.
+      stream->read(&mFieldData.mShapeRetries);			         // Shapes Retries.
       mFieldData.mShapeFile				= stream->readSTString();		// Shape File.
       mFieldData.mShapeFile				= stream->readSTString();		// Shape File.
-      mFieldData.mInnerRadiusX			= stream->readInt(32);			// Shapes Inner Radius X.
-      mFieldData.mInnerRadiusY			= stream->readInt(32);			// Shapes Inner Radius Y.
-      mFieldData.mOuterRadiusX			= stream->readInt(32);			// Shapes Outer Radius X.
-      mFieldData.mOuterRadiusY			= stream->readInt(32);			// Shapes Outer Radius Y.
-      mathRead(*stream, &mFieldData.mShapeScaleMin);						// Shapes Scale Min.
-      mathRead(*stream, &mFieldData.mShapeScaleMax);						// Shapes Scale Max.
-      mathRead(*stream, &mFieldData.mShapeRotateMin);						// Shapes Rotate Min.
-      mathRead(*stream, &mFieldData.mShapeRotateMax);						// Shapes Rotate Max.
-      mFieldData.mOffsetZ					= stream->readSignedInt(32);	// Shapes Offset Z.
+      stream->read(&mFieldData.mInnerRadiusX);			         // Shapes Inner Radius X.
+      stream->read(&mFieldData.mInnerRadiusY);			         // Shapes Inner Radius Y.
+      stream->read(&mFieldData.mOuterRadiusX);			         // Shapes Outer Radius X.
+      stream->read(&mFieldData.mOuterRadiusY);			         // Shapes Outer Radius Y.
+      mathRead(*stream, &mFieldData.mShapeScaleMin);				   // Shapes Scale Min.
+      mathRead(*stream, &mFieldData.mShapeScaleMax);				   // Shapes Scale Max.
+      mathRead(*stream, &mFieldData.mShapeRotateMin);					// Shapes Rotate Min.
+      mathRead(*stream, &mFieldData.mShapeRotateMax);					// Shapes Rotate Max.
+      stream->read(&mFieldData.mOffsetZ);	// Shapes Offset Z.
       mFieldData.mAllowOnTerrain			= stream->readFlag();			// Allow on Terrain.
       mFieldData.mAllowOnTerrain			= stream->readFlag();			// Allow on Terrain.
       mFieldData.mAllowStatics			= stream->readFlag();			// Allow on Statics.
       mFieldData.mAllowStatics			= stream->readFlag();			// Allow on Statics.
       mFieldData.mAllowOnWater			= stream->readFlag();			// Allow on Water.
       mFieldData.mAllowOnWater			= stream->readFlag();			// Allow on Water.
       mFieldData.mAllowWaterSurface		= stream->readFlag();			// Allow on Water Surface.
       mFieldData.mAllowWaterSurface		= stream->readFlag();			// Allow on Water Surface.
-      mFieldData.mAllowedTerrainSlope		= stream->readSignedInt(32);	// Allowed Terrain Slope.
+      stream->read(&mFieldData.mAllowedTerrainSlope);	      // Allowed Terrain Slope.
       mFieldData.mAlignToTerrain			= stream->readFlag();			// Read AlignToTerrain.
       mFieldData.mAlignToTerrain			= stream->readFlag();			// Read AlignToTerrain.
-      mathRead(*stream, &mFieldData.mTerrainAlignment);					// Read Terrain Alignment.
+      mathRead(*stream, &mFieldData.mTerrainAlignment);			// Read Terrain Alignment.
       mFieldData.mHideReplications		= stream->readFlag();			// Hide Replications.
       mFieldData.mHideReplications		= stream->readFlag();			// Hide Replications.
       mFieldData.mInteractions			= stream->readFlag();			// Read Interactions.
       mFieldData.mInteractions			= stream->readFlag();			// Read Interactions.
       mFieldData.mShowPlacementArea	= stream->readFlag();				// Show Placement Area Flag.
       mFieldData.mShowPlacementArea	= stream->readFlag();				// Show Placement Area Flag.
-      mFieldData.mPlacementBandHeight	= stream->readInt(32);				// Placement Area Height.
+      stream->read(&mFieldData.mPlacementBandHeight);	// Placement Area Height.
       stream->read(&mFieldData.mPlaceAreaColour);
       stream->read(&mFieldData.mPlaceAreaColour);
 
 
       // Set Transform.
       // Set Transform.

+ 30 - 30
Engine/source/T3D/fx/groundCover.cpp

@@ -545,18 +545,18 @@ void GroundCover::initPersistFields()
 
 
       INITPERSISTFIELD_MATERIALASSET(Material, GroundCover, "Material used by all GroundCover segments.");
       INITPERSISTFIELD_MATERIALASSET(Material, GroundCover, "Material used by all GroundCover segments.");
 
 
-      addField( "radius",        TypeF32,          Offset( mRadius, GroundCover ),              "Outer generation radius from the current camera position." );
-      addField( "dissolveRadius",TypeF32,          Offset( mFadeRadius, GroundCover ),          "This is less than or equal to radius and defines when fading of cover elements begins." );
-      addField( "reflectScale",  TypeF32,          Offset( mReflectRadiusScale, GroundCover ),  "Scales the various culling radii when rendering a reflection. Typically for water." );
+      addFieldV( "radius", TypeRangedF32,          Offset( mRadius, GroundCover ), &CommonValidators::PositiveFloat,              "Outer generation radius from the current camera position." );
+      addFieldV( "dissolveRadius", TypeRangedF32,          Offset( mFadeRadius, GroundCover ), &CommonValidators::PositiveFloat,          "This is less than or equal to radius and defines when fading of cover elements begins." );
+      addFieldV( "reflectScale", TypeRangedF32,          Offset( mReflectRadiusScale, GroundCover ), &CommonValidators::PositiveFloat,  "Scales the various culling radii when rendering a reflection. Typically for water." );
 
 
-      addField( "gridSize",      TypeS32,          Offset( mGridSize, GroundCover ),            "The number of cells per axis in the grid." );
-      addField( "zOffset",       TypeF32,          Offset( mZOffset, GroundCover ),             "Offset along the Z axis to render the ground cover." );
+      addFieldV( "gridSize",      TypeRangedS32,          Offset( mGridSize, GroundCover ), &CommonValidators::PositiveInt,            "The number of cells per axis in the grid." );
+      addFieldV( "zOffset", TypeRangedF32,          Offset( mZOffset, GroundCover ), &CommonValidators::F32Range,             "Offset along the Z axis to render the ground cover." );
 
 
       addField( "seed",          TypeS32,          Offset( mRandomSeed, GroundCover ),          "This RNG seed is saved and sent to clients for generating the same cover." );
       addField( "seed",          TypeS32,          Offset( mRandomSeed, GroundCover ),          "This RNG seed is saved and sent to clients for generating the same cover." );
-      addField( "maxElements",   TypeS32,          Offset( mMaxPlacement, GroundCover ),        "The maximum amount of cover elements to include in the grid at any one time." );
+      addFieldV( "maxElements",   TypeRangedS32,          Offset( mMaxPlacement, GroundCover ), &CommonValidators::PositiveInt,        "The maximum amount of cover elements to include in the grid at any one time." );
 
 
-      addField( "maxBillboardTiltAngle", TypeF32,  Offset( mMaxBillboardTiltAngle, GroundCover ),"The maximum amout of degrees the billboard will tilt down to match the camera." );
-      addField( "shapeCullRadius", TypeF32,        Offset( mShapeCullRadius, GroundCover ),     "This is the distance at which DTS elements are  completely culled out." );      
+      addFieldV( "maxBillboardTiltAngle", TypeRangedF32,  Offset( mMaxBillboardTiltAngle, GroundCover ), &CommonValidators::PosDegreeRangeHalf,"The maximum amout of degrees the billboard will tilt down to match the camera." );
+      addFieldV( "shapeCullRadius", TypeRangedF32,        Offset( mShapeCullRadius, GroundCover ), &CommonValidators::PositiveFloat,     "This is the distance at which DTS elements are  completely culled out." );
       addField( "shapesCastShadows", TypeBool,     Offset( mShapesCastShadows, GroundCover ),   "Whether DTS elements should cast shadows or not." );
       addField( "shapesCastShadows", TypeBool,     Offset( mShapesCastShadows, GroundCover ),   "Whether DTS elements should cast shadows or not." );
 
 
       addArray( "Types", MAX_COVERTYPES );
       addArray( "Types", MAX_COVERTYPES );
@@ -570,37 +570,37 @@ void GroundCover::initPersistFields()
 
 
          addField( "invertLayer",   TypeBool,      Offset( mInvertLayer, GroundCover ), MAX_COVERTYPES,     "Indicates that the terrain material index given in 'layer' is an exclusion mask." );
          addField( "invertLayer",   TypeBool,      Offset( mInvertLayer, GroundCover ), MAX_COVERTYPES,     "Indicates that the terrain material index given in 'layer' is an exclusion mask." );
 
 
-         addField( "probability",   TypeF32,       Offset( mProbability, GroundCover ), MAX_COVERTYPES,     "The probability of one cover type verses another (relative to all cover types)." );
+         addFieldV( "probability",   TypeRangedF32,       Offset( mProbability, GroundCover ), &CommonValidators::PositiveFloat, MAX_COVERTYPES,     "The probability of one cover type verses another (relative to all cover types)." );
 
 
-         addField( "sizeMin",       TypeF32,       Offset( mSizeMin, GroundCover ), MAX_COVERTYPES,         "The minimum random size for each cover type." );
+         addFieldV( "sizeMin", TypeRangedF32,       Offset( mSizeMin, GroundCover ), &CommonValidators::PositiveFloat, MAX_COVERTYPES,         "The minimum random size for each cover type." );
 
 
-         addField( "sizeMax",       TypeF32,       Offset( mSizeMax, GroundCover ), MAX_COVERTYPES,         "The maximum random size of this cover type." );
+         addFieldV( "sizeMax", TypeRangedF32,       Offset( mSizeMax, GroundCover ), &CommonValidators::PositiveFloat, MAX_COVERTYPES,         "The maximum random size of this cover type." );
 
 
-         addField( "sizeExponent",  TypeF32,       Offset( mSizeExponent, GroundCover ), MAX_COVERTYPES,    "An exponent used to bias between the minimum and maximum random sizes." );
+         addFieldV( "sizeExponent", TypeRangedF32,       Offset( mSizeExponent, GroundCover ), &CommonValidators::PositiveFloat, MAX_COVERTYPES,    "An exponent used to bias between the minimum and maximum random sizes." );
 
 
-         addField( "windScale",     TypeF32,       Offset( mWindScale, GroundCover ), MAX_COVERTYPES,       "The wind effect scale." );
+         addFieldV( "windScale", TypeRangedF32,       Offset( mWindScale, GroundCover ), &CommonValidators::PositiveFloat, MAX_COVERTYPES,       "The wind effect scale." );
 
 
-		 addField( "minSlope",      TypeF32,       Offset(mMinSlope, GroundCover), MAX_COVERTYPES,          "The minimum slope angle in degrees for placement.");
+         addFieldV( "minSlope", TypeRangedF32,       Offset(mMinSlope, GroundCover), &CommonValidators::PosDegreeRangeQuarter, MAX_COVERTYPES,          "The minimum slope angle in degrees for placement.");
 
 
-         addField( "maxSlope",      TypeF32,       Offset( mMaxSlope, GroundCover ), MAX_COVERTYPES,        "The maximum slope angle in degrees for placement." );
+         addFieldV( "maxSlope", TypeRangedF32,       Offset( mMaxSlope, GroundCover ), &CommonValidators::PosDegreeRangeQuarter, MAX_COVERTYPES,        "The maximum slope angle in degrees for placement." );
 
 
 		 addField("conformToNormal",TypeBool,      Offset(mConformToNormal, GroundCover), MAX_COVERTYPES,   "Use the terrain's slope for angle");
 		 addField("conformToNormal",TypeBool,      Offset(mConformToNormal, GroundCover), MAX_COVERTYPES,   "Use the terrain's slope for angle");
-		 addField("minRotX",        TypeF32,       Offset(mMinRotX, GroundCover), MAX_COVERTYPES,           "minumum amount of rotation along the X axis to add");
-		 addField("maxRotX",        TypeF32,       Offset(mMaxRotX, GroundCover), MAX_COVERTYPES,           "maximum amount of rotation along the X axis to add");
-		 addField("minRotY",        TypeF32,       Offset(mMinRotY, GroundCover), MAX_COVERTYPES,           "minumum amount of rotation along the Y axis to add");
-		 addField("maxRotY",        TypeF32,       Offset(mMaxRotY, GroundCover), MAX_COVERTYPES,           "maximum amount of rotation along the Y axis to add");
+		 addFieldV("minRotX", TypeRangedF32,       Offset(mMinRotX, GroundCover), &CommonValidators::DegreeRange, MAX_COVERTYPES,           "minumum amount of rotation along the X axis to add");
+		 addFieldV("maxRotX", TypeRangedF32,       Offset(mMaxRotX, GroundCover), &CommonValidators::DegreeRange, MAX_COVERTYPES,           "maximum amount of rotation along the X axis to add");
+		 addFieldV("minRotY", TypeRangedF32,       Offset(mMinRotY, GroundCover), &CommonValidators::DegreeRange, MAX_COVERTYPES,           "minumum amount of rotation along the Y axis to add");
+		 addFieldV("maxRotY", TypeRangedF32,       Offset(mMaxRotY, GroundCover), &CommonValidators::DegreeRange, MAX_COVERTYPES,           "maximum amount of rotation along the Y axis to add");
 
 
-         addField( "minElevation",  TypeF32,       Offset( mMinElevation, GroundCover ), MAX_COVERTYPES,    "The minimum world space elevation for placement." );
+         addFieldV( "minElevation", TypeRangedF32,       Offset( mMinElevation, GroundCover ), &CommonValidators::F32Range, MAX_COVERTYPES,    "The minimum world space elevation for placement." );
 
 
-         addField( "maxElevation",  TypeF32,       Offset( mMaxElevation, GroundCover ), MAX_COVERTYPES,    "The maximum world space elevation for placement." );
+         addFieldV( "maxElevation", TypeRangedF32,       Offset( mMaxElevation, GroundCover ), &CommonValidators::F32Range, MAX_COVERTYPES,    "The maximum world space elevation for placement." );
 
 
-         addField( "minClumpCount", TypeS32,       Offset( mMinClumpCount, GroundCover ), MAX_COVERTYPES,   "The minimum amount of elements in a clump." );
+         addFieldV( "minClumpCount", TypeRangedS32,       Offset( mMinClumpCount, GroundCover ), &CommonValidators::PositiveInt, MAX_COVERTYPES,   "The minimum amount of elements in a clump." );
       
       
-         addField( "maxClumpCount", TypeS32,       Offset( mMaxClumpCount, GroundCover ), MAX_COVERTYPES,   "The maximum amount of elements in a clump." );
+         addFieldV( "maxClumpCount", TypeRangedS32,       Offset( mMaxClumpCount, GroundCover ), &CommonValidators::PositiveInt, MAX_COVERTYPES,   "The maximum amount of elements in a clump." );
 
 
-         addField( "clumpExponent", TypeF32,       Offset( mClumpCountExponent, GroundCover ), MAX_COVERTYPES, "An exponent used to bias between the minimum and maximum clump counts for a particular clump." );
+         addFieldV( "clumpExponent", TypeRangedF32,       Offset( mClumpCountExponent, GroundCover ), &CommonValidators::PositiveFloat, MAX_COVERTYPES, "An exponent used to bias between the minimum and maximum clump counts for a particular clump." );
 
 
-         addField( "clumpRadius",   TypeF32,       Offset( mClumpRadius, GroundCover ), MAX_COVERTYPES,     "The maximum clump radius." );
+         addFieldV( "clumpRadius", TypeRangedF32,       Offset( mClumpRadius, GroundCover ), &CommonValidators::PositiveFloat, MAX_COVERTYPES,     "The maximum clump radius." );
 
 
       endArray( "Types" );
       endArray( "Types" );
 
 
@@ -610,12 +610,12 @@ void GroundCover::initPersistFields()
 
 
       addField( "windDirection",    TypePoint2F,   Offset( mWindDirection, GroundCover ),             "The direction of the wind." );
       addField( "windDirection",    TypePoint2F,   Offset( mWindDirection, GroundCover ),             "The direction of the wind." );
 
 
-      addField( "windGustLength",   TypeF32,       Offset( mWindGustLength, GroundCover ),            "The length in meters between peaks in the wind gust." );
-      addField( "windGustFrequency",TypeF32,       Offset( mWindGustFrequency, GroundCover ),         "Controls how often the wind gust peaks per second." );
-      addField( "windGustStrength", TypeF32,       Offset( mWindGustStrength, GroundCover ),          "The maximum distance in meters that the peak wind  gust will displace an element." );
+      addFieldV( "windGustLength", TypeRangedF32,       Offset( mWindGustLength, GroundCover ), &CommonValidators::PositiveFloat,            "The length in meters between peaks in the wind gust." );
+      addFieldV( "windGustFrequency", TypeRangedF32,       Offset( mWindGustFrequency, GroundCover ), &CommonValidators::PositiveFloat,         "Controls how often the wind gust peaks per second." );
+      addFieldV( "windGustStrength", TypeRangedF32,       Offset( mWindGustStrength, GroundCover ), &CommonValidators::PositiveFloat,          "The maximum distance in meters that the peak wind  gust will displace an element." );
 
 
-      addField( "windTurbulenceFrequency",   TypeF32, Offset( mWindTurbulenceFrequency, GroundCover ),"Controls the overall rapidity of the wind turbulence." );
-      addField( "windTurbulenceStrength",    TypeF32, Offset( mWindTurbulenceStrength, GroundCover ), "The maximum distance in meters that the turbulence can displace a ground cover element." );
+      addFieldV( "windTurbulenceFrequency", TypeRangedF32, Offset( mWindTurbulenceFrequency, GroundCover ), &CommonValidators::PositiveFloat,"Controls the overall rapidity of the wind turbulence." );
+      addFieldV( "windTurbulenceStrength", TypeRangedF32, Offset( mWindTurbulenceStrength, GroundCover ), &CommonValidators::PositiveFloat, "The maximum distance in meters that the turbulence can displace a ground cover element." );
 
 
    endGroup( "GroundCover Wind" );
    endGroup( "GroundCover Wind" );
 
 

+ 5 - 5
Engine/source/T3D/fx/lightning.cpp

@@ -410,12 +410,12 @@ void Lightning::initPersistFields()
 {
 {
    docsURL;
    docsURL;
    addGroup( "Strikes" );
    addGroup( "Strikes" );
-   addField( "strikesPerMinute", TypeS32, Offset(strikesPerMinute, Lightning),
+   addFieldV( "strikesPerMinute", TypeRangedS32, Offset(strikesPerMinute, Lightning), &CommonValidators::PositiveInt,
       "@brief Number of lightning strikes to perform per minute.\n\n"
       "@brief Number of lightning strikes to perform per minute.\n\n"
       "Automatically invokes strikeRandomPoint() at regular intervals." );
       "Automatically invokes strikeRandomPoint() at regular intervals." );
-   addField( "strikeWidth", TypeF32, Offset(strikeWidth, Lightning),
+   addFieldV( "strikeWidth", TypeRangedF32, Offset(strikeWidth, Lightning), &CommonValidators::PositiveFloat,
       "Width of a lightning bolt." );
       "Width of a lightning bolt." );
-   addField( "strikeRadius", TypeF32, Offset(strikeRadius, Lightning),
+   addFieldV( "strikeRadius", TypeRangedF32, Offset(strikeRadius, Lightning), &CommonValidators::PositiveFloat,
       "@brief Horizontal size (XY plane) of the search box used to find and "
       "@brief Horizontal size (XY plane) of the search box used to find and "
       "damage Player or Vehicle objects within range of the strike.\n\n"
       "damage Player or Vehicle objects within range of the strike.\n\n"
       "Only the object at highest altitude with a clear line of sight to the "
       "Only the object at highest altitude with a clear line of sight to the "
@@ -431,9 +431,9 @@ void Lightning::initPersistFields()
    endGroup( "Colors" );
    endGroup( "Colors" );
 
 
    addGroup( "Bolts" );
    addGroup( "Bolts" );
-   addField( "chanceToHitTarget", TypeF32, Offset(chanceToHitTarget, Lightning),
+   addFieldV( "chanceToHitTarget", TypeRangedF32, Offset(chanceToHitTarget, Lightning), &CommonValidators::NormalizedFloat,
       "Percentage chance (0-1) that a given lightning bolt will hit something." );
       "Percentage chance (0-1) that a given lightning bolt will hit something." );
-   addField( "boltStartRadius", TypeF32, Offset(boltStartRadius, Lightning),
+   addFieldV( "boltStartRadius", TypeRangedF32, Offset(boltStartRadius, Lightning), &CommonValidators::PositiveFloat,
       "@brief Radial distance from the center of the Lightning object for the "
       "@brief Radial distance from the center of the Lightning object for the "
       "start point of the bolt.\n\n"
       "start point of the bolt.\n\n"
       "The actual start point will be a random point within this radius." );
       "The actual start point will be a random point within this radius." );

+ 39 - 26
Engine/source/T3D/fx/particle.cpp

@@ -141,6 +141,8 @@ ParticleData::ParticleData()
 FRangeValidator dragCoefFValidator(0.f, 5.f);
 FRangeValidator dragCoefFValidator(0.f, 5.f);
 FRangeValidator gravCoefFValidator(-10.f, 10.f);
 FRangeValidator gravCoefFValidator(-10.f, 10.f);
 FRangeValidator spinRandFValidator(-1000.f, 1000.f);
 FRangeValidator spinRandFValidator(-1000.f, 1000.f);
+FRangeValidator particleTimeFValidator(0.0f, 1.0f, 1<<8);
+FRangeValidator particleSizeFValidator(0.0f, MaxParticleSize, 1<<16);
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // initPersistFields
 // initPersistFields
@@ -160,31 +162,31 @@ void ParticleData::initPersistFields()
          "If true, particles blend like ParticleBlendStyle NORMAL, if false, "
          "If true, particles blend like ParticleBlendStyle NORMAL, if false, "
          "blend like ParticleBlendStyle ADDITIVE.\n"
          "blend like ParticleBlendStyle ADDITIVE.\n"
          "@note If ParticleEmitterData::blendStyle is set, it will override this value.");
          "@note If ParticleEmitterData::blendStyle is set, it will override this value.");
-      addField("lifetimeMS", TYPEID< S32 >(), Offset(lifetimeMS, ParticleData),
+      addFieldV("lifetimeMS", TypeRangedS32, Offset(lifetimeMS, ParticleData), &CommonValidators::PositiveInt,
          "Time in milliseconds before this particle is destroyed.");
          "Time in milliseconds before this particle is destroyed.");
-      addField("lifetimeVarianceMS", TYPEID< S32 >(), Offset(lifetimeVarianceMS, ParticleData),
+      addFieldV("lifetimeVarianceMS", TypeRangedS32, Offset(lifetimeVarianceMS, ParticleData), &CommonValidators::PositiveInt,
          "Variance in lifetime of particle, from 0 - lifetimeMS.");
          "Variance in lifetime of particle, from 0 - lifetimeMS.");
    endGroup("Basic");
    endGroup("Basic");
 
 
    addGroup("Motion");
    addGroup("Motion");
-      addFieldV("dragCoefficient", TYPEID< F32 >(), Offset(dragCoefficient, ParticleData), &dragCoefFValidator,
+      addFieldV("dragCoefficient", TypeRangedF32, Offset(dragCoefficient, ParticleData), &dragCoefFValidator,
          "Particle physics drag amount.");
          "Particle physics drag amount.");
-      addField("windCoefficient", TYPEID< F32 >(), Offset(windCoefficient, ParticleData),
+      addFieldV("windCoefficient", TypeRangedF32, Offset(windCoefficient, ParticleData),&CommonValidators::F32Range,
          "Strength of wind on the particles.");
          "Strength of wind on the particles.");
-      addFieldV("gravityCoefficient", TYPEID< F32 >(), Offset(gravityCoefficient, ParticleData), &gravCoefFValidator,
+      addFieldV("gravityCoefficient", TypeRangedF32, Offset(gravityCoefficient, ParticleData), &gravCoefFValidator,
          "Strength of gravity on the particles.");
          "Strength of gravity on the particles.");
-      addFieldV("inheritedVelFactor", TYPEID< F32 >(), Offset(inheritedVelFactor, ParticleData), &CommonValidators::NormalizedFloat,
+      addFieldV("inheritedVelFactor", TypeRangedF32, Offset(inheritedVelFactor, ParticleData), &CommonValidators::NormalizedFloat,
          "Amount of emitter velocity to add to particle initial velocity.");
          "Amount of emitter velocity to add to particle initial velocity.");
-      addField("constantAcceleration", TYPEID< F32 >(), Offset(constantAcceleration, ParticleData),
+      addFieldV("constantAcceleration", TypeRangedF32, Offset(constantAcceleration, ParticleData), &CommonValidators::F32Range,
          "Constant acceleration to apply to this particle.");
          "Constant acceleration to apply to this particle.");
    endGroup("Motion");
    endGroup("Motion");
    
    
    addGroup("Spin");
    addGroup("Spin");
-      addField("spinSpeed", TYPEID< F32 >(), Offset(spinSpeed, ParticleData),
+      addFieldV("spinSpeed", TypeRangedF32, Offset(spinSpeed, ParticleData), &spinRandFValidator,
          "Speed at which to spin the particle.");
          "Speed at which to spin the particle.");
-      addFieldV("spinRandomMin", TYPEID< F32 >(), Offset(spinRandomMin, ParticleData), &spinRandFValidator,
+      addFieldV("spinRandomMin", TypeRangedF32, Offset(spinRandomMin, ParticleData), &spinRandFValidator,
          "Minimum allowed spin speed of this particle, between -1000 and spinRandomMax.");
          "Minimum allowed spin speed of this particle, between -1000 and spinRandomMax.");
-      addFieldV("spinRandomMax", TYPEID< F32 >(), Offset(spinRandomMax, ParticleData), &spinRandFValidator,
+      addFieldV("spinRandomMax", TypeRangedF32, Offset(spinRandomMax, ParticleData), &spinRandFValidator,
          "Maximum allowed spin speed of this particle, between spinRandomMin and 1000.");
          "Maximum allowed spin speed of this particle, between spinRandomMin and 1000.");
    endGroup("Spin");
    endGroup("Spin");
   
   
@@ -223,16 +225,16 @@ void ParticleData::initPersistFields()
 
 
    // Interpolation variables
    // Interpolation variables
    addGroup("Over Time");
    addGroup("Over Time");
-      addProtectedField("times", TYPEID< F32 >(), Offset(times, ParticleData), &protectedSetTimes,
-         &defaultProtectedGetFn, PDC_NUM_KEYS,
+      addProtectedFieldV("times", TypeRangedF32, Offset(times, ParticleData), &protectedSetTimes,
+         &defaultProtectedGetFn, &particleTimeFValidator, PDC_NUM_KEYS,
          "@brief Time keys used with the colors and sizes keyframes.\n\n"
          "@brief Time keys used with the colors and sizes keyframes.\n\n"
          "Values are from 0.0 (particle creation) to 1.0 (end of lifespace).");
          "Values are from 0.0 (particle creation) to 1.0 (end of lifespace).");
       addField( "colors", TYPEID< LinearColorF >(), Offset(colors, ParticleData), PDC_NUM_KEYS,
       addField( "colors", TYPEID< LinearColorF >(), Offset(colors, ParticleData), PDC_NUM_KEYS,
          "@brief Particle RGBA color keyframe values.\n\n"
          "@brief Particle RGBA color keyframe values.\n\n"
          "The particle color will linearly interpolate between the color/time keys "
          "The particle color will linearly interpolate between the color/time keys "
          "over the lifetime of the particle." );
          "over the lifetime of the particle." );
-      addProtectedField( "sizes", TYPEID< F32 >(), Offset(sizes, ParticleData), &protectedSetSizes, 
-         &defaultProtectedGetFn, PDC_NUM_KEYS,
+      addProtectedFieldV( "sizes", TypeRangedF32, Offset(sizes, ParticleData), &protectedSetSizes,
+         &defaultProtectedGetFn, &particleSizeFValidator, PDC_NUM_KEYS,
          "@brief Particle size keyframe values.\n\n"
          "@brief Particle size keyframe values.\n\n"
          "The particle size will linearly interpolate between the size/time keys "
          "The particle size will linearly interpolate between the size/time keys "
          "over the lifetime of the particle." );
          "over the lifetime of the particle." );
@@ -242,10 +244,10 @@ void ParticleData::initPersistFields()
       addProtectedField("textureExtName", TypeFilename, Offset(mTextureExtName,     ParticleData), _setTextureExtData, &defaultProtectedGetFn, "", AbstractClassRep::FIELD_HideInInspectors);
       addProtectedField("textureExtName", TypeFilename, Offset(mTextureExtName,     ParticleData), _setTextureExtData, &defaultProtectedGetFn, "", AbstractClassRep::FIELD_HideInInspectors);
       INITPERSISTFIELD_IMAGEASSET(TextureExt, ParticleData, "");
       INITPERSISTFIELD_IMAGEASSET(TextureExt, ParticleData, "");
       addField("constrainPos",         TypeBool,     Offset(constrain_pos,      ParticleData));
       addField("constrainPos",         TypeBool,     Offset(constrain_pos,      ParticleData));
-      addField("angle",                TypeF32,      Offset(start_angle,        ParticleData));
-      addField("angleVariance",        TypeF32,      Offset(angle_variance,     ParticleData));
-      addField("sizeBias",             TypeF32,      Offset(sizeBias,           ParticleData));
-      addField("spinBias",             TypeF32,      Offset(spinBias,           ParticleData));
+      addFieldV("angle", TypeRangedF32,      Offset(start_angle,        ParticleData), &CommonValidators::DegreeRange);
+      addFieldV("angleVariance", TypeRangedF32,      Offset(angle_variance,     ParticleData), &CommonValidators::DegreeRange);
+      addFieldV("sizeBias", TypeRangedF32,      Offset(sizeBias,           ParticleData), &CommonValidators::F32Range);
+      addFieldV("spinBias", TypeRangedF32,      Offset(spinBias,           ParticleData), &CommonValidators::F32Range);
       addField("randomizeSpinDir",     TypeBool,     Offset(randomizeSpinDir,   ParticleData));
       addField("randomizeSpinDir",     TypeBool,     Offset(randomizeSpinDir,   ParticleData));
    endGroup("AFX"); 
    endGroup("AFX"); 
    Parent::initPersistFields();
    Parent::initPersistFields();
@@ -296,10 +298,10 @@ void ParticleData::packData(BitStream* stream)
 
 
    for( i=0; i<count; i++ )
    for( i=0; i<count; i++ )
    {
    {
-      stream->writeFloat( colors[i].red, 7);
-      stream->writeFloat( colors[i].green, 7);
-      stream->writeFloat( colors[i].blue, 7);
-      stream->writeFloat( colors[i].alpha, 7);
+      stream->writeFloat( colors[i].red, 8);
+      stream->writeFloat( colors[i].green, 8);
+      stream->writeFloat( colors[i].blue, 8);
+      stream->writeFloat( colors[i].alpha, 8);
       // AFX bits raised from 14 to 16 to allow larger sizes
       // AFX bits raised from 14 to 16 to allow larger sizes
       stream->writeFloat( sizes[i]/MaxParticleSize, 16);
       stream->writeFloat( sizes[i]/MaxParticleSize, 16);
       stream->writeFloat( times[i], 8);
       stream->writeFloat( times[i], 8);
@@ -381,10 +383,10 @@ void ParticleData::unpackData(BitStream* stream)
    S32 count = stream->readInt(3) + 1;
    S32 count = stream->readInt(3) + 1;
    for(i = 0;i < count; i++)
    for(i = 0;i < count; i++)
    {
    {
-      colors[i].red = stream->readFloat(7);
-      colors[i].green = stream->readFloat(7);
-      colors[i].blue = stream->readFloat(7);
-      colors[i].alpha = stream->readFloat(7);
+      colors[i].red = stream->readFloat(8);
+      colors[i].green = stream->readFloat(8);
+      colors[i].blue = stream->readFloat(8);
+      colors[i].alpha = stream->readFloat(8);
       // AFX bits raised from 14 to 16 to allow larger sizes
       // AFX bits raised from 14 to 16 to allow larger sizes
       sizes[i] = stream->readFloat(16) * MaxParticleSize;
       sizes[i] = stream->readFloat(16) * MaxParticleSize;
       times[i] = stream->readFloat(8);
       times[i] = stream->readFloat(8);
@@ -443,6 +445,17 @@ bool ParticleData::protectedSetTimes( void *object, const char *index, const cha
 
 
    pData->times[i] = mClampF( val, 0.f, 1.f );
    pData->times[i] = mClampF( val, 0.f, 1.f );
 
 
+   pData->times[0] = 0.0f;
+
+   S32 last = i - 1;
+   S32 next = i + 1;
+   if (last >= 0 && next < PDC_NUM_KEYS-1)
+   {
+      if ((pData->times[last] != -1.0f) && (pData->times[i] < pData->times[last]))
+         pData->times[i] = pData->times[last];
+      else if ((pData->times[next] != -1.0f) && (pData->times[i] > pData->times[next]))
+         pData->times[i] = pData->times[next];
+   }
    return false;
    return false;
 }
 }
 
 

+ 16 - 18
Engine/source/T3D/fx/particleEmitter.cpp

@@ -199,8 +199,6 @@ IRangeValidator ejectPeriodIValidator(1, 2047);
 IRangeValidator periodVarianceIValidator(0, 2047);
 IRangeValidator periodVarianceIValidator(0, 2047);
 FRangeValidator ejectionFValidator(0.f, 655.35f);
 FRangeValidator ejectionFValidator(0.f, 655.35f);
 FRangeValidator velVarianceFValidator(0.f, 163.83f);
 FRangeValidator velVarianceFValidator(0.f, 163.83f);
-FRangeValidator thetaFValidator(0.f, 180.f);
-FRangeValidator phiFValidator(0.f, 360.f);
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // initPersistFields
 // initPersistFields
@@ -210,45 +208,45 @@ void ParticleEmitterData::initPersistFields()
    docsURL;
    docsURL;
    addGroup( "ParticleEmitterData" );
    addGroup( "ParticleEmitterData" );
 
 
-      addFieldV("ejectionPeriodMS", TYPEID< S32 >(), Offset(ejectionPeriodMS,   ParticleEmitterData), &ejectPeriodIValidator,
+      addFieldV("ejectionPeriodMS", TypeRangedS32, Offset(ejectionPeriodMS,   ParticleEmitterData), &ejectPeriodIValidator,
          "Time (in milliseconds) between each particle ejection." );
          "Time (in milliseconds) between each particle ejection." );
 
 
-      addFieldV("periodVarianceMS", TYPEID< S32 >(), Offset(periodVarianceMS,   ParticleEmitterData), &periodVarianceIValidator,
+      addFieldV("periodVarianceMS", TypeRangedS32, Offset(periodVarianceMS,   ParticleEmitterData), &periodVarianceIValidator,
          "Variance in ejection period, from 1 - ejectionPeriodMS." );
          "Variance in ejection period, from 1 - ejectionPeriodMS." );
 
 
-      addFieldV( "ejectionVelocity", TYPEID< F32 >(), Offset(ejectionVelocity, ParticleEmitterData), &ejectionFValidator,
+      addFieldV( "ejectionVelocity", TypeRangedF32, Offset(ejectionVelocity, ParticleEmitterData), &ejectionFValidator,
          "Particle ejection velocity." );
          "Particle ejection velocity." );
 
 
-      addFieldV( "velocityVariance", TYPEID< F32 >(), Offset(velocityVariance, ParticleEmitterData), &velVarianceFValidator,
+      addFieldV( "velocityVariance", TypeRangedF32, Offset(velocityVariance, ParticleEmitterData), &velVarianceFValidator,
          "Variance for ejection velocity, from 0 - ejectionVelocity." );
          "Variance for ejection velocity, from 0 - ejectionVelocity." );
 
 
-      addFieldV( "ejectionOffset", TYPEID< F32 >(), Offset(ejectionOffset, ParticleEmitterData), &ejectionFValidator,
+      addFieldV( "ejectionOffset", TypeRangedF32, Offset(ejectionOffset, ParticleEmitterData), &ejectionFValidator,
          "Distance along ejection Z axis from which to eject particles." );
          "Distance along ejection Z axis from which to eject particles." );
 		 
 		 
-      addFieldV( "ejectionOffsetVariance", TYPEID< F32 >(), Offset(ejectionOffsetVariance, ParticleEmitterData), &ejectionFValidator,
+      addFieldV( "ejectionOffsetVariance", TypeRangedF32, Offset(ejectionOffsetVariance, ParticleEmitterData), &ejectionFValidator,
          "Distance Padding along ejection Z axis from which to eject particles." );
          "Distance Padding along ejection Z axis from which to eject particles." );
 
 
-      addFieldV( "thetaMin", TYPEID< F32 >(), Offset(thetaMin, ParticleEmitterData), &thetaFValidator,
+      addFieldV( "thetaMin", TypeRangedF32, Offset(thetaMin, ParticleEmitterData), &CommonValidators::PosDegreeRangeHalf,
          "Minimum angle, from the horizontal plane, to eject from." );
          "Minimum angle, from the horizontal plane, to eject from." );
 
 
-      addFieldV( "thetaMax", TYPEID< F32 >(), Offset(thetaMax, ParticleEmitterData), &thetaFValidator,
+      addFieldV( "thetaMax", TypeRangedF32, Offset(thetaMax, ParticleEmitterData), &CommonValidators::PosDegreeRangeHalf,
          "Maximum angle, from the horizontal plane, to eject particles from." );
          "Maximum angle, from the horizontal plane, to eject particles from." );
 
 
-	  addFieldV( "thetaVariance", TYPEID< F32 >(), Offset(thetaVariance, ParticleEmitterData), &thetaFValidator,
+	  addFieldV( "thetaVariance", TypeRangedF32, Offset(thetaVariance, ParticleEmitterData), &CommonValidators::PosDegreeRangeHalf,
          "Angle variance from the previous particle, from 0 - 180." );
          "Angle variance from the previous particle, from 0 - 180." );
 
 
-      addFieldV( "phiReferenceVel", TYPEID< F32 >(), Offset(phiReferenceVel, ParticleEmitterData), &phiFValidator,
+      addFieldV( "phiReferenceVel", TypeRangedF32, Offset(phiReferenceVel, ParticleEmitterData), &CommonValidators::PosDegreeRange,
          "Reference angle, from the vertical plane, to eject particles from." );
          "Reference angle, from the vertical plane, to eject particles from." );
 
 
-      addFieldV( "phiVariance", TYPEID< F32 >(), Offset(phiVariance, ParticleEmitterData), &phiFValidator,
+      addFieldV( "phiVariance", TypeRangedF32, Offset(phiVariance, ParticleEmitterData), &CommonValidators::PosDegreeRange,
          "Variance from the reference angle, from 0 - 360." );
          "Variance from the reference angle, from 0 - 360." );
 
 
-      addField( "softnessDistance", TYPEID< F32 >(), Offset(softnessDistance, ParticleEmitterData),
+      addFieldV( "softnessDistance", TypeRangedF32, Offset(softnessDistance, ParticleEmitterData), &CommonValidators::PositiveFloat,
          "For soft particles, the distance (in meters) where particles will be "
          "For soft particles, the distance (in meters) where particles will be "
          "faded based on the difference in depth between the particle and the "
          "faded based on the difference in depth between the particle and the "
          "scene geometry." );
          "scene geometry." );
 
 
-      addField( "ambientFactor", TYPEID< F32 >(), Offset(ambientFactor, ParticleEmitterData),
+      addFieldV( "ambientFactor", TypeRangedF32, Offset(ambientFactor, ParticleEmitterData), &CommonValidators::NormalizedFloat,
          "Used to generate the final particle color by controlling interpolation "
          "Used to generate the final particle color by controlling interpolation "
          "between the particle color and the particle color multiplied by the "
          "between the particle color and the particle color multiplied by the "
          "ambient light color." );
          "ambient light color." );
@@ -272,10 +270,10 @@ void ParticleEmitterData::initPersistFields()
          "A random one of these datablocks is selected each time a particle is "
          "A random one of these datablocks is selected each time a particle is "
          "emitted." );
          "emitted." );
 
 
-      addField( "lifetimeMS", TYPEID< S32 >(), Offset(lifetimeMS, ParticleEmitterData),
+      addFieldV( "lifetimeMS", TypeRangedS32, Offset(lifetimeMS, ParticleEmitterData), &CommonValidators::PositiveInt,
          "Lifetime of emitted particles (in milliseconds)." );
          "Lifetime of emitted particles (in milliseconds)." );
 
 
-      addField("lifetimeVarianceMS", TYPEID< S32 >(), Offset(lifetimeVarianceMS, ParticleEmitterData),
+      addFieldV("lifetimeVarianceMS", TypeRangedS32, Offset(lifetimeVarianceMS, ParticleEmitterData), &CommonValidators::PositiveInt,
          "Variance in particle lifetime from 0 - lifetimeMS." );
          "Variance in particle lifetime from 0 - lifetimeMS." );
 
 
       addField( "useEmitterSizes", TYPEID< bool >(), Offset(useEmitterSizes, ParticleEmitterData),
       addField( "useEmitterSizes", TYPEID< bool >(), Offset(useEmitterSizes, ParticleEmitterData),
@@ -338,7 +336,7 @@ void ParticleEmitterData::initPersistFields()
 #if defined(AFX_CAP_PARTICLE_POOLS)
 #if defined(AFX_CAP_PARTICLE_POOLS)
    addGroup("AFX Pooled Particles");
    addGroup("AFX Pooled Particles");
    addField("poolData", TYPEID<afxParticlePoolData>(), Offset(pool_datablock, ParticleEmitterData));
    addField("poolData", TYPEID<afxParticlePoolData>(), Offset(pool_datablock, ParticleEmitterData));
-   addField("poolIndex",            TypeS32,                      Offset(pool_index,        ParticleEmitterData));
+   addFieldV("poolIndex",            TypeRangedS32,                      Offset(pool_index,        ParticleEmitterData), &CommonValidators::PositiveInt);
    addField("poolDepthFade",        TypeBool,                     Offset(pool_depth_fade,   ParticleEmitterData));
    addField("poolDepthFade",        TypeBool,                     Offset(pool_depth_fade,   ParticleEmitterData));
    addField("poolRadialFade",       TypeBool,                     Offset(pool_radial_fade,  ParticleEmitterData));
    addField("poolRadialFade",       TypeBool,                     Offset(pool_radial_fade,  ParticleEmitterData));
    endGroup("AFX Pooled Particles");
    endGroup("AFX Pooled Particles");

+ 1 - 1
Engine/source/T3D/fx/particleEmitter.h

@@ -98,7 +98,7 @@ class ParticleEmitterData : public GameBaseData
    F32 ambientFactor;
    F32 ambientFactor;
 
 
    S32   lifetimeMS;                         ///< Lifetime of particles
    S32   lifetimeMS;                         ///< Lifetime of particles
-   U32   lifetimeVarianceMS;                 ///< Varience in lifetime from 0 to n
+   S32   lifetimeVarianceMS;                 ///< Varience in lifetime from 0 to n
 
 
    bool  overrideAdvance;                    ///<
    bool  overrideAdvance;                    ///<
    bool  orientParticles;                    ///< Particles always face the screen
    bool  orientParticles;                    ///< Particles always face the screen

+ 3 - 2
Engine/source/T3D/fx/particleEmitterNode.cpp

@@ -87,10 +87,11 @@ ParticleEmitterNodeData::~ParticleEmitterNodeData()
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // initPersistFields
 // initPersistFields
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
+FRangeValidator emTimeMultipleRange(0.01f,100.0f);
 void ParticleEmitterNodeData::initPersistFields()
 void ParticleEmitterNodeData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-   addField( "timeMultiple", TYPEID< F32 >(), Offset(timeMultiple, ParticleEmitterNodeData),
+   addFieldV( "timeMultiple", TypeRangedF32, Offset(timeMultiple, ParticleEmitterNodeData), &emTimeMultipleRange,
       "@brief Time multiplier for particle emitter nodes.\n\n"
       "@brief Time multiplier for particle emitter nodes.\n\n"
       "Increasing timeMultiple is like running the emitter at a faster rate - single-shot "
       "Increasing timeMultiple is like running the emitter at a faster rate - single-shot "
       "emitters will complete in a shorter time, and continuous emitters will generate "
       "emitters will complete in a shorter time, and continuous emitters will generate "
@@ -187,7 +188,7 @@ void ParticleEmitterNode::initPersistFields()
       "Controls whether particles are emitted from this node." );
       "Controls whether particles are emitted from this node." );
    addField( "emitter",  TYPEID< ParticleEmitterData >(), Offset(mEmitterDatablock, ParticleEmitterNode),
    addField( "emitter",  TYPEID< ParticleEmitterData >(), Offset(mEmitterDatablock, ParticleEmitterNode),
       "Datablock to use when emitting particles." );
       "Datablock to use when emitting particles." );
-   addField( "velocity", TYPEID< F32 >(), Offset(mVelocity, ParticleEmitterNode),
+   addFieldV( "velocity", TypeRangedF32, Offset(mVelocity, ParticleEmitterNode), &CommonValidators::F32Range,
       "Velocity to use when emitting particles (in the direction of the "
       "Velocity to use when emitting particles (in the direction of the "
       "ParticleEmitterNode object's up (Z) axis)." );
       "ParticleEmitterNode object's up (Z) axis)." );
 
 

+ 17 - 17
Engine/source/T3D/fx/precipitation.cpp

@@ -173,11 +173,11 @@ void PrecipitationData::initPersistFields()
 
 
    addField( "splashShader", TypeString, Offset(mSplashShaderName, PrecipitationData),
    addField( "splashShader", TypeString, Offset(mSplashShaderName, PrecipitationData),
       "The name of the shader used for splashes." );
       "The name of the shader used for splashes." );
-   addField( "dropsPerSide", TypeS32, Offset(mDropsPerSide, PrecipitationData),
+   addFieldV( "dropsPerSide", TypeRangedS32, Offset(mDropsPerSide, PrecipitationData), &CommonValidators::PositiveInt,
       "@brief How many rows and columns are in the raindrop texture.\n\n"
       "@brief How many rows and columns are in the raindrop texture.\n\n"
       "For example, if the texture has 16 raindrops arranged in a grid, this "
       "For example, if the texture has 16 raindrops arranged in a grid, this "
       "field should be set to 4." );
       "field should be set to 4." );
-   addField( "splashesPerSide", TypeS32, Offset(mSplashesPerSide, PrecipitationData),
+   addFieldV( "splashesPerSide", TypeRangedS32, Offset(mSplashesPerSide, PrecipitationData), &CommonValidators::PositiveInt,
       "@brief How many rows and columns are in the splash texture.\n\n"
       "@brief How many rows and columns are in the splash texture.\n\n"
       "For example, if the texture has 9 splashes arranged in a grid, this "
       "For example, if the texture has 9 splashes arranged in a grid, this "
       "field should be set to 3." );
       "field should be set to 3." );
@@ -368,45 +368,45 @@ void Precipitation::initPersistFields()
    docsURL;
    docsURL;
    addGroup("Precipitation");
    addGroup("Precipitation");
 
 
-      addFieldV( "numDrops", TypeS32, Offset(mNumDrops, Precipitation), &ValidNumDropsRange,
+      addFieldV( "numDrops", TypeRangedS32, Offset(mNumDrops, Precipitation), &ValidNumDropsRange,
          "@brief Maximum number of drops allowed to exist in the precipitation "
          "@brief Maximum number of drops allowed to exist in the precipitation "
          "box at any one time.\n\n"
          "box at any one time.\n\n"
          "The actual number of drops in the effect depends on the current "
          "The actual number of drops in the effect depends on the current "
          "percentage, which can change over time using modifyStorm()." );
          "percentage, which can change over time using modifyStorm()." );
 
 
-      addField( "boxWidth", TypeF32, Offset(mBoxWidth, Precipitation),
+      addFieldV( "boxWidth", TypeRangedF32, Offset(mBoxWidth, Precipitation), &CommonValidators::PositiveFloat,
          "Width and depth (horizontal dimensions) of the precipitation box." );
          "Width and depth (horizontal dimensions) of the precipitation box." );
 
 
-      addField( "boxHeight", TypeF32, Offset(mBoxHeight, Precipitation),
+      addFieldV( "boxHeight", TypeRangedF32, Offset(mBoxHeight, Precipitation), &CommonValidators::PositiveFloat,
          "Height (vertical dimension) of the precipitation box." );
          "Height (vertical dimension) of the precipitation box." );
 
 
    endGroup("Precipitation");
    endGroup("Precipitation");
 
 
    addGroup("Rendering");
    addGroup("Rendering");
 
 
-      addField( "dropSize", TypeF32, Offset(mDropSize, Precipitation),
+      addFieldV( "dropSize", TypeRangedF32, Offset(mDropSize, Precipitation), &CommonValidators::PositiveFloat,
          "Size of each drop of precipitation. This will scale the texture." );
          "Size of each drop of precipitation. This will scale the texture." );
 
 
-      addField( "splashSize", TypeF32, Offset(mSplashSize, Precipitation),
+      addFieldV( "splashSize", TypeRangedF32, Offset(mSplashSize, Precipitation), &CommonValidators::PositiveFloat,
          "Size of each splash animation when a drop collides with another surface." );
          "Size of each splash animation when a drop collides with another surface." );
 
 
-      addField( "splashMS", TypeS32, Offset(mSplashMS, Precipitation),
+      addFieldV( "splashMS", TypeRangedS32, Offset(mSplashMS, Precipitation), &CommonValidators::PositiveInt,
          "Lifetime of splashes in milliseconds." );
          "Lifetime of splashes in milliseconds." );
 
 
       addField( "animateSplashes", TypeBool, Offset(mAnimateSplashes, Precipitation),
       addField( "animateSplashes", TypeBool, Offset(mAnimateSplashes, Precipitation),
          "Set to true to enable splash animations when drops collide with other surfaces." );
          "Set to true to enable splash animations when drops collide with other surfaces." );
 
 
-      addField( "dropAnimateMS", TypeS32, Offset(mDropAnimateMS, Precipitation),
+      addFieldV( "dropAnimateMS", TypeRangedS32, Offset(mDropAnimateMS, Precipitation), &CommonValidators::PositiveInt,
          "@brief Length (in milliseconds) to display each drop frame.\n\n"
          "@brief Length (in milliseconds) to display each drop frame.\n\n"
          "If #dropAnimateMS <= 0, drops select a single random frame at creation "
          "If #dropAnimateMS <= 0, drops select a single random frame at creation "
          "that does not change throughout the drop's lifetime. If #dropAnimateMS "
          "that does not change throughout the drop's lifetime. If #dropAnimateMS "
          "> 0, each drop cycles through the the available frames in the drop "
          "> 0, each drop cycles through the the available frames in the drop "
          "texture at the given rate." );
          "texture at the given rate." );
 
 
-      addField( "fadeDist", TypeF32, Offset(mFadeDistance, Precipitation),
+      addFieldV( "fadeDist", TypeRangedF32, Offset(mFadeDistance, Precipitation), &CommonValidators::PositiveFloat,
          "The distance at which drops begin to fade out." );
          "The distance at which drops begin to fade out." );
 
 
-      addField( "fadeDistEnd", TypeF32, Offset(mFadeDistanceEnd, Precipitation),
+      addFieldV( "fadeDistEnd", TypeRangedF32, Offset(mFadeDistanceEnd, Precipitation), &CommonValidators::PositiveFloat,
          "The distance at which drops are completely faded out." );
          "The distance at which drops are completely faded out." );
 
 
       addField( "useTrueBillboards", TypeBool, Offset(mUseTrueBillboards, Precipitation),
       addField( "useTrueBillboards", TypeBool, Offset(mUseTrueBillboards, Precipitation),
@@ -459,23 +459,23 @@ void Precipitation::initPersistFields()
          "Controls whether drops are affected by wind.\n"
          "Controls whether drops are affected by wind.\n"
          "@see ForestWindEmitter" );
          "@see ForestWindEmitter" );
 
 
-      addField( "minSpeed", TypeF32, Offset(mMinSpeed, Precipitation),
+      addFieldV( "minSpeed", TypeRangedF32, Offset(mMinSpeed, Precipitation), &CommonValidators::PositiveFloat,
          "@brief Minimum speed at which a drop will fall.\n\n"
          "@brief Minimum speed at which a drop will fall.\n\n"
          "On creation, the drop will be assigned a random speed between #minSpeed "
          "On creation, the drop will be assigned a random speed between #minSpeed "
          "and #maxSpeed." );
          "and #maxSpeed." );
 
 
-      addField( "maxSpeed", TypeF32, Offset(mMaxSpeed, Precipitation),
+      addFieldV( "maxSpeed", TypeRangedF32, Offset(mMaxSpeed, Precipitation), &CommonValidators::PositiveFloat,
          "@brief Maximum speed at which a drop will fall.\n\n"
          "@brief Maximum speed at which a drop will fall.\n\n"
          "On creation, the drop will be assigned a random speed between #minSpeed "
          "On creation, the drop will be assigned a random speed between #minSpeed "
          "and #maxSpeed." );
          "and #maxSpeed." );
 
 
-      addField( "minMass", TypeF32, Offset(mMinMass, Precipitation),
+      addFieldV( "minMass", TypeRangedF32, Offset(mMinMass, Precipitation), &CommonValidators::PositiveFloat,
          "@brief Minimum mass of a drop.\n\n"
          "@brief Minimum mass of a drop.\n\n"
          "Drop mass determines how strongly the drop is affected by wind and "
          "Drop mass determines how strongly the drop is affected by wind and "
          "turbulence. On creation, the drop will be assigned a random speed "
          "turbulence. On creation, the drop will be assigned a random speed "
          "between #minMass and #minMass." );
          "between #minMass and #minMass." );
 
 
-      addField( "maxMass", TypeF32, Offset(mMaxMass, Precipitation),
+      addFieldV( "maxMass", TypeRangedF32, Offset(mMaxMass, Precipitation), &CommonValidators::PositiveFloat,
          "@brief Maximum mass of a drop.\n\n"
          "@brief Maximum mass of a drop.\n\n"
          "Drop mass determines how strongly the drop is affected by wind and "
          "Drop mass determines how strongly the drop is affected by wind and "
          "turbulence. On creation, the drop will be assigned a random speed "
          "turbulence. On creation, the drop will be assigned a random speed "
@@ -489,10 +489,10 @@ void Precipitation::initPersistFields()
          "Check to enable turbulence. This causes precipitation drops to spiral "
          "Check to enable turbulence. This causes precipitation drops to spiral "
          "while falling." );
          "while falling." );
 
 
-      addField( "maxTurbulence", TypeF32, Offset(mMaxTurbulence, Precipitation),
+      addFieldV( "maxTurbulence", TypeRangedF32, Offset(mMaxTurbulence, Precipitation), &CommonValidators::PositiveFloat,
          "Radius at which precipitation drops spiral when turbulence is enabled." );
          "Radius at which precipitation drops spiral when turbulence is enabled." );
 
 
-      addField( "turbulenceSpeed", TypeF32, Offset(mTurbulenceSpeed, Precipitation),
+      addFieldV( "turbulenceSpeed", TypeRangedF32, Offset(mTurbulenceSpeed, Precipitation), &CommonValidators::PositiveFloat,
          "Speed at which precipitation drops spiral when turbulence is enabled." );
          "Speed at which precipitation drops spiral when turbulence is enabled." );
 
 
    endGroup("Turbulence");
    endGroup("Turbulence");

+ 7 - 7
Engine/source/T3D/fx/ribbon.cpp

@@ -73,27 +73,27 @@ void RibbonData::initPersistFields()
 
 
    addGroup("Ribbon");
    addGroup("Ribbon");
 
 
-   addField("size", TypeF32, Offset(mSizes, RibbonData), NumFields,
+   addFieldV("size", TypeRangedF32, Offset(mSizes, RibbonData), &CommonValidators::PositiveFloat, NumFields,
       "The size of the ribbon at the specified keyframe.");
       "The size of the ribbon at the specified keyframe.");
    addField("color", TypeColorF, Offset(mColours, RibbonData), NumFields,
    addField("color", TypeColorF, Offset(mColours, RibbonData), NumFields,
       "The colour of the ribbon at the specified keyframe.");
       "The colour of the ribbon at the specified keyframe.");
-   addField("position", TypeF32, Offset(mTimes, RibbonData), NumFields,
+   addFieldV("position", TypeRangedF32, Offset(mTimes, RibbonData), &CommonValidators::PositiveFloat, NumFields,
       "The position of the keyframe along the lifetime of the ribbon.");
       "The position of the keyframe along the lifetime of the ribbon.");
 
 
-   addField("ribbonLength", TypeS32, Offset(mRibbonLength, RibbonData),
+   addFieldV("ribbonLength", TypeRangedS32, Offset(mRibbonLength, RibbonData), &CommonValidators::NaturalNumber,
       "The amount of segments the Ribbon can maximally have in length.");
       "The amount of segments the Ribbon can maximally have in length.");
-   addField("segmentsPerUpdate", TypeS32, Offset(segmentsPerUpdate, RibbonData),
+   addFieldV("segmentsPerUpdate", TypeRangedS32, Offset(segmentsPerUpdate, RibbonData), &CommonValidators::NaturalNumber,
       "How many segments to add each update.");
       "How many segments to add each update.");
-   addField("skipAmount", TypeS32, Offset(mSegmentSkipAmount, RibbonData),
+   addFieldV("skipAmount", TypeRangedS32, Offset(mSegmentSkipAmount, RibbonData), &CommonValidators::PositiveInt,
       "The amount of segments to skip each update.");
       "The amount of segments to skip each update.");
 
 
    addField("useFadeOut", TypeBool, Offset(mUseFadeOut, RibbonData),
    addField("useFadeOut", TypeBool, Offset(mUseFadeOut, RibbonData),
       "If true, the ribbon will fade away after deletion.");
       "If true, the ribbon will fade away after deletion.");
-   addField("fadeAwayStep", TypeF32, Offset(mFadeAwayStep, RibbonData),
+   addFieldV("fadeAwayStep", TypeRangedF32, Offset(mFadeAwayStep, RibbonData), &CommonValidators::PositiveFloat,
       "How much to fade the ribbon with each update, after deletion.");
       "How much to fade the ribbon with each update, after deletion.");
    addField("ribbonMaterial", TypeString, Offset(mMatName, RibbonData),
    addField("ribbonMaterial", TypeString, Offset(mMatName, RibbonData),
       "The material the ribbon uses for rendering.");
       "The material the ribbon uses for rendering.");
-   addField("tileScale", TypeF32, Offset(mTileScale, RibbonData),
+   addFieldV("tileScale", TypeRangedF32, Offset(mTileScale, RibbonData), &CommonValidators::NormalizedFloat,
       "How much to scale each 'tile' with, where 1 means the material is stretched"
       "How much to scale each 'tile' with, where 1 means the material is stretched"
       "across the whole ribbon. (If TexcoordsRelativeToDistance is true, this is in meters.)");
       "across the whole ribbon. (If TexcoordsRelativeToDistance is true, this is in meters.)");
    addField("fixedTexcoords", TypeBool, Offset(mFixedTexcoords, RibbonData),
    addField("fixedTexcoords", TypeBool, Offset(mFixedTexcoords, RibbonData),

+ 16 - 16
Engine/source/T3D/fx/splash.cpp

@@ -121,26 +121,26 @@ void SplashData::initPersistFields()
 
 
    addField("scale",             TypePoint3F,                  Offset(scale,              SplashData), "The scale of this splashing effect, defined as the F32 points X, Y, Z.\n");
    addField("scale",             TypePoint3F,                  Offset(scale,              SplashData), "The scale of this splashing effect, defined as the F32 points X, Y, Z.\n");
    addField("emitter",           TYPEID< ParticleEmitterData >(),   Offset(emitterList,        SplashData), NUM_EMITTERS, "List of particle emitters to create at the point of this Splash effect.\n");
    addField("emitter",           TYPEID< ParticleEmitterData >(),   Offset(emitterList,        SplashData), NUM_EMITTERS, "List of particle emitters to create at the point of this Splash effect.\n");
-   addField("delayMS",           TypeS32,                      Offset(delayMS,            SplashData), "Time to delay, in milliseconds, before actually starting this effect.\n");
-   addField("delayVariance",     TypeS32,                      Offset(delayVariance,      SplashData), "Time variance for delayMS.\n");
-   addField("lifetimeMS",        TypeS32,                      Offset(lifetimeMS,         SplashData), "Lifetime for this effect, in milliseconds.\n");
-   addField("lifetimeVariance",  TypeS32,                      Offset(lifetimeVariance,   SplashData), "Time variance for lifetimeMS.\n");
-   addField("width",             TypeF32,                      Offset(width,              SplashData), "Width for the X and Y coordinates to create this effect within.");
-   addField("numSegments",       TypeS32,                      Offset(numSegments,        SplashData), "Number of ejection points in the splash ring.\n");
-   addField("velocity",          TypeF32,                      Offset(velocity,           SplashData), "Velocity for the splash effect to travel.\n");
-   addField("height",            TypeF32,                      Offset(height,             SplashData), "Height for the splash to reach.\n");
-   addField("acceleration",      TypeF32,                      Offset(acceleration,       SplashData), "Constant acceleration value to place upon the splash effect.\n");
-   addField("times",             TypeF32,                      Offset(times,              SplashData), NUM_TIME_KEYS, "Times to transition through the splash effect. Up to 4 allowed. Values are 0.0 - 1.0, and corrispond to the life of the particle where 0 is first created and 1 is end of lifespace.\n" );
+   addFieldV("delayMS", TypeRangedS32,                      Offset(delayMS,            SplashData), &CommonValidators::PositiveInt, "Time to delay, in milliseconds, before actually starting this effect.\n");
+   addFieldV("delayVariance", TypeRangedS32,                      Offset(delayVariance,      SplashData), &CommonValidators::PositiveInt, "Time variance for delayMS.\n");
+   addFieldV("lifetimeMS", TypeRangedS32,                      Offset(lifetimeMS,         SplashData), &CommonValidators::PositiveInt, "Lifetime for this effect, in milliseconds.\n");
+   addFieldV("lifetimeVariance", TypeRangedS32,                      Offset(lifetimeVariance,   SplashData), &CommonValidators::PositiveInt, "Time variance for lifetimeMS.\n");
+   addFieldV("width", TypeRangedF32,                      Offset(width,              SplashData), &CommonValidators::PositiveFloat, "Width for the X and Y coordinates to create this effect within.");
+   addFieldV("numSegments", TypeRangedS32,                      Offset(numSegments,        SplashData), &CommonValidators::NaturalNumber, "Number of ejection points in the splash ring.\n");
+   addFieldV("velocity", TypeRangedF32,                      Offset(velocity,           SplashData), &CommonValidators::PositiveFloat, "Velocity for the splash effect to travel.\n");
+   addFieldV("height", TypeRangedF32,                      Offset(height,             SplashData), &CommonValidators::PositiveFloat, "Height for the splash to reach.\n");
+   addFieldV("acceleration", TypeRangedF32,                      Offset(acceleration,       SplashData), &CommonValidators::PositiveFloat, "Constant acceleration value to place upon the splash effect.\n");
+   addFieldV("times", TypeRangedF32,                      Offset(times,              SplashData), &CommonValidators::NormalizedFloat, NUM_TIME_KEYS, "Times to transition through the splash effect. Up to 4 allowed. Values are 0.0 - 1.0, and corrispond to the life of the particle where 0 is first created and 1 is end of lifespace.\n" );
    addField("colors",            TypeColorF,                   Offset(colors,             SplashData), NUM_TIME_KEYS, "Color values to set the splash effect, rgba. Up to 4 allowed. Will transition through colors based on values set in the times value. Example: colors[0] = \"0.6 1.0 1.0 0.5\".\n" );
    addField("colors",            TypeColorF,                   Offset(colors,             SplashData), NUM_TIME_KEYS, "Color values to set the splash effect, rgba. Up to 4 allowed. Will transition through colors based on values set in the times value. Example: colors[0] = \"0.6 1.0 1.0 0.5\".\n" );
 
 
    INITPERSISTFIELD_IMAGEASSET_ARRAY(Texture, NUM_TEX, SplashData, "Image to use as the texture for the splash effect.\n");
    INITPERSISTFIELD_IMAGEASSET_ARRAY(Texture, NUM_TEX, SplashData, "Image to use as the texture for the splash effect.\n");
 
 
-   addField("texWrap",           TypeF32,                      Offset(texWrap,            SplashData), "Amount to wrap the texture around the splash ring, 0.0f - 1.0f.\n");
-   addField("texFactor",         TypeF32,                      Offset(texFactor,          SplashData), "Factor in which to apply the texture to the splash ring, 0.0f - 1.0f.\n");
-   addField("ejectionFreq",      TypeF32,                      Offset(ejectionFreq,       SplashData), "Frequency in which to emit splash rings.\n");
-   addField("ejectionAngle",     TypeF32,                      Offset(ejectionAngle,      SplashData), "Rotational angle to create a splash ring.\n");
-   addField("ringLifetime",      TypeF32,                      Offset(ringLifetime,       SplashData), "Lifetime, in milliseconds, for a splash ring.\n");
-   addField("startRadius",       TypeF32,                      Offset(startRadius,        SplashData), "Starting radius size of a splash ring.\n");
+   addFieldV("texWrap", TypeRangedF32,                      Offset(texWrap,            SplashData), &CommonValidators::NormalizedFloat, "Amount to wrap the texture around the splash ring, 0.0f - 1.0f.\n");
+   addFieldV("texFactor", TypeRangedF32,                      Offset(texFactor,          SplashData), &CommonValidators::NormalizedFloat, "Factor in which to apply the texture to the splash ring, 0.0f - 1.0f.\n");
+   addFieldV("ejectionFreq", TypeRangedF32,                      Offset(ejectionFreq,       SplashData), &CommonValidators::PositiveFloat, "Frequency in which to emit splash rings.\n");
+   addFieldV("ejectionAngle", TypeRangedF32,                      Offset(ejectionAngle,      SplashData), &CommonValidators::DegreeRange, "Rotational angle to create a splash ring.\n");
+   addFieldV("ringLifetime",      TypeRangedF32,                      Offset(ringLifetime,       SplashData), &CommonValidators::PositiveFloat, "Lifetime, in milliseconds, for a splash ring.\n");
+   addFieldV("startRadius", TypeRangedF32,                      Offset(startRadius,        SplashData), &CommonValidators::PositiveFloat, "Starting radius size of a splash ring.\n");
    addField("explosion",         TYPEID< ExplosionData >(),    Offset(explosion,          SplashData), "ExplosionData object to create at the creation position of this splash effect.\n");
    addField("explosion",         TYPEID< ExplosionData >(),    Offset(explosion,          SplashData), "ExplosionData object to create at the creation position of this splash effect.\n");
 
 
    Parent::initPersistFields();
    Parent::initPersistFields();

+ 1 - 1
Engine/source/T3D/gameBase/gameBase.cpp

@@ -127,7 +127,7 @@ IMPLEMENT_CALLBACK( GameBase, setControl, void, ( bool controlled ), ( controlle
 
 
 GameBaseData::GameBaseData()
 GameBaseData::GameBaseData()
 {
 {
-   mCategory = "";
+   mCategory = StringTable->EmptyString();
    mPacked = false;
    mPacked = false;
 }
 }
 GameBaseData::GameBaseData(const GameBaseData& other, bool temp_clone) : SimDataBlock(other, temp_clone)
 GameBaseData::GameBaseData(const GameBaseData& other, bool temp_clone) : SimDataBlock(other, temp_clone)

+ 4 - 4
Engine/source/T3D/groundPlane.cpp

@@ -100,15 +100,15 @@ GroundPlane::~GroundPlane()
    mConvexList->nukeList();
    mConvexList->nukeList();
    SAFE_DELETE( mConvexList );
    SAFE_DELETE( mConvexList );
 }
 }
-
+FRangeValidator squareSizeRange(sMIN_SQUARE_SIZE, FLT_MAX);
 void GroundPlane::initPersistFields()
 void GroundPlane::initPersistFields()
 {
 {
    docsURL;
    docsURL;
    addGroup( "Plane" );
    addGroup( "Plane" );
 
 
-      addField( "squareSize",    TypeF32,          Offset( mSquareSize, GroundPlane ), "Square size in meters to which %GroundPlane subdivides its geometry." );
-      addField( "scaleU",        TypeF32,          Offset( mScaleU, GroundPlane ), "Scale of texture repeat in the U direction." );
-      addField( "scaleV",        TypeF32,          Offset( mScaleV, GroundPlane ), "Scale of texture repeat in the V direction." );
+      addFieldV( "squareSize",    TypeRangedF32,          Offset( mSquareSize, GroundPlane ),&squareSizeRange, "Square size in meters to which %GroundPlane subdivides its geometry." );
+      addFieldV( "scaleU", TypeRangedF32,          Offset( mScaleU, GroundPlane ), &CommonValidators::PositiveFloat, "Scale of texture repeat in the U direction." );
+      addFieldV( "scaleV", TypeRangedF32,          Offset( mScaleV, GroundPlane ), &CommonValidators::PositiveFloat, "Scale of texture repeat in the V direction." );
 
 
       INITPERSISTFIELD_MATERIALASSET(Material, GroundPlane, "The material used to render the ground plane.");
       INITPERSISTFIELD_MATERIALASSET(Material, GroundPlane, "The material used to render the ground plane.");
 
 

+ 4 - 4
Engine/source/T3D/guiObjectView.cpp

@@ -171,13 +171,13 @@ void GuiObjectView::initPersistFields()
    
    
    addGroup( "Camera" );
    addGroup( "Camera" );
    
    
-      addField( "orbitDiststance", TypeF32, Offset( mOrbitDist, GuiObjectView ),
+      addFieldV( "orbitDiststance", TypeRangedF32, Offset( mOrbitDist, GuiObjectView ), &CommonValidators::PositiveFloat,
          "Distance from which to render the model." );
          "Distance from which to render the model." );
-      addField( "minOrbitDiststance", TypeF32, Offset( mMinOrbitDist, GuiObjectView ),
+      addFieldV( "minOrbitDiststance", TypeRangedF32, Offset( mMinOrbitDist, GuiObjectView ), &CommonValidators::PositiveFloat,
          "Maxiumum distance to which the camera can be zoomed out." );
          "Maxiumum distance to which the camera can be zoomed out." );
-      addField( "maxOrbitDiststance", TypeF32, Offset( mMaxOrbitDist, GuiObjectView ),
+      addFieldV( "maxOrbitDiststance", TypeRangedF32, Offset( mMaxOrbitDist, GuiObjectView ), &CommonValidators::PositiveFloat,
          "Minimum distance below which the camera will not zoom in further." );
          "Minimum distance below which the camera will not zoom in further." );
-      addField( "cameraSpeed", TypeF32, Offset( mCameraSpeed, GuiObjectView ),
+      addFieldV( "cameraSpeed", TypeRangedF32, Offset( mCameraSpeed, GuiObjectView ), &CommonValidators::PositiveFloat,
          "Multiplier for mouse camera operations." );
          "Multiplier for mouse camera operations." );
       addField( "cameraRotation", TypePoint3F, Offset( mCameraRotation, GuiObjectView ),
       addField( "cameraRotation", TypePoint3F, Offset( mCameraRotation, GuiObjectView ),
          "Set the camera rotation." );
          "Set the camera rotation." );

+ 17 - 14
Engine/source/T3D/item.cpp

@@ -135,20 +135,23 @@ ImplementEnumType( ItemLightType,
    { Item::PulsingLight,      "PulsingLight",   "The item has a pulsing light attached.\n" }
    { Item::PulsingLight,      "PulsingLight",   "The item has a pulsing light attached.\n" }
 EndImplementEnumType;
 EndImplementEnumType;
 
 
+FRangeValidator itemFrictionRange(0.0f, FLT_MAX, 1<<10);
+FRangeValidator itemElasticityRange(0.0f, FLT_MAX, 1<<10);
+FRangeValidator itemGravityModRange(FLT_MIN, FLT_MAX, 1<<10);
 void ItemData::initPersistFields()
 void ItemData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
    Parent::initPersistFields();
    Parent::initPersistFields();
    addGroup("Physics");
    addGroup("Physics");
-      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.");
+      addFieldV("friction",          TypeRangedF32,       Offset(friction,           ItemData), &itemFrictionRange, "A floating-point value specifying how much velocity is lost to impact and sliding friction.");
+      addFieldV("elasticity", TypeRangedF32,       Offset(elasticity,         ItemData) ,&itemElasticityRange, "A floating-point value specifying how 'bouncy' this ItemData is.");
       addField("sticky",            TypeBool,      Offset(sticky,             ItemData),
       addField("sticky",            TypeBool,      Offset(sticky,             ItemData),
          "@brief If true, ItemData will 'stick' to any surface it collides with.\n\n"
          "@brief If true, ItemData will 'stick' to any surface it collides with.\n\n"
          "When an item does stick to a surface, the Item::onStickyCollision() callback is called.  The Item has methods to retrieve "
          "When an item does stick to a surface, the Item::onStickyCollision() callback is called.  The Item has methods to retrieve "
          "the world position and normal the Item is stuck to.\n"
          "the world position and normal the Item is stuck to.\n"
          "@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("maxVelocity",       TypeF32,       Offset(maxVelocity,        ItemData), "Maximum velocity that this ItemData is able to move.");
+      addFieldV("gravityMod", TypeRangedF32,       Offset(gravityMod,         ItemData),&itemGravityModRange, "Floating point value to multiply the existing gravity with, just for this ItemData.");
+      addFieldV("maxVelocity", TypeRangedF32,       Offset(maxVelocity,        ItemData), &CommonValidators::PositiveFloat, "Maximum velocity that this ItemData is able to move.");
       addField("simpleServerCollision",   TypeBool,  Offset(simpleServerCollision,    ItemData),
       addField("simpleServerCollision",   TypeBool,  Offset(simpleServerCollision,    ItemData),
          "@brief Determines if only simple server-side collision will be used (for pick ups).\n\n"
          "@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 set to true then only simple, server-side collision detection will be used.  This is often the case "
@@ -164,10 +167,10 @@ void ItemData::initPersistFields()
       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"
          "@see lightType\n");
          "@see lightType\n");
-      addField("lightTime",         TypeS32,       Offset(lightTime,          ItemData), 
+      addFieldV("lightTime",         TypeRangedS32,       Offset(lightTime,          ItemData), &CommonValidators::NaturalNumber,
          "@brief Time value for the light of this ItemData, used to control the pulse speed of the PulsingLight LightType.\n\n"
          "@brief Time value for the light of this ItemData, used to control the pulse speed of the PulsingLight LightType.\n\n"
          "@see lightType\n");
          "@see lightType\n");
-      addField("lightRadius",       TypeF32,       Offset(lightRadius,        ItemData), 
+      addFieldV("lightRadius",       TypeRangedF32,       Offset(lightRadius,        ItemData), &CommonValidators::PositiveFloat,
          "@brief Distance from the center point of this ItemData for the light to affect\n\n"
          "@brief Distance from the center point of this ItemData for the light to affect\n\n"
          "@see lightType\n");
          "@see lightType\n");
       addField("lightOnlyStatic",   TypeBool,      Offset(lightOnlyStatic,    ItemData), 
       addField("lightOnlyStatic",   TypeBool,      Offset(lightOnlyStatic,    ItemData), 
@@ -191,10 +194,10 @@ void ItemData::packData(BitStream* stream)
    {
    {
       AssertFatal(Item::NumLightTypes < (1 << 2), "ItemData: light type needs more bits");
       AssertFatal(Item::NumLightTypes < (1 << 2), "ItemData: light type needs more bits");
       stream->writeInt(lightType, 2);
       stream->writeInt(lightType, 2);
-      stream->writeFloat(lightColor.red, 7);
-      stream->writeFloat(lightColor.green, 7);
-      stream->writeFloat(lightColor.blue, 7);
-      stream->writeFloat(lightColor.alpha, 7);
+      stream->writeFloat(lightColor.red, 8);
+      stream->writeFloat(lightColor.green, 8);
+      stream->writeFloat(lightColor.blue, 8);
+      stream->writeFloat(lightColor.alpha, 8);
       stream->write(lightTime);
       stream->write(lightTime);
       stream->write(lightRadius);
       stream->write(lightRadius);
       stream->writeFlag(lightOnlyStatic);
       stream->writeFlag(lightOnlyStatic);
@@ -222,10 +225,10 @@ void ItemData::unpackData(BitStream* stream)
    if(stream->readFlag())
    if(stream->readFlag())
    {
    {
       lightType = stream->readInt(2);
       lightType = stream->readInt(2);
-      lightColor.red = stream->readFloat(7);
-      lightColor.green = stream->readFloat(7);
-      lightColor.blue = stream->readFloat(7);
-      lightColor.alpha = stream->readFloat(7);
+      lightColor.red = stream->readFloat(8);
+      lightColor.green = stream->readFloat(8);
+      lightColor.blue = stream->readFloat(8);
+      lightColor.alpha = stream->readFloat(8);
       stream->read(&lightTime);
       stream->read(&lightTime);
       stream->read(&lightRadius);
       stream->read(&lightRadius);
       lightOnlyStatic = stream->readFlag();
       lightOnlyStatic = stream->readFlag();

+ 9 - 11
Engine/source/T3D/levelInfo.cpp

@@ -123,20 +123,18 @@ LevelInfo::~LevelInfo()
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-FRangeValidator ValiDampnessRange(0.0f, 1.0f);
-
 void LevelInfo::initPersistFields()
 void LevelInfo::initPersistFields()
 {
 {
    docsURL;
    docsURL;
    addGroup( "Visibility" );
    addGroup( "Visibility" );
 
 
-      addField( "nearClip", TypeF32, Offset( mNearClip, LevelInfo ), "Closest distance from the camera's position to render the world." );
-      addField( "visibleDistance", TypeF32, Offset( mVisibleDistance, LevelInfo ), "Furthest distance from the camera's position to render the world." );
-      addField( "visibleGhostDistance", TypeF32, Offset( mVisibleGhostDistance, LevelInfo ), "Furthest distance from the camera's position to render players. Defaults to visibleDistance." );
-      addField( "decalBias", TypeF32, Offset( mDecalBias, LevelInfo ),
+      addFieldV( "nearClip", TypeRangedF32, Offset( mNearClip, LevelInfo ), &CommonValidators::PositiveFloat, "Closest distance from the camera's position to render the world." );
+      addFieldV( "visibleDistance", TypeRangedF32, Offset( mVisibleDistance, LevelInfo ), &CommonValidators::PositiveFloat, "Furthest distance from the camera's position to render the world." );
+      addFieldV( "visibleGhostDistance", TypeRangedF32, Offset( mVisibleGhostDistance, LevelInfo ), &CommonValidators::PositiveFloat, "Furthest distance from the camera's position to render players. Defaults to visibleDistance." );
+      addFieldV( "decalBias", TypeRangedF32, Offset( mDecalBias, LevelInfo ), &CommonValidators::PositiveFloat,
          "NearPlane bias used when rendering Decal and DecalRoad. This should be tuned to the visibleDistance in your level." );
          "NearPlane bias used when rendering Decal and DecalRoad. This should be tuned to the visibleDistance in your level." );
 
 
-      addFieldV("dampness", TypeF32, Offset(mDampness, LevelInfo), &ValiDampnessRange,
+      addFieldV("dampness", TypeRangedF32, Offset(mDampness, LevelInfo), &CommonValidators::NormalizedFloat,
          "@brief dampness influence");
          "@brief dampness influence");
    endGroup( "Visibility" );
    endGroup( "Visibility" );
 
 
@@ -145,13 +143,13 @@ void LevelInfo::initPersistFields()
       addField( "fogColor", TypeColorF, Offset( mFogData.color, LevelInfo ),
       addField( "fogColor", TypeColorF, Offset( mFogData.color, LevelInfo ),
          "The default color for the scene fog." );
          "The default color for the scene fog." );
 
 
-      addField( "fogDensity", TypeF32, Offset( mFogData.density, LevelInfo ),
+      addFieldV( "fogDensity", TypeRangedF32, Offset( mFogData.density, LevelInfo ), &CommonValidators::NormalizedFloat,
          "The 0 to 1 density value for the exponential fog falloff." );
          "The 0 to 1 density value for the exponential fog falloff." );
 
 
-      addField( "fogDensityOffset", TypeF32, Offset( mFogData.densityOffset, LevelInfo ),
+      addFieldV( "fogDensityOffset", TypeRangedF32, Offset( mFogData.densityOffset, LevelInfo ), &CommonValidators::PositiveFloat,
          "An offset from the camera in meters for moving the start of the fog effect." );
          "An offset from the camera in meters for moving the start of the fog effect." );
 
 
-      addField( "fogAtmosphereHeight", TypeF32, Offset( mFogData.atmosphereHeight, LevelInfo ),
+      addFieldV( "fogAtmosphereHeight", TypeRangedF32, Offset( mFogData.atmosphereHeight, LevelInfo ), &CommonValidators::PositiveFloat,
          "A height in meters for altitude fog falloff." );
          "A height in meters for altitude fog falloff." );
 
 
    endGroup( "Fog" );
    endGroup( "Fog" );
@@ -165,7 +163,7 @@ void LevelInfo::initPersistFields()
 
 
    addGroup( "Lighting" );
    addGroup( "Lighting" );
 
 
-      addField( "ambientLightBlendPhase", TypeF32, Offset( mAmbientLightBlendPhase, LevelInfo ),
+      addFieldV( "ambientLightBlendPhase", TypeRangedF32, Offset( mAmbientLightBlendPhase, LevelInfo ), &CommonValidators::PositiveFloat,
          "Number of seconds it takes to blend from one ambient light color to a different one." );
          "Number of seconds it takes to blend from one ambient light color to a different one." );
 
 
       addField( "ambientLightBlendCurve", TypeEaseF, Offset( mAmbientLightBlendCurve, LevelInfo ),
       addField( "ambientLightBlendCurve", TypeEaseF, Offset( mAmbientLightBlendCurve, LevelInfo ),

+ 24 - 21
Engine/source/T3D/lightAnimData.cpp

@@ -65,77 +65,80 @@ void LightAnimData::initPersistFields()
    docsURL;
    docsURL;
    addGroup( "Offset",
    addGroup( "Offset",
       "The XYZ translation animation state relative to the light position." );
       "The XYZ translation animation state relative to the light position." );
-
-      addField( "offsetA", TypeF32, Offset( mOffset.value1, LightAnimData ), 3,
+      addArray("XYZ Pan", Axis);
+         addFieldV( "offsetA", TypeRangedF32, Offset( mOffset.value1, LightAnimData ), &CommonValidators::PositiveFloat, Axis,
          "The value of the A key in the keyframe sequence." );
          "The value of the A key in the keyframe sequence." );
 
 
-      addField( "offsetZ", TypeF32, Offset( mOffset.value2, LightAnimData ), 3,
+         addFieldV( "offsetZ", TypeRangedF32, Offset( mOffset.value2, LightAnimData ), &CommonValidators::PositiveFloat, Axis,
          "The value of the Z key in the keyframe sequence." );
          "The value of the Z key in the keyframe sequence." );
 
 
-      addField( "offsetPeriod", TypeF32, Offset( mOffset.period, LightAnimData ), 3,
+         addFieldV( "offsetPeriod", TypeRangedF32, Offset( mOffset.period, LightAnimData ), &CommonValidators::PositiveFloat, Axis,
          "The animation time for keyframe sequence." );
          "The animation time for keyframe sequence." );
 
 
-      addField( "offsetKeys", TypeString, Offset( mOffset.keys, LightAnimData ), 3,
+        addField( "offsetKeys", TypeString, Offset( mOffset.keys, LightAnimData ), Axis,
          "The keyframe sequence encoded into a string where characters from A to Z define "
          "The keyframe sequence encoded into a string where characters from A to Z define "
          "a position between the two animation values." );
          "a position between the two animation values." );
 
 
-      addField( "offsetSmooth", TypeBool, Offset( mOffset.smooth, LightAnimData ), 3,
+         addField( "offsetSmooth", TypeBool, Offset( mOffset.smooth, LightAnimData ), Axis,
          "If true the transition between keyframes will be smooth." );
          "If true the transition between keyframes will be smooth." );
-
+      endArray("XYZ Pan");
    endGroup( "Offset" );
    endGroup( "Offset" );
 
 
    addGroup( "Rotation",
    addGroup( "Rotation",
       "The XYZ rotation animation state relative to the light orientation." );
       "The XYZ rotation animation state relative to the light orientation." );
+      addArray("XYZ Rot", Axis);
 
 
-      addField( "rotA", TypeF32, Offset( mRot.value1, LightAnimData ), 3,
+         addFieldV( "rotA", TypeRangedF32, Offset( mRot.value1, LightAnimData ), &CommonValidators::DegreeRange, Axis,
          "The value of the A key in the keyframe sequence." );
          "The value of the A key in the keyframe sequence." );
 
 
-      addField( "rotZ", TypeF32, Offset( mRot.value2, LightAnimData ), 3,
+         addFieldV( "rotZ", TypeRangedF32, Offset( mRot.value2, LightAnimData ), &CommonValidators::DegreeRange, Axis,
          "The value of the Z key in the keyframe sequence." );
          "The value of the Z key in the keyframe sequence." );
 
 
-      addField( "rotPeriod", TypeF32, Offset( mRot.period, LightAnimData ), 3,
+         addFieldV( "rotPeriod", TypeRangedF32, Offset( mRot.period, LightAnimData ), &CommonValidators::PositiveFloat, Axis,
          "The animation time for keyframe sequence." );
          "The animation time for keyframe sequence." );
 
 
-      addField( "rotKeys", TypeString, Offset( mRot.keys, LightAnimData ), 3,
+         addField( "rotKeys", TypeString, Offset( mRot.keys, LightAnimData ), Axis,
          "The keyframe sequence encoded into a string where characters from A to Z define "
          "The keyframe sequence encoded into a string where characters from A to Z define "
          "a position between the two animation values." );
          "a position between the two animation values." );
 
 
-      addField( "rotSmooth", TypeBool, Offset( mRot.smooth, LightAnimData ), 3,
+         addField( "rotSmooth", TypeBool, Offset( mRot.smooth, LightAnimData ), Axis,
          "If true the transition between keyframes will be smooth." );
          "If true the transition between keyframes will be smooth." );
-
+      endArray("XYZ Rot");
    endGroup( "Rotation" );
    endGroup( "Rotation" );
 
 
    addGroup( "Color",
    addGroup( "Color",
       "The RGB color animation state." );
       "The RGB color animation state." );
+      addArray("RGB", Channel);
 
 
-      addField( "colorA", TypeF32, Offset( mColor.value1, LightAnimData ), 3,
+         addFieldV( "colorA", TypeRangedF32, Offset( mColor.value1, LightAnimData ), &CommonValidators::F32_8BitPercent, Channel,
          "The value of the A key in the keyframe sequence." );
          "The value of the A key in the keyframe sequence." );
 
 
-      addField( "colorZ", TypeF32, Offset( mColor.value2, LightAnimData ), 3,
+         addFieldV( "colorZ", TypeRangedF32, Offset( mColor.value2, LightAnimData ), &CommonValidators::F32_8BitPercent, Channel,
          "The value of the Z key in the keyframe sequence." );
          "The value of the Z key in the keyframe sequence." );
 
 
-      addField( "colorPeriod", TypeF32, Offset( mColor.period, LightAnimData ), 3,
+         addFieldV( "colorPeriod", TypeRangedF32, Offset( mColor.period, LightAnimData ), &CommonValidators::PositiveFloat, Channel,
          "The animation time for keyframe sequence." );
          "The animation time for keyframe sequence." );
 
 
-      addField( "colorKeys", TypeString, Offset( mColor.keys, LightAnimData ), 3,
+         addField( "colorKeys", TypeString, Offset( mColor.keys, LightAnimData ), Channel,
          "The keyframe sequence encoded into a string where characters from A to Z define "
          "The keyframe sequence encoded into a string where characters from A to Z define "
          "a position between the two animation values." );
          "a position between the two animation values." );
 
 
-      addField( "colorSmooth", TypeBool, Offset( mColor.smooth, LightAnimData ), 3,
+         addField( "colorSmooth", TypeBool, Offset( mColor.smooth, LightAnimData ), Channel,
          "If true the transition between keyframes will be smooth." );
          "If true the transition between keyframes will be smooth." );
+      endArray("RGB");
 
 
    endGroup( "Color" );
    endGroup( "Color" );
 
 
    addGroup( "Brightness",
    addGroup( "Brightness",
       "The brightness animation state." );
       "The brightness animation state." );
 
 
-      addField( "brightnessA", TypeF32, Offset( mBrightness.value1, LightAnimData ),
+      addFieldV( "brightnessA", TypeRangedF32, Offset( mBrightness.value1, LightAnimData ), &CommonValidators::PositiveFloat,
          "The value of the A key in the keyframe sequence." );
          "The value of the A key in the keyframe sequence." );
 
 
-      addField( "brightnessZ", TypeF32, Offset( mBrightness.value2, LightAnimData ),
+      addFieldV( "brightnessZ", TypeRangedF32, Offset( mBrightness.value2, LightAnimData ), &CommonValidators::PositiveFloat,
          "The value of the Z key in the keyframe sequence." );
          "The value of the Z key in the keyframe sequence." );
 
 
-      addField( "brightnessPeriod", TypeF32, Offset( mBrightness.period, LightAnimData ),
+      addFieldV( "brightnessPeriod", TypeRangedF32, Offset( mBrightness.period, LightAnimData ), &CommonValidators::PositiveFloat,
          "The animation time for keyframe sequence." );
          "The animation time for keyframe sequence." );
 
 
       addField( "brightnessKeys", TypeString, Offset( mBrightness.keys, LightAnimData ),
       addField( "brightnessKeys", TypeString, Offset( mBrightness.keys, LightAnimData ),

+ 8 - 3
Engine/source/T3D/lightAnimData.h

@@ -164,14 +164,19 @@ public:
       void read( BitStream *stream );
       void read( BitStream *stream );
    };
    };
 
 
+   enum animEnums
+   {
+      Axis = 3,
+      Channel = 3
+   };
    /// The positional animation parameters for x, y, and z.
    /// The positional animation parameters for x, y, and z.
-   AnimValue<3> mOffset;
+   AnimValue<Axis> mOffset;
 
 
    /// The rotational animation parameters for x, y, and z.
    /// The rotational animation parameters for x, y, and z.
-   AnimValue<3> mRot;
+   AnimValue<Axis> mRot;
 
 
    /// The color animation parameters for r, g, and b.
    /// The color animation parameters for r, g, and b.
-   AnimValue<3> mColor;
+   AnimValue<Channel> mColor;
 
 
    /// The brightness animation parameter.
    /// The brightness animation parameter.
    AnimValue<1> mBrightness;
    AnimValue<1> mBrightness;

+ 5 - 5
Engine/source/T3D/lightBase.cpp

@@ -97,11 +97,11 @@ void LightBase::initPersistFields()
       
       
       addField( "isEnabled", TypeBool, Offset( mIsEnabled, LightBase ), "Enables/Disables the object rendering and functionality in the scene." );
       addField( "isEnabled", TypeBool, Offset( mIsEnabled, LightBase ), "Enables/Disables the object rendering and functionality in the scene." );
       addField( "color", TypeColorF, Offset( mColor, LightBase ), "Changes the base color hue of the light." );
       addField( "color", TypeColorF, Offset( mColor, LightBase ), "Changes the base color hue of the light." );
-      addField( "brightness", TypeF32, Offset( mBrightness, LightBase ), "Adjusts the lights power, 0 being off completely." );      
+      addFieldV( "brightness", TypeRangedF32, Offset( mBrightness, LightBase ), &CommonValidators::PositiveFloat, "Adjusts the lights power, 0 being off completely." );
       addField( "castShadows", TypeBool, Offset( mCastShadows, LightBase ), "Enables/disabled shadow casts by this light." );
       addField( "castShadows", TypeBool, Offset( mCastShadows, LightBase ), "Enables/disabled shadow casts by this light." );
       //addField( "staticRefreshFreq", TypeS32, Offset( mStaticRefreshFreq, LightBase ), "static shadow refresh rate (milliseconds)" );
       //addField( "staticRefreshFreq", TypeS32, Offset( mStaticRefreshFreq, LightBase ), "static shadow refresh rate (milliseconds)" );
       //addField( "dynamicRefreshFreq", TypeS32, Offset( mDynamicRefreshFreq, LightBase ), "dynamic shadow refresh rate (milliseconds)");
       //addField( "dynamicRefreshFreq", TypeS32, Offset( mDynamicRefreshFreq, LightBase ), "dynamic shadow refresh rate (milliseconds)");
-      addField( "priority", TypeF32, Offset( mPriority, LightBase ), "Used for sorting of lights by the light manager. "
+      addFieldV( "priority", TypeRangedF32, Offset( mPriority, LightBase ), &CommonValidators::PositiveFloat, "Used for sorting of lights by the light manager. "
 		  "Priority determines if a light has a stronger effect than, those with a lower value" );
 		  "Priority determines if a light has a stronger effect than, those with a lower value" );
 
 
    endGroup( "Light" );
    endGroup( "Light" );
@@ -110,15 +110,15 @@ void LightBase::initPersistFields()
 
 
       addField( "animate", TypeBool, Offset( mAnimState.active, LightBase ), "Toggles animation for the light on and off" );
       addField( "animate", TypeBool, Offset( mAnimState.active, LightBase ), "Toggles animation for the light on and off" );
       addField( "animationType", TYPEID< LightAnimData >(), Offset( mAnimationData, LightBase ), "Datablock containing light animation information (LightAnimData)" );
       addField( "animationType", TYPEID< LightAnimData >(), Offset( mAnimationData, LightBase ), "Datablock containing light animation information (LightAnimData)" );
-      addFieldV( "animationPeriod", TypeF32, Offset( mAnimState.animationPeriod, LightBase ), &CommonValidators::PositiveNonZeroFloat, "The length of time in seconds for a single playback of the light animation (must be > 0)" );
-      addField( "animationPhase", TypeF32, Offset( mAnimState.animationPhase, LightBase ), "The phase used to offset the animation start time to vary the animation of nearby lights." );      
+      addFieldV( "animationPeriod", TypeRangedF32, Offset( mAnimState.animationPeriod, LightBase ), &CommonValidators::PositiveNonZeroFloat, "The length of time in seconds for a single playback of the light animation (must be > 0)" );
+      addFieldV( "animationPhase", TypeRangedF32, Offset( mAnimState.animationPhase, LightBase ), &CommonValidators::PositiveFloat, "The phase used to offset the animation start time to vary the animation of nearby lights." );
 
 
    endGroup( "Light Animation" );
    endGroup( "Light Animation" );
 
 
    addGroup( "Misc" );
    addGroup( "Misc" );
 
 
       addField( "flareType", TYPEID< LightFlareData >(), Offset( mFlareData, LightBase ), "Datablock containing light flare information (LightFlareData)" );
       addField( "flareType", TYPEID< LightFlareData >(), Offset( mFlareData, LightBase ), "Datablock containing light flare information (LightFlareData)" );
-      addField( "flareScale", TypeF32, Offset( mFlareScale, LightBase ), "Globally scales all features of the light flare" );
+      addFieldV( "flareScale", TypeRangedF32, Offset( mFlareScale, LightBase ), &CommonValidators::PositiveFloat, "Globally scales all features of the light flare" );
 
 
    endGroup( "Misc" );
    endGroup( "Misc" );
 
 

+ 8 - 6
Engine/source/T3D/lightDescription.cpp

@@ -29,6 +29,7 @@
 #include "core/stream/bitStream.h"
 #include "core/stream/bitStream.h"
 #include "lighting/lightInfo.h"
 #include "lighting/lightInfo.h"
 #include "console/engineAPI.h"
 #include "console/engineAPI.h"
+#include "console/typeValidators.h"
 
 
 
 
 LightDescription::LightDescription()
 LightDescription::LightDescription()
@@ -94,26 +95,27 @@ void LightDescription::initPersistFields()
    addGroup( "Light" );
    addGroup( "Light" );
 
 
       addField( "color", TypeColorF, Offset( color, LightDescription ), "Changes the base color hue of the light." );
       addField( "color", TypeColorF, Offset( color, LightDescription ), "Changes the base color hue of the light." );
-      addField( "brightness", TypeF32, Offset( brightness, LightDescription ), "Adjusts the lights power, 0 being off completely." );      
-      addField( "range", TypeF32, Offset( range, LightDescription ), "Controls the size (radius) of the light" );
+      addFieldV( "brightness", TypeRangedF32, Offset( brightness, LightDescription ), &CommonValidators::PositiveFloat, "Adjusts the lights power, 0 being off completely." );
+      addFieldV( "range", TypeRangedF32, Offset( range, LightDescription ), &CommonValidators::PositiveFloat, "Controls the size (radius) of the light" );
       addField( "castShadows", TypeBool, Offset( castShadows, LightDescription ), "Enables/disabled shadow casts by this light." );
       addField( "castShadows", TypeBool, Offset( castShadows, LightDescription ), "Enables/disabled shadow casts by this light." );
+      /*
       addField( "staticRefreshFreq", TypeS32, Offset( mStaticRefreshFreq, LightDescription ), "static shadow refresh rate (milliseconds)" );
       addField( "staticRefreshFreq", TypeS32, Offset( mStaticRefreshFreq, LightDescription ), "static shadow refresh rate (milliseconds)" );
       addField( "dynamicRefreshFreq", TypeS32, Offset( mDynamicRefreshFreq, LightDescription ), "dynamic shadow refresh rate (milliseconds)");
       addField( "dynamicRefreshFreq", TypeS32, Offset( mDynamicRefreshFreq, LightDescription ), "dynamic shadow refresh rate (milliseconds)");
-
+      */
    endGroup( "Light" );
    endGroup( "Light" );
 
 
    addGroup( "Light Animation" );
    addGroup( "Light Animation" );
 
 
       addField( "animationType", TYPEID< LightAnimData >(), Offset( animationData, LightDescription ), "Datablock containing light animation information (LightAnimData)" );
       addField( "animationType", TYPEID< LightAnimData >(), Offset( animationData, LightDescription ), "Datablock containing light animation information (LightAnimData)" );
-      addField( "animationPeriod", TypeF32, Offset( animationPeriod, LightDescription ), "The length of time in seconds for a single playback of the light animation" );
-      addField( "animationPhase", TypeF32, Offset( animationPhase, LightDescription ), "The phase used to offset the animation start time to vary the animation of nearby lights." );
+      addFieldV( "animationPeriod", TypeRangedF32, Offset( animationPeriod, LightDescription ), &CommonValidators::PositiveFloat, "The length of time in seconds for a single playback of the light animation" );
+      addFieldV( "animationPhase", TypeRangedF32, Offset( animationPhase, LightDescription ), &CommonValidators::PositiveFloat, "The phase used to offset the animation start time to vary the animation of nearby lights." );
 
 
    endGroup( "Light Animation" );
    endGroup( "Light Animation" );
 
 
    addGroup( "Misc" );
    addGroup( "Misc" );
 
 
       addField( "flareType", TYPEID< LightFlareData >(), Offset( flareData, LightDescription ), "Datablock containing light flare information (LightFlareData)" );
       addField( "flareType", TYPEID< LightFlareData >(), Offset( flareData, LightDescription ), "Datablock containing light flare information (LightFlareData)" );
-      addField( "flareScale", TypeF32, Offset( flareScale, LightDescription ), "Globally scales all features of the light flare" );
+      addFieldV( "flareScale", TypeRangedF32, Offset( flareScale, LightDescription ), &CommonValidators::PositiveFloat, "Globally scales all features of the light flare" );
 
 
    endGroup( "Misc" );
    endGroup( "Misc" );
 
 

+ 4 - 4
Engine/source/T3D/lightFlareData.cpp

@@ -145,10 +145,10 @@ void LightFlareData::initPersistFields()
    docsURL;
    docsURL;
    addGroup( "LightFlareData" );
    addGroup( "LightFlareData" );
 
 
-      addField( "overallScale", TypeF32, Offset( mScale, LightFlareData ),
+      addFieldV( "overallScale", TypeRangedF32, Offset( mScale, LightFlareData ), &CommonValidators::PositiveFloat,
          "Size scale applied to all elements of the flare." );
          "Size scale applied to all elements of the flare." );
 
 
-      addField( "occlusionRadius", TypeF32, Offset( mOcclusionRadius, LightFlareData ), 
+      addFieldV( "occlusionRadius", TypeRangedF32, Offset( mOcclusionRadius, LightFlareData ), &CommonValidators::PositiveFloat,
          "If positive an occlusion query is used to test flare visibility, else it uses simple raycasts." );
          "If positive an occlusion query is used to test flare visibility, else it uses simple raycasts." );
 
 
       addField( "renderReflectPass", TypeBool, Offset( mRenderReflectPass, LightFlareData ), 
       addField( "renderReflectPass", TypeBool, Offset( mRenderReflectPass, LightFlareData ), 
@@ -168,10 +168,10 @@ void LightFlareData::initPersistFields()
          addField( "elementRect", TypeRectF, Offset( mElementRect, LightFlareData ), MAX_ELEMENTS,
          addField( "elementRect", TypeRectF, Offset( mElementRect, LightFlareData ), MAX_ELEMENTS,
             "A rectangle specified in pixels of the flareTexture image." );
             "A rectangle specified in pixels of the flareTexture image." );
 
 
-         addField( "elementDist", TypeF32, Offset( mElementDist, LightFlareData ), MAX_ELEMENTS,
+         addFieldV( "elementDist", TypeRangedF32, Offset( mElementDist, LightFlareData ), &CommonValidators::PositiveFloat, MAX_ELEMENTS,
             "Where this element appears along the flare beam." );
             "Where this element appears along the flare beam." );
 
 
-         addField( "elementScale", TypeF32, Offset( mElementScale, LightFlareData ), MAX_ELEMENTS,
+         addFieldV( "elementScale", TypeRangedF32, Offset( mElementScale, LightFlareData ), &CommonValidators::PositiveFloat, MAX_ELEMENTS,
             "Size scale applied to this element." );
             "Size scale applied to this element." );
 
 
          addField( "elementTint", TypeColorF, Offset( mElementTint, LightFlareData ), MAX_ELEMENTS,
          addField( "elementTint", TypeColorF, Offset( mElementTint, LightFlareData ), MAX_ELEMENTS,

+ 0 - 1
Engine/source/T3D/lighting/boxEnvironmentProbe.cpp

@@ -92,7 +92,6 @@ void BoxEnvironmentProbe::initPersistFields()
    docsURL;
    docsURL;
    // SceneObject already handles exposing the transform
    // SceneObject already handles exposing the transform
    Parent::initPersistFields();
    Parent::initPersistFields();
-
    removeField("radius");
    removeField("radius");
 }
 }
 
 

+ 2 - 2
Engine/source/T3D/lighting/reflectionProbe.cpp

@@ -157,11 +157,11 @@ void ReflectionProbe::initPersistFields()
       addProtectedField("enabled", TypeBool, Offset(mEnabled, ReflectionProbe),
       addProtectedField("enabled", TypeBool, Offset(mEnabled, ReflectionProbe),
          &_setEnabled, &defaultProtectedGetFn, "Is the probe enabled or not");
          &_setEnabled, &defaultProtectedGetFn, "Is the probe enabled or not");
       addField("canDamp", TypeBool, Offset(mCanDamp, ReflectionProbe),"wetness allowed");
       addField("canDamp", TypeBool, Offset(mCanDamp, ReflectionProbe),"wetness allowed");
-      addField("attenuation", TypeF32, Offset(mAtten, ReflectionProbe), "falloff percent");
+      addFieldV("attenuation", TypeRangedF32, Offset(mAtten, ReflectionProbe), &CommonValidators::NormalizedFloat, "falloff percent");
    endGroup("Rendering");
    endGroup("Rendering");
 
 
    addGroup("Reflection");
    addGroup("Reflection");
-      addProtectedField("radius", TypeF32, Offset(mRadius, ReflectionProbe), &_setRadius, &defaultProtectedGetFn, 
+      addProtectedFieldV("radius", TypeRangedF32, Offset(mRadius, ReflectionProbe), &_setRadius, &defaultProtectedGetFn, &CommonValidators::PositiveFloat,
          "The name of the material used to render the mesh.");
          "The name of the material used to render the mesh.");
 
 
       addProtectedField("EditPosOffset", TypeBool, Offset(mEditPosOffset, ReflectionProbe),
       addProtectedField("EditPosOffset", TypeBool, Offset(mEditPosOffset, ReflectionProbe),

+ 3 - 2
Engine/source/T3D/missionArea.cpp

@@ -22,6 +22,7 @@
 
 
 #include "T3D/missionArea.h"
 #include "T3D/missionArea.h"
 #include "console/consoleTypes.h"
 #include "console/consoleTypes.h"
+#include "console/typeValidators.h"
 #include "core/stream/bitStream.h"
 #include "core/stream/bitStream.h"
 #include "math/mathIO.h"
 #include "math/mathIO.h"
 #include "console/engineAPI.h"
 #include "console/engineAPI.h"
@@ -133,8 +134,8 @@ void MissionArea::initPersistFields()
    docsURL;
    docsURL;
    addGroup("Dimensions");	
    addGroup("Dimensions");	
    addField("area", TypeRectI, Offset(mArea, MissionArea), "Four corners (X1, X2, Y1, Y2) that makes up the level's boundaries");
    addField("area", TypeRectI, Offset(mArea, MissionArea), "Four corners (X1, X2, Y1, Y2) that makes up the level's boundaries");
-   addField("flightCeiling", TypeF32, Offset(mFlightCeiling, MissionArea), "Represents the top of the mission area, used by FlyingVehicle. ");
-   addField("flightCeilingRange", TypeF32, Offset(mFlightCeilingRange, MissionArea), "Distance from ceiling before FlyingVehicle thrust is cut off. ");
+   addFieldV("flightCeiling", TypeRangedF32, Offset(mFlightCeiling, MissionArea),&CommonValidators::F32Range, "Represents the top of the mission area, used by FlyingVehicle. ");
+   addFieldV("flightCeilingRange", TypeRangedF32, Offset(mFlightCeilingRange, MissionArea), &CommonValidators::F32Range, "Distance from ceiling before FlyingVehicle thrust is cut off. ");
    endGroup("Dimensions");
    endGroup("Dimensions");
 
 
    Parent::initPersistFields();
    Parent::initPersistFields();

+ 1 - 1
Engine/source/T3D/missionMarker.cpp

@@ -489,7 +489,7 @@ void SpawnSphere::initPersistFields()
    endGroup( "Spawn" );
    endGroup( "Spawn" );
 
 
    addGroup( "Dimensions" );
    addGroup( "Dimensions" );
-   addField( "radius", TypeF32, Offset(mRadius, SpawnSphere), "Deprecated" );
+   addFieldV( "radius", TypeRangedF32, Offset(mRadius, SpawnSphere), &CommonValidators::PositiveFloat, "Deprecated" );
    endGroup( "Dimensions" );
    endGroup( "Dimensions" );
 
 
    addGroup( "Weight" );
    addGroup( "Weight" );

+ 4 - 2
Engine/source/T3D/physicalZone.cpp

@@ -146,12 +146,14 @@ void PhysicalZone::consoleInit()
 	   "@ingroup EnviroMisc\n");
 	   "@ingroup EnviroMisc\n");
 }
 }
 
 
+FRangeValidator velocityModRange(-40.0f, 40.0f);
+FRangeValidator gravityModRange(-40.0f, 40.0f);
 void PhysicalZone::initPersistFields()
 void PhysicalZone::initPersistFields()
 {
 {
    docsURL;
    docsURL;
    addGroup("Misc");
    addGroup("Misc");
-   addField("velocityMod",  TypeF32,               Offset(mVelocityMod,  PhysicalZone), "Multiply velocity of objects entering zone by this value every tick.");
-   addField("gravityMod",   TypeF32,               Offset(mGravityMod,   PhysicalZone), "Gravity in PhysicalZone. Multiplies against standard gravity.");
+   addFieldV("velocityMod",  TypeRangedF32,               Offset(mVelocityMod,  PhysicalZone), &velocityModRange, "Multiply velocity of objects entering zone by this value every tick.");
+   addFieldV("gravityMod", TypeRangedF32,               Offset(mGravityMod,   PhysicalZone), &gravityModRange, "Gravity in PhysicalZone. Multiplies against standard gravity.");
    addField("appliedForce", TypePoint3F,           Offset(mAppliedForce, PhysicalZone), "Three-element floating point value representing forces in three axes to apply to objects entering PhysicalZone.");
    addField("appliedForce", TypePoint3F,           Offset(mAppliedForce, PhysicalZone), "Three-element floating point value representing forces in three axes to apply to objects entering PhysicalZone.");
    addField("polyhedron",   TypeTriggerPolyhedron, Offset(mPolyhedron,   PhysicalZone),
    addField("polyhedron",   TypeTriggerPolyhedron, Offset(mPolyhedron,   PhysicalZone),
       "The polyhedron type is really a quadrilateral and consists of a corner"
       "The polyhedron type is really a quadrilateral and consists of a corner"

+ 12 - 12
Engine/source/T3D/physics/physicsDebris.cpp

@@ -128,29 +128,29 @@ void PhysicsDebrisData::initPersistFields()
 
 
    addGroup( "Physics" );
    addGroup( "Physics" );
 
 
-      addField("lifetime", TypeF32, Offset( lifetime, PhysicsDebrisData ),
+      addFieldV("lifetime", TypeRangedF32, Offset( lifetime, PhysicsDebrisData ), &CommonValidators::PositiveFloat,
          "@brief Base time, in seconds, that debris persists after time of creation.\n\n"
          "@brief Base time, in seconds, that debris persists after time of creation.\n\n"
          "@note A %PhysicsDebris' lifetime multiplied by it's $pref::PhysicsDebris::lifetimeScale "
          "@note A %PhysicsDebris' lifetime multiplied by it's $pref::PhysicsDebris::lifetimeScale "
          "must be equal to or greater than 1.0.\n\n");
          "must be equal to or greater than 1.0.\n\n");
 
 
-      addField("lifetimeVariance", TypeF32, Offset( lifetimeVariance, PhysicsDebrisData ),
+      addFieldV("lifetimeVariance", TypeRangedF32, Offset( lifetimeVariance, PhysicsDebrisData ), &CommonValidators::PositiveFloat,
          "@brief Range of variation randomly applied to lifetime when debris is created.\n\n"
          "@brief Range of variation randomly applied to lifetime when debris is created.\n\n"
          "Represents the maximum amount of seconds that will be added or subtracted to a shape's base lifetime. "
          "Represents the maximum amount of seconds that will be added or subtracted to a shape's base lifetime. "
          "A value of 0 will apply the same lifetime to each shape created.\n\n");
          "A value of 0 will apply the same lifetime to each shape created.\n\n");
 
 
-      addField( "mass", TypeF32, Offset( mass, PhysicsDebrisData ),
+      addFieldV( "mass", TypeRangedF32, Offset( mass, PhysicsDebrisData ), &CommonValidators::PositiveFloat,
          "@brief Value representing the mass of the shape.\n\n"
          "@brief Value representing the mass of the shape.\n\n"
          "A shape's mass influences the magnitude of any force applied to it. "
          "A shape's mass influences the magnitude of any force applied to it. "
          "@note All PhysicsDebris objects are dynamic.");
          "@note All PhysicsDebris objects are dynamic.");
 
 
-      addField( "friction", TypeF32, Offset( dynamicFriction, PhysicsDebrisData ),
+      addFieldV( "friction", TypeRangedF32, Offset( dynamicFriction, PhysicsDebrisData ), &CommonValidators::PositiveFloat,
          "@brief Coefficient of kinetic %friction to be applied to the shape.\n\n" 
          "@brief Coefficient of kinetic %friction to be applied to the shape.\n\n" 
          "Kinetic %friction reduces the velocity of a moving object while it is in contact with a surface. "
          "Kinetic %friction reduces the velocity of a moving object while it is in contact with a surface. "
          "A larger coefficient will result in a larger reduction in velocity. "
          "A larger coefficient will result in a larger reduction in velocity. "
          "A shape's friction should be smaller than it's staticFriction, but greater than 0.\n\n"
          "A shape's friction should be smaller than it's staticFriction, but greater than 0.\n\n"
          "@note This value is only applied while an object is in motion. For an object starting at rest, see PhysicsDebrisData::staticFriction");
          "@note This value is only applied while an object is in motion. For an object starting at rest, see PhysicsDebrisData::staticFriction");
 
 
-      addField( "staticFriction", TypeF32, Offset( staticFriction, PhysicsDebrisData ),
+      addFieldV( "staticFriction", TypeRangedF32, Offset( staticFriction, PhysicsDebrisData ), &CommonValidators::PositiveFloat,
          "@brief Coefficient of static %friction to be applied to the shape.\n\n" 
          "@brief Coefficient of static %friction to be applied to the shape.\n\n" 
          "Static %friction determines the force needed to start moving an at-rest object in contact with a surface. "
          "Static %friction determines the force needed to start moving an at-rest object in contact with a surface. "
          "If the force applied onto shape cannot overcome the force of static %friction, the shape will remain at rest. "
          "If the force applied onto shape cannot overcome the force of static %friction, the shape will remain at rest. "
@@ -158,7 +158,7 @@ void PhysicsDebrisData::initPersistFields()
          "This value should be both greater than 0 and the PhysicsDebrisData::friction.\n\n"
          "This value should be both greater than 0 and the PhysicsDebrisData::friction.\n\n"
          "@note This value is only applied while an object is at rest. For an object in motion, see PhysicsDebrisData::friction");
          "@note This value is only applied while an object is at rest. For an object in motion, see PhysicsDebrisData::friction");
 
 
-      addField( "restitution", TypeF32, Offset( restitution, PhysicsDebrisData ),
+      addFieldV( "restitution", TypeRangedF32, Offset( restitution, PhysicsDebrisData ), &CommonValidators::PositiveFloat,
          "@brief Bounce coeffecient applied to the shape in response to a collision.\n\n"
          "@brief Bounce coeffecient applied to the shape in response to a collision.\n\n"
          "Restitution is a ratio of a shape's velocity before and after a collision. "
          "Restitution is a ratio of a shape's velocity before and after a collision. "
          "A value of 0 will zero out a shape's post-collision velocity, making it stop on contact. "
          "A value of 0 will zero out a shape's post-collision velocity, making it stop on contact. "
@@ -167,29 +167,29 @@ void PhysicsDebrisData::initPersistFields()
          "@note Values near or equaling 1.0 are likely to cause undesirable results in the physics simulation."
          "@note Values near or equaling 1.0 are likely to cause undesirable results in the physics simulation."
          " Because of this, it is reccomended to avoid values close to 1.0");
          " Because of this, it is reccomended to avoid values close to 1.0");
 
 
-      addField( "linearDamping", TypeF32, Offset( linearDamping, PhysicsDebrisData ),
+      addFieldV( "linearDamping", TypeRangedF32, Offset( linearDamping, PhysicsDebrisData ), &CommonValidators::PositiveFloat,
          "@brief Value that reduces an object's linear velocity over time.\n\n"
          "@brief Value that reduces an object's linear velocity over time.\n\n"
          "Larger values will cause velocity to decay quicker.\n\n" );
          "Larger values will cause velocity to decay quicker.\n\n" );
 
 
-      addField( "angularDamping", TypeF32, Offset( angularDamping, PhysicsDebrisData ),
+      addFieldV( "angularDamping", TypeRangedF32, Offset( angularDamping, PhysicsDebrisData ), &CommonValidators::PositiveFloat,
          "@brief Value that reduces an object's rotational velocity over time.\n\n"
          "@brief Value that reduces an object's rotational velocity over time.\n\n"
          "Larger values will cause velocity to decay quicker.\n\n" );
          "Larger values will cause velocity to decay quicker.\n\n" );
 
 
-      addField( "linearSleepThreshold", TypeF32, Offset( linearSleepThreshold, PhysicsDebrisData ),
+      addFieldV( "linearSleepThreshold", TypeRangedF32, Offset( linearSleepThreshold, PhysicsDebrisData ), &CommonValidators::PositiveFloat,
          "@brief Minimum linear velocity before the shape can be put to sleep.\n\n"
          "@brief Minimum linear velocity before the shape can be put to sleep.\n\n"
          "This should be a positive value. Shapes put to sleep will not be simulated in order to save system resources.\n\n"
          "This should be a positive value. Shapes put to sleep will not be simulated in order to save system resources.\n\n"
          "@note The shape must be dynamic.");
          "@note The shape must be dynamic.");
 
 
-      addField( "angularSleepThreshold", TypeF32, Offset( angularSleepThreshold, PhysicsDebrisData ),
+      addFieldV( "angularSleepThreshold", TypeRangedF32, Offset( angularSleepThreshold, PhysicsDebrisData ), &CommonValidators::PositiveFloat,
          "@brief Minimum rotational velocity before the shape can be put to sleep.\n\n"
          "@brief Minimum rotational velocity before the shape can be put to sleep.\n\n"
          "This should be a positive value. Shapes put to sleep will not be simulated in order to save system resources.\n\n"
          "This should be a positive value. Shapes put to sleep will not be simulated in order to save system resources.\n\n"
          "@note The shape must be dynamic.");
          "@note The shape must be dynamic.");
 
 
-      addField( "waterDampingScale", TypeF32, Offset( waterDampingScale, PhysicsDebrisData ),
+      addFieldV( "waterDampingScale", TypeRangedF32, Offset( waterDampingScale, PhysicsDebrisData ), &CommonValidators::PositiveFloat,
          "@brief Scale to apply to linear and angular dampening while underwater.\n\n "
          "@brief Scale to apply to linear and angular dampening while underwater.\n\n "
          "@see angularDamping linearDamping" );
          "@see angularDamping linearDamping" );
 
 
-      addField( "buoyancyDensity", TypeF32, Offset( buoyancyDensity, PhysicsDebrisData ),
+      addFieldV( "buoyancyDensity", TypeRangedF32, Offset( buoyancyDensity, PhysicsDebrisData ), &CommonValidators::PositiveFloat,
          "@brief The density of this shape for purposes of calculating buoyant forces.\n\n"
          "@brief The density of this shape for purposes of calculating buoyant forces.\n\n"
          "The result of the calculated buoyancy is relative to the density of the WaterObject the PhysicsDebris is within."
          "The result of the calculated buoyancy is relative to the density of the WaterObject the PhysicsDebris is within."
          "@see WaterObject::density");
          "@see WaterObject::density");

+ 10 - 10
Engine/source/T3D/physics/physicsShape.cpp

@@ -106,21 +106,21 @@ void PhysicsShapeData::initPersistFields()
 
 
    addGroup( "Physics" );
    addGroup( "Physics" );
       
       
-      addField( "mass", TypeF32, Offset( mass, PhysicsShapeData ),
+      addFieldV( "mass", TypeRangedF32, Offset( mass, PhysicsShapeData ), &CommonValidators::PositiveFloat,
          "@brief Value representing the mass of the shape.\n\n"
          "@brief Value representing the mass of the shape.\n\n"
          "A shape's mass influences the magnitude of any force exerted on it. "
          "A shape's mass influences the magnitude of any force exerted on it. "
          "For example, a PhysicsShape with a large mass requires a much larger force to move than "
          "For example, a PhysicsShape with a large mass requires a much larger force to move than "
          "the same shape with a smaller mass.\n"
          "the same shape with a smaller mass.\n"
          "@note A mass of zero will create a kinematic shape while anything greater will create a dynamic shape.");
          "@note A mass of zero will create a kinematic shape while anything greater will create a dynamic shape.");
 
 
-      addField( "friction", TypeF32, Offset( dynamicFriction, PhysicsShapeData ),
+      addFieldV( "friction", TypeRangedF32, Offset( dynamicFriction, PhysicsShapeData ), &CommonValidators::PositiveFloat,
          "@brief Coefficient of kinetic %friction to be applied to the shape.\n\n" 
          "@brief Coefficient of kinetic %friction to be applied to the shape.\n\n" 
          "Kinetic %friction reduces the velocity of a moving object while it is in contact with a surface. "
          "Kinetic %friction reduces the velocity of a moving object while it is in contact with a surface. "
          "A higher coefficient will result in a larger velocity reduction. "
          "A higher coefficient will result in a larger velocity reduction. "
          "A shape's friction should be lower than it's staticFriction, but larger than 0.\n\n"
          "A shape's friction should be lower than it's staticFriction, but larger than 0.\n\n"
          "@note This value is only applied while an object is in motion. For an object starting at rest, see PhysicsShape::staticFriction");
          "@note This value is only applied while an object is in motion. For an object starting at rest, see PhysicsShape::staticFriction");
 
 
-      addField( "staticFriction", TypeF32, Offset( staticFriction, PhysicsShapeData ),
+      addFieldV( "staticFriction", TypeRangedF32, Offset( staticFriction, PhysicsShapeData ), &CommonValidators::PositiveFloat,
          "@brief Coefficient of static %friction to be applied to the shape.\n\n" 
          "@brief Coefficient of static %friction to be applied to the shape.\n\n" 
          "Static %friction determines the force needed to start moving an at-rest object in contact with a surface. "
          "Static %friction determines the force needed to start moving an at-rest object in contact with a surface. "
          "If the force applied onto shape cannot overcome the force of static %friction, the shape will remain at rest. "
          "If the force applied onto shape cannot overcome the force of static %friction, the shape will remain at rest. "
@@ -128,7 +128,7 @@ void PhysicsShapeData::initPersistFields()
          "This value should be larger than zero and the physicsShape's friction.\n\n"
          "This value should be larger than zero and the physicsShape's friction.\n\n"
          "@note This value is only applied while an object is at rest. For an object in motion, see PhysicsShape::friction");
          "@note This value is only applied while an object is at rest. For an object in motion, see PhysicsShape::friction");
 
 
-      addField( "restitution", TypeF32, Offset( restitution, PhysicsShapeData ),
+      addFieldV( "restitution", TypeRangedF32, Offset( restitution, PhysicsShapeData ), &CommonValidators::PositiveFloat,
          "@brief Coeffecient of a bounce applied to the shape in response to a collision.\n\n"
          "@brief Coeffecient of a bounce applied to the shape in response to a collision.\n\n"
          "Restitution is a ratio of a shape's velocity before and after a collision. "
          "Restitution is a ratio of a shape's velocity before and after a collision. "
          "A value of 0 will zero out a shape's post-collision velocity, making it stop on contact. "
          "A value of 0 will zero out a shape's post-collision velocity, making it stop on contact. "
@@ -137,30 +137,30 @@ void PhysicsShapeData::initPersistFields()
          "@note Values near or equaling 1.0 are likely to cause undesirable results in the physics simulation."
          "@note Values near or equaling 1.0 are likely to cause undesirable results in the physics simulation."
          " Because of this it is reccomended to avoid values close to 1.0");
          " Because of this it is reccomended to avoid values close to 1.0");
 
 
-      addField( "linearDamping", TypeF32, Offset( linearDamping, PhysicsShapeData ),
+      addFieldV( "linearDamping", TypeRangedF32, Offset( linearDamping, PhysicsShapeData ), &CommonValidators::PositiveFloat,
          "@brief Value that reduces an object's linear velocity over time.\n\n"
          "@brief Value that reduces an object's linear velocity over time.\n\n"
          "Larger values will cause velocity to decay quicker.\n\n" );
          "Larger values will cause velocity to decay quicker.\n\n" );
 
 
-      addField( "angularDamping", TypeF32, Offset( angularDamping, PhysicsShapeData ),
+      addFieldV( "angularDamping", TypeRangedF32, Offset( angularDamping, PhysicsShapeData ), &CommonValidators::PositiveFloat,
          "@brief Value that reduces an object's rotational velocity over time.\n\n"
          "@brief Value that reduces an object's rotational velocity over time.\n\n"
          "Larger values will cause velocity to decay quicker.\n\n" );
          "Larger values will cause velocity to decay quicker.\n\n" );
 
 
-      addField( "linearSleepThreshold", TypeF32, Offset( linearSleepThreshold, PhysicsShapeData ),
+      addFieldV( "linearSleepThreshold", TypeRangedF32, Offset( linearSleepThreshold, PhysicsShapeData ), &CommonValidators::PositiveFloat,
          "@brief Minimum linear velocity before the shape can be put to sleep.\n\n"
          "@brief Minimum linear velocity before the shape can be put to sleep.\n\n"
          "This should be a positive value. Shapes put to sleep will not be simulated in order to save system resources.\n\n"
          "This should be a positive value. Shapes put to sleep will not be simulated in order to save system resources.\n\n"
          "@note The shape must be dynamic.");
          "@note The shape must be dynamic.");
 
 
-      addField( "angularSleepThreshold", TypeF32, Offset( angularSleepThreshold, PhysicsShapeData ),
+      addFieldV( "angularSleepThreshold", TypeRangedF32, Offset( angularSleepThreshold, PhysicsShapeData ), &CommonValidators::PositiveFloat,
          "@brief Minimum rotational velocity before the shape can be put to sleep.\n\n"
          "@brief Minimum rotational velocity before the shape can be put to sleep.\n\n"
          "This should be a positive value. Shapes put to sleep will not be simulated in order to save system resources.\n\n"
          "This should be a positive value. Shapes put to sleep will not be simulated in order to save system resources.\n\n"
          "@note The shape must be dynamic.");
          "@note The shape must be dynamic.");
 
 
-      addField( "waterDampingScale", TypeF32, Offset( waterDampingScale, PhysicsShapeData ),
+      addFieldV( "waterDampingScale", TypeRangedF32, Offset( waterDampingScale, PhysicsShapeData ), &CommonValidators::PositiveFloat,
          "@brief Scale to apply to linear and angular dampening while underwater.\n\n "
          "@brief Scale to apply to linear and angular dampening while underwater.\n\n "
          "Used with the waterViscosity of the  "
          "Used with the waterViscosity of the  "
          "@see angularDamping linearDamping" );
          "@see angularDamping linearDamping" );
 
 
-      addField( "buoyancyDensity", TypeF32, Offset( buoyancyDensity, PhysicsShapeData ),
+      addFieldV( "buoyancyDensity", TypeRangedF32, Offset( buoyancyDensity, PhysicsShapeData ), &CommonValidators::PositiveFloat,
          "@brief The density of the shape for calculating buoyant forces.\n\n"
          "@brief The density of the shape for calculating buoyant forces.\n\n"
          "The result of the calculated buoyancy is relative to the density of the WaterObject the PhysicsShape is within.\n\n"
          "The result of the calculated buoyancy is relative to the density of the WaterObject the PhysicsShape is within.\n\n"
          "@see WaterObject::density");
          "@see WaterObject::density");

+ 82 - 81
Engine/source/T3D/player.cpp

@@ -699,19 +699,20 @@ bool PlayerData::isJumpAction(U32 action)
 {
 {
    return (action == JumpAnim || action == StandJumpAnim);
    return (action == JumpAnim || action == StandJumpAnim);
 }
 }
+IRangeValidator jumpDelayRange(0, 1 << PlayerData::JumpDelayBits);
 
 
 void PlayerData::initPersistFields()
 void PlayerData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
    Parent::initPersistFields();
    Parent::initPersistFields();
 
 
-   addField( "pickupRadius", TypeF32, Offset(pickupRadius, PlayerData),
+   addFieldV( "pickupRadius", TypeRangedF32, Offset(pickupRadius, PlayerData), &CommonValidators::PositiveFloat,
       "@brief Radius around the player to collide with Items in the scene (on server).\n\n"
       "@brief Radius around the player to collide with Items in the scene (on server).\n\n"
       "Internally the pickupRadius is added to the larger side of the initial bounding box "
       "Internally the pickupRadius is added to the larger side of the initial bounding box "
       "to determine the actual distance, to a maximum of 2 times the bounding box size.  The "
       "to determine the actual distance, to a maximum of 2 times the bounding box size.  The "
       "initial bounding box is that used for the root pose, and therefore doesn't take into "
       "initial bounding box is that used for the root pose, and therefore doesn't take into "
       "account the change in pose.\n");
       "account the change in pose.\n");
-   addField( "maxTimeScale", TypeF32, Offset(maxTimeScale, PlayerData),
+   addFieldV( "maxTimeScale", TypeRangedF32, Offset(maxTimeScale, PlayerData), &CommonValidators::PositiveFloat,
       "@brief Maximum time scale for action animations.\n\n"
       "@brief Maximum time scale for action animations.\n\n"
       "If an action animation has a defined ground frame, it is automatically scaled to match the "
       "If an action animation has a defined ground frame, it is automatically scaled to match the "
       "player's ground velocity.  This field limits the maximum time scale used even if "
       "player's ground velocity.  This field limits the maximum time scale used even if "
@@ -725,13 +726,13 @@ void PlayerData::initPersistFields()
       addField( "firstPersonShadows", TypeBool, Offset(firstPersonShadows, PlayerData),
       addField( "firstPersonShadows", TypeBool, Offset(firstPersonShadows, PlayerData),
          "@brief Forces shadows to be rendered in first person when renderFirstPerson is disabled.  Defaults to false.\n\n" );
          "@brief Forces shadows to be rendered in first person when renderFirstPerson is disabled.  Defaults to false.\n\n" );
 
 
-      addField( "minLookAngle", TypeF32, Offset(minLookAngle, PlayerData),
+      addFieldV( "minLookAngle", TypeRangedF32, Offset(minLookAngle, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Lowest angle (in radians) the player can look.\n\n"
          "@brief Lowest angle (in radians) the player can look.\n\n"
          "@note An angle of zero is straight ahead, with positive up and negative down." );
          "@note An angle of zero is straight ahead, with positive up and negative down." );
-      addField( "maxLookAngle", TypeF32, Offset(maxLookAngle, PlayerData),
+      addFieldV( "maxLookAngle", TypeRangedF32, Offset(maxLookAngle, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Highest angle (in radians) the player can look.\n\n"
          "@brief Highest angle (in radians) the player can look.\n\n"
          "@note An angle of zero is straight ahead, with positive up and negative down." );
          "@note An angle of zero is straight ahead, with positive up and negative down." );
-      addField( "maxFreelookAngle", TypeF32, Offset(maxFreelookAngle, PlayerData),
+      addFieldV( "maxFreelookAngle", TypeRangedF32, Offset(maxFreelookAngle, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Defines the maximum left and right angles (in radians) the player can "
          "@brief Defines the maximum left and right angles (in radians) the player can "
          "look in freelook mode.\n\n" );
          "look in freelook mode.\n\n" );
 
 
@@ -739,72 +740,72 @@ void PlayerData::initPersistFields()
 
 
    addGroup( "Movement" );
    addGroup( "Movement" );
 
 
-      addField( "maxStepHeight", TypeF32, Offset(maxStepHeight, PlayerData),
+      addFieldV( "maxStepHeight", TypeRangedF32, Offset(maxStepHeight, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum height the player can step up.\n\n"
          "@brief Maximum height the player can step up.\n\n"
          "The player will automatically step onto changes in ground height less "
          "The player will automatically step onto changes in ground height less "
          "than maxStepHeight.  The player will collide with ground height changes "
          "than maxStepHeight.  The player will collide with ground height changes "
          "greater than this." );
          "greater than this." );
 
 
-      addField( "runForce", TypeF32, Offset(runForce, PlayerData),
+      addFieldV( "runForce", TypeRangedF32, Offset(runForce, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Force used to accelerate the player when running.\n\n" );
          "@brief Force used to accelerate the player when running.\n\n" );
 
 
-      addField( "runEnergyDrain", TypeF32, Offset(runEnergyDrain, PlayerData),
+      addFieldV( "runEnergyDrain", TypeRangedF32, Offset(runEnergyDrain, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Energy value drained each tick that the player is moving.\n\n"
          "@brief Energy value drained each tick that the player is moving.\n\n"
          "The player will not be able to move when his energy falls below "
          "The player will not be able to move when his energy falls below "
          "minRunEnergy.\n"
          "minRunEnergy.\n"
          "@note Setting this to zero will disable any energy drain.\n"
          "@note Setting this to zero will disable any energy drain.\n"
          "@see minRunEnergy\n");
          "@see minRunEnergy\n");
-      addField( "minRunEnergy", TypeF32, Offset(minRunEnergy, PlayerData),
+      addFieldV( "minRunEnergy", TypeRangedF32, Offset(minRunEnergy, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum energy level required to run or swim.\n\n"
          "@brief Minimum energy level required to run or swim.\n\n"
          "@see runEnergyDrain\n");
          "@see runEnergyDrain\n");
 
 
-      addField( "maxForwardSpeed", TypeF32, Offset(maxForwardSpeed, PlayerData),
+      addFieldV( "maxForwardSpeed", TypeRangedF32, Offset(maxForwardSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum forward speed when running." );
          "@brief Maximum forward speed when running." );
-      addField( "maxBackwardSpeed", TypeF32, Offset(maxBackwardSpeed, PlayerData),
+      addFieldV( "maxBackwardSpeed", TypeRangedF32, Offset(maxBackwardSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum backward speed when running." );
          "@brief Maximum backward speed when running." );
-      addField( "maxSideSpeed", TypeF32, Offset(maxSideSpeed, PlayerData),
+      addFieldV( "maxSideSpeed", TypeRangedF32, Offset(maxSideSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum sideways speed when running." );
          "@brief Maximum sideways speed when running." );
 
 
-      addField( "runSurfaceAngle", TypeF32, Offset(runSurfaceAngle, PlayerData),
+      addFieldV( "runSurfaceAngle", TypeRangedF32, Offset(runSurfaceAngle, PlayerData), &CommonValidators::PosDegreeRangeQuarter,
          "@brief Maximum angle from vertical (in degrees) the player can run up.\n\n" );
          "@brief Maximum angle from vertical (in degrees) the player can run up.\n\n" );
 
 
-      addField( "minImpactSpeed", TypeF32, Offset(minImpactSpeed, PlayerData),
+      addFieldV( "minImpactSpeed", TypeRangedF32, Offset(minImpactSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum impact speed to apply falling damage.\n\n"
          "@brief Minimum impact speed to apply falling damage.\n\n"
          "This field also sets the minimum speed for the onImpact callback "
          "This field also sets the minimum speed for the onImpact callback "
          "to be invoked.\n"
          "to be invoked.\n"
          "@see ShapeBaseData::onImpact()\n");
          "@see ShapeBaseData::onImpact()\n");
-      addField( "minLateralImpactSpeed", TypeF32, Offset(minLateralImpactSpeed, PlayerData),
+      addFieldV( "minLateralImpactSpeed", TypeRangedF32, Offset(minLateralImpactSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum impact speed to apply non-falling damage.\n\n"
          "@brief Minimum impact speed to apply non-falling damage.\n\n"
          "This field also sets the minimum speed for the onLateralImpact callback "
          "This field also sets the minimum speed for the onLateralImpact callback "
          "to be invoked.\n"
          "to be invoked.\n"
          "@see ShapeBaseData::onLateralImpact()\n");
          "@see ShapeBaseData::onLateralImpact()\n");
 
 
-      addField( "horizMaxSpeed", TypeF32, Offset(horizMaxSpeed, PlayerData),
+      addFieldV( "horizMaxSpeed", TypeRangedF32, Offset(horizMaxSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum horizontal speed.\n\n"
          "@brief Maximum horizontal speed.\n\n"
          "@note This limit is only enforced if the player's horizontal speed "
          "@note This limit is only enforced if the player's horizontal speed "
          "exceeds horizResistSpeed.\n"
          "exceeds horizResistSpeed.\n"
          "@see horizResistSpeed\n"
          "@see horizResistSpeed\n"
          "@see horizResistFactor\n" );
          "@see horizResistFactor\n" );
-      addField( "horizResistSpeed", TypeF32, Offset(horizResistSpeed, PlayerData),
+      addFieldV( "horizResistSpeed", TypeRangedF32, Offset(horizResistSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Horizontal speed at which resistence will take place.\n\n"
          "@brief Horizontal speed at which resistence will take place.\n\n"
          "@see horizMaxSpeed\n"
          "@see horizMaxSpeed\n"
          "@see horizResistFactor\n" );
          "@see horizResistFactor\n" );
-      addField( "horizResistFactor", TypeF32, Offset(horizResistFactor, PlayerData),
+      addFieldV( "horizResistFactor", TypeRangedF32, Offset(horizResistFactor, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Factor of resistence once horizResistSpeed has been reached.\n\n"
          "@brief Factor of resistence once horizResistSpeed has been reached.\n\n"
          "@see horizMaxSpeed\n"
          "@see horizMaxSpeed\n"
          "@see horizResistSpeed\n" );
          "@see horizResistSpeed\n" );
 
 
-      addField( "upMaxSpeed", TypeF32, Offset(upMaxSpeed, PlayerData),
+      addFieldV( "upMaxSpeed", TypeRangedF32, Offset(upMaxSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum upwards speed.\n\n"
          "@brief Maximum upwards speed.\n\n"
          "@note This limit is only enforced if the player's upward speed exceeds "
          "@note This limit is only enforced if the player's upward speed exceeds "
          "upResistSpeed.\n"
          "upResistSpeed.\n"
          "@see upResistSpeed\n"
          "@see upResistSpeed\n"
          "@see upResistFactor\n" );
          "@see upResistFactor\n" );
-      addField( "upResistSpeed", TypeF32, Offset(upResistSpeed, PlayerData),
+      addFieldV( "upResistSpeed", TypeRangedF32, Offset(upResistSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Upwards speed at which resistence will take place.\n\n"
          "@brief Upwards speed at which resistence will take place.\n\n"
          "@see upMaxSpeed\n"
          "@see upMaxSpeed\n"
          "@see upResistFactor\n" );
          "@see upResistFactor\n" );
-      addField( "upResistFactor", TypeF32, Offset(upResistFactor, PlayerData),
+      addFieldV( "upResistFactor", TypeRangedF32, Offset(upResistFactor, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Factor of resistence once upResistSpeed has been reached.\n\n"
          "@brief Factor of resistence once upResistSpeed has been reached.\n\n"
          "@see upMaxSpeed\n"
          "@see upMaxSpeed\n"
          "@see upResistSpeed\n" );
          "@see upResistSpeed\n" );
@@ -813,29 +814,29 @@ void PlayerData::initPersistFields()
    
    
    addGroup( "Movement: Jumping" );
    addGroup( "Movement: Jumping" );
 
 
-      addField( "jumpForce", TypeF32, Offset(jumpForce, PlayerData),
+      addFieldV( "jumpForce", TypeRangedF32, Offset(jumpForce, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Force used to accelerate the player when a jump is initiated.\n\n" );
          "@brief Force used to accelerate the player when a jump is initiated.\n\n" );
 
 
-      addField( "jumpEnergyDrain", TypeF32, Offset(jumpEnergyDrain, PlayerData),
+      addFieldV( "jumpEnergyDrain", TypeRangedF32, Offset(jumpEnergyDrain, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Energy level drained each time the player jumps.\n\n"
          "@brief Energy level drained each time the player jumps.\n\n"
          "@note Setting this to zero will disable any energy drain\n"
          "@note Setting this to zero will disable any energy drain\n"
          "@see minJumpEnergy\n");
          "@see minJumpEnergy\n");
-      addField( "minJumpEnergy", TypeF32, Offset(minJumpEnergy, PlayerData),
+      addFieldV( "minJumpEnergy", TypeRangedF32, Offset(minJumpEnergy, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum energy level required to jump.\n\n"
          "@brief Minimum energy level required to jump.\n\n"
          "@see jumpEnergyDrain\n");
          "@see jumpEnergyDrain\n");
 
 
-      addField( "minJumpSpeed", TypeF32, Offset(minJumpSpeed, PlayerData),
+      addFieldV( "minJumpSpeed", TypeRangedF32, Offset(minJumpSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum speed needed to jump.\n\n"
          "@brief Minimum speed needed to jump.\n\n"
          "If the player's own z velocity is greater than this, then it is used to scale "
          "If the player's own z velocity is greater than this, then it is used to scale "
          "the jump speed, up to maxJumpSpeed.\n"
          "the jump speed, up to maxJumpSpeed.\n"
          "@see maxJumpSpeed\n");
          "@see maxJumpSpeed\n");
-      addField( "maxJumpSpeed", TypeF32, Offset(maxJumpSpeed, PlayerData),
+      addFieldV( "maxJumpSpeed", TypeRangedF32, Offset(maxJumpSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum vertical speed before the player can no longer jump.\n\n" );
          "@brief Maximum vertical speed before the player can no longer jump.\n\n" );
-      addField( "jumpSurfaceAngle", TypeF32, Offset(jumpSurfaceAngle, PlayerData),
+      addFieldV( "jumpSurfaceAngle", TypeRangedF32, Offset(jumpSurfaceAngle, PlayerData), &CommonValidators::PosDegreeRangeQuarter,
          "@brief Angle from vertical (in degrees) where the player can jump.\n\n" );
          "@brief Angle from vertical (in degrees) where the player can jump.\n\n" );
-      addField( "jumpDelay", TypeS32, Offset(jumpDelay, PlayerData),
+      addFieldV( "jumpDelay", TypeRangedS32, Offset(jumpDelay, PlayerData), &jumpDelayRange,
          "@brief Delay time in number of ticks ticks between jumps.\n\n" );
          "@brief Delay time in number of ticks ticks between jumps.\n\n" );
-      addField( "airControl", TypeF32, Offset(airControl, PlayerData),
+      addFieldV( "airControl", TypeRangedF32, Offset(airControl, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Amount of movement control the player has when in the air.\n\n"
          "@brief Amount of movement control the player has when in the air.\n\n"
          "This is applied as a multiplier to the player's x and y motion.\n");
          "This is applied as a multiplier to the player's x and y motion.\n");
       addField( "jumpTowardsNormal", TypeBool, Offset(jumpTowardsNormal, PlayerData),
       addField( "jumpTowardsNormal", TypeBool, Offset(jumpTowardsNormal, PlayerData),
@@ -849,31 +850,31 @@ void PlayerData::initPersistFields()
    
    
    addGroup( "Movement: Sprinting" );
    addGroup( "Movement: Sprinting" );
 
 
-      addField( "sprintForce", TypeF32, Offset(sprintForce, PlayerData),
+      addFieldV( "sprintForce", TypeRangedF32, Offset(sprintForce, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Force used to accelerate the player when sprinting.\n\n" );
          "@brief Force used to accelerate the player when sprinting.\n\n" );
 
 
-      addField( "sprintEnergyDrain", TypeF32, Offset(sprintEnergyDrain, PlayerData),
+      addFieldV( "sprintEnergyDrain", TypeRangedF32, Offset(sprintEnergyDrain, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Energy value drained each tick that the player is sprinting.\n\n"
          "@brief Energy value drained each tick that the player is sprinting.\n\n"
          "The player will not be able to move when his energy falls below "
          "The player will not be able to move when his energy falls below "
          "sprintEnergyDrain.\n"
          "sprintEnergyDrain.\n"
          "@note Setting this to zero will disable any energy drain.\n"
          "@note Setting this to zero will disable any energy drain.\n"
          "@see minSprintEnergy\n");
          "@see minSprintEnergy\n");
-      addField( "minSprintEnergy", TypeF32, Offset(minSprintEnergy, PlayerData),
+      addFieldV( "minSprintEnergy", TypeRangedF32, Offset(minSprintEnergy, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum energy level required to sprint.\n\n"
          "@brief Minimum energy level required to sprint.\n\n"
          "@see sprintEnergyDrain\n");
          "@see sprintEnergyDrain\n");
 
 
-      addField( "maxSprintForwardSpeed", TypeF32, Offset(maxSprintForwardSpeed, PlayerData),
+      addFieldV( "maxSprintForwardSpeed", TypeRangedF32, Offset(maxSprintForwardSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum forward speed when sprinting." );
          "@brief Maximum forward speed when sprinting." );
-      addField( "maxSprintBackwardSpeed", TypeF32, Offset(maxSprintBackwardSpeed, PlayerData),
+      addFieldV( "maxSprintBackwardSpeed", TypeRangedF32, Offset(maxSprintBackwardSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum backward speed when sprinting." );
          "@brief Maximum backward speed when sprinting." );
-      addField( "maxSprintSideSpeed", TypeF32, Offset(maxSprintSideSpeed, PlayerData),
+      addFieldV( "maxSprintSideSpeed", TypeRangedF32, Offset(maxSprintSideSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum sideways speed when sprinting." );
          "@brief Maximum sideways speed when sprinting." );
 
 
-      addField( "sprintStrafeScale", TypeF32, Offset(sprintStrafeScale, PlayerData),
+      addFieldV( "sprintStrafeScale", TypeRangedF32, Offset(sprintStrafeScale, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Amount to scale strafing motion vector while sprinting." );
          "@brief Amount to scale strafing motion vector while sprinting." );
-      addField( "sprintYawScale", TypeF32, Offset(sprintYawScale, PlayerData),
+      addFieldV( "sprintYawScale", TypeRangedF32, Offset(sprintYawScale, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Amount to scale yaw motion while sprinting." );
          "@brief Amount to scale yaw motion while sprinting." );
-      addField( "sprintPitchScale", TypeF32, Offset(sprintPitchScale, PlayerData),
+      addFieldV( "sprintPitchScale", TypeRangedF32, Offset(sprintPitchScale, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Amount to scale pitch motion while sprinting." );
          "@brief Amount to scale pitch motion while sprinting." );
 
 
       addField( "sprintCanJump", TypeBool, Offset(sprintCanJump, PlayerData),
       addField( "sprintCanJump", TypeBool, Offset(sprintCanJump, PlayerData),
@@ -883,82 +884,82 @@ void PlayerData::initPersistFields()
 
 
    addGroup( "Movement: Swimming" );
    addGroup( "Movement: Swimming" );
 
 
-      addField( "swimForce", TypeF32, Offset(swimForce, PlayerData),
+      addFieldV( "swimForce", TypeRangedF32, Offset(swimForce, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Force used to accelerate the player when swimming.\n\n" );
          "@brief Force used to accelerate the player when swimming.\n\n" );
-      addField( "maxUnderwaterForwardSpeed", TypeF32, Offset(maxUnderwaterForwardSpeed, PlayerData),
+      addFieldV( "maxUnderwaterForwardSpeed", TypeRangedF32, Offset(maxUnderwaterForwardSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum forward speed when underwater.\n\n" );
          "@brief Maximum forward speed when underwater.\n\n" );
-      addField( "maxUnderwaterBackwardSpeed", TypeF32, Offset(maxUnderwaterBackwardSpeed, PlayerData),
+      addFieldV( "maxUnderwaterBackwardSpeed", TypeRangedF32, Offset(maxUnderwaterBackwardSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum backward speed when underwater.\n\n" );
          "@brief Maximum backward speed when underwater.\n\n" );
-      addField( "maxUnderwaterSideSpeed", TypeF32, Offset(maxUnderwaterSideSpeed, PlayerData),
+      addFieldV( "maxUnderwaterSideSpeed", TypeRangedF32, Offset(maxUnderwaterSideSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum sideways speed when underwater.\n\n" );
          "@brief Maximum sideways speed when underwater.\n\n" );
 
 
    endGroup( "Movement: Swimming" );
    endGroup( "Movement: Swimming" );
 
 
    addGroup( "Movement: Crouching" );
    addGroup( "Movement: Crouching" );
 
 
-      addField( "crouchForce", TypeF32, Offset(crouchForce, PlayerData),
+      addFieldV( "crouchForce", TypeRangedF32, Offset(crouchForce, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Force used to accelerate the player when crouching.\n\n" );
          "@brief Force used to accelerate the player when crouching.\n\n" );
-      addField( "maxCrouchForwardSpeed", TypeF32, Offset(maxCrouchForwardSpeed, PlayerData),
+      addFieldV( "maxCrouchForwardSpeed", TypeRangedF32, Offset(maxCrouchForwardSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum forward speed when crouching.\n\n" );
          "@brief Maximum forward speed when crouching.\n\n" );
-      addField( "maxCrouchBackwardSpeed", TypeF32, Offset(maxCrouchBackwardSpeed, PlayerData),
+      addFieldV( "maxCrouchBackwardSpeed", TypeRangedF32, Offset(maxCrouchBackwardSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum backward speed when crouching.\n\n" );
          "@brief Maximum backward speed when crouching.\n\n" );
-      addField( "maxCrouchSideSpeed", TypeF32, Offset(maxCrouchSideSpeed, PlayerData),
+      addFieldV( "maxCrouchSideSpeed", TypeRangedF32, Offset(maxCrouchSideSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum sideways speed when crouching.\n\n" );
          "@brief Maximum sideways speed when crouching.\n\n" );
 
 
    endGroup( "Movement: Crouching" );
    endGroup( "Movement: Crouching" );
 
 
    addGroup( "Movement: Prone" );
    addGroup( "Movement: Prone" );
 
 
-      addField( "proneForce", TypeF32, Offset(proneForce, PlayerData),
+      addFieldV( "proneForce", TypeRangedF32, Offset(proneForce, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Force used to accelerate the player when prone (laying down).\n\n" );
          "@brief Force used to accelerate the player when prone (laying down).\n\n" );
-      addField( "maxProneForwardSpeed", TypeF32, Offset(maxProneForwardSpeed, PlayerData),
+      addFieldV( "maxProneForwardSpeed", TypeRangedF32, Offset(maxProneForwardSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum forward speed when prone (laying down).\n\n" );
          "@brief Maximum forward speed when prone (laying down).\n\n" );
-      addField( "maxProneBackwardSpeed", TypeF32, Offset(maxProneBackwardSpeed, PlayerData),
+      addFieldV( "maxProneBackwardSpeed", TypeRangedF32, Offset(maxProneBackwardSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum backward speed when prone (laying down).\n\n" );
          "@brief Maximum backward speed when prone (laying down).\n\n" );
-      addField( "maxProneSideSpeed", TypeF32, Offset(maxProneSideSpeed, PlayerData),
+      addFieldV( "maxProneSideSpeed", TypeRangedF32, Offset(maxProneSideSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum sideways speed when prone (laying down).\n\n" );
          "@brief Maximum sideways speed when prone (laying down).\n\n" );
 
 
    endGroup( "Movement: Prone" );
    endGroup( "Movement: Prone" );
 
 
    addGroup( "Movement: Jetting" );
    addGroup( "Movement: Jetting" );
 
 
-      addField( "jetJumpForce", TypeF32, Offset(jetJumpForce, PlayerData),
+      addFieldV( "jetJumpForce", TypeRangedF32, Offset(jetJumpForce, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Force used to accelerate the player when a jet jump is initiated.\n\n" );
          "@brief Force used to accelerate the player when a jet jump is initiated.\n\n" );
 
 
-      addField( "jetJumpEnergyDrain", TypeF32, Offset(jetJumpEnergyDrain, PlayerData),
+      addFieldV( "jetJumpEnergyDrain", TypeRangedF32, Offset(jetJumpEnergyDrain, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Energy level drained each time the player jet jumps.\n\n"
          "@brief Energy level drained each time the player jet jumps.\n\n"
          "@note Setting this to zero will disable any energy drain\n"
          "@note Setting this to zero will disable any energy drain\n"
          "@see jetMinJumpEnergy\n");
          "@see jetMinJumpEnergy\n");
-      addField( "jetMinJumpEnergy", TypeF32, Offset(jetMinJumpEnergy, PlayerData),
+      addFieldV( "jetMinJumpEnergy", TypeRangedF32, Offset(jetMinJumpEnergy, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum energy level required to jet jump.\n\n"
          "@brief Minimum energy level required to jet jump.\n\n"
          "@see jetJumpEnergyDrain\n");
          "@see jetJumpEnergyDrain\n");
 
 
-      addField( "jetMinJumpSpeed", TypeF32, Offset(jetMinJumpSpeed, PlayerData),
+      addFieldV( "jetMinJumpSpeed", TypeRangedF32, Offset(jetMinJumpSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum speed needed to jet jump.\n\n"
          "@brief Minimum speed needed to jet jump.\n\n"
          "If the player's own z velocity is greater than this, then it is used to scale "
          "If the player's own z velocity is greater than this, then it is used to scale "
          "the jet jump speed, up to jetMaxJumpSpeed.\n"
          "the jet jump speed, up to jetMaxJumpSpeed.\n"
          "@see jetMaxJumpSpeed\n");
          "@see jetMaxJumpSpeed\n");
-      addField( "jetMaxJumpSpeed", TypeF32, Offset(jetMaxJumpSpeed, PlayerData),
+      addFieldV( "jetMaxJumpSpeed", TypeRangedF32, Offset(jetMaxJumpSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Maximum vertical speed before the player can no longer jet jump.\n\n" );
          "@brief Maximum vertical speed before the player can no longer jet jump.\n\n" );
-      addField( "jetJumpSurfaceAngle", TypeF32, Offset(jetJumpSurfaceAngle, PlayerData),
+      addFieldV( "jetJumpSurfaceAngle", TypeRangedF32, Offset(jetJumpSurfaceAngle, PlayerData), &CommonValidators::PosDegreeRangeQuarter,
          "@brief Angle from vertical (in degrees) where the player can jet jump.\n\n" );
          "@brief Angle from vertical (in degrees) where the player can jet jump.\n\n" );
 
 
    endGroup( "Movement: Jetting" );
    endGroup( "Movement: Jetting" );
 
 
    addGroup( "Falling" );
    addGroup( "Falling" );
 
 
-      addField( "fallingSpeedThreshold", TypeF32, Offset(fallingSpeedThreshold, PlayerData),
+      addFieldV( "fallingSpeedThreshold", TypeRangedF32, Offset(fallingSpeedThreshold, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Downward speed at which we consider the player falling.\n\n" );
          "@brief Downward speed at which we consider the player falling.\n\n" );
 
 
-      addField( "recoverDelay", TypeS32, Offset(recoverDelay, PlayerData),
+      addFieldV( "recoverDelay", TypeRangedS32, Offset(recoverDelay, PlayerData), &CommonValidators::PositiveInt,
          "@brief Number of ticks for the player to recover from falling.\n\n" );
          "@brief Number of ticks for the player to recover from falling.\n\n" );
 
 
-      addField( "recoverRunForceScale", TypeF32, Offset(recoverRunForceScale, PlayerData),
+      addFieldV( "recoverRunForceScale", TypeRangedF32, Offset(recoverRunForceScale, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Scale factor applied to runForce while in the recover state.\n\n"
          "@brief Scale factor applied to runForce while in the recover state.\n\n"
          "This can be used to temporarily slow the player's movement after a fall, or "
          "This can be used to temporarily slow the player's movement after a fall, or "
          "prevent the player from moving at all if set to zero.\n" );
          "prevent the player from moving at all if set to zero.\n" );
 
 
-      addField( "landSequenceTime", TypeF32, Offset(landSequenceTime, PlayerData),
+      addFieldV( "landSequenceTime", TypeRangedF32, Offset(landSequenceTime, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Time of land sequence play back when using new recover system.\n\n"
          "@brief Time of land sequence play back when using new recover system.\n\n"
          "If greater than 0 then the legacy fall recovery system will be bypassed "
          "If greater than 0 then the legacy fall recovery system will be bypassed "
          "in favour of just playing the player's land sequence.  The time to "
          "in favour of just playing the player's land sequence.  The time to "
@@ -988,27 +989,27 @@ void PlayerData::initPersistFields()
          "@brief Collision bounding box used when the player is swimming.\n\n"
          "@brief Collision bounding box used when the player is swimming.\n\n"
          "@see boundingBox" );
          "@see boundingBox" );
 
 
-      addField( "boxHeadPercentage", TypeF32, Offset(boxHeadPercentage, PlayerData),
+      addFieldV( "boxHeadPercentage", TypeRangedF32, Offset(boxHeadPercentage, PlayerData), &CommonValidators::NormalizedFloat,
          "@brief Percentage of the player's bounding box height that represents the head.\n\n"
          "@brief Percentage of the player's bounding box height that represents the head.\n\n"
          "Used when computing the damage location.\n"
          "Used when computing the damage location.\n"
          "@see Player::getDamageLocation" );
          "@see Player::getDamageLocation" );
-      addField( "boxTorsoPercentage", TypeF32, Offset(boxTorsoPercentage, PlayerData),
+      addFieldV( "boxTorsoPercentage", TypeRangedF32, Offset(boxTorsoPercentage, PlayerData), &CommonValidators::NormalizedFloat,
          "@brief Percentage of the player's bounding box height that represents the torso.\n\n"
          "@brief Percentage of the player's bounding box height that represents the torso.\n\n"
          "Used when computing the damage location.\n"
          "Used when computing the damage location.\n"
          "@see Player::getDamageLocation" );
          "@see Player::getDamageLocation" );
-      addField( "boxHeadLeftPercentage", TypeF32, Offset(boxHeadLeftPercentage, PlayerData),
+      addFieldV( "boxHeadLeftPercentage", TypeRangedF32, Offset(boxHeadLeftPercentage, PlayerData), &CommonValidators::NormalizedFloat,
          "@brief Percentage of the player's bounding box width that represents the left side of the head.\n\n"
          "@brief Percentage of the player's bounding box width that represents the left side of the head.\n\n"
          "Used when computing the damage location.\n"
          "Used when computing the damage location.\n"
          "@see Player::getDamageLocation" );
          "@see Player::getDamageLocation" );
-      addField( "boxHeadRightPercentage", TypeF32, Offset(boxHeadRightPercentage, PlayerData),
+      addFieldV( "boxHeadRightPercentage", TypeRangedF32, Offset(boxHeadRightPercentage, PlayerData), &CommonValidators::NormalizedFloat,
          "@brief Percentage of the player's bounding box width that represents the right side of the head.\n\n"
          "@brief Percentage of the player's bounding box width that represents the right side of the head.\n\n"
          "Used when computing the damage location.\n"
          "Used when computing the damage location.\n"
          "@see Player::getDamageLocation" );
          "@see Player::getDamageLocation" );
-      addField( "boxHeadBackPercentage", TypeF32, Offset(boxHeadBackPercentage, PlayerData),
+      addFieldV( "boxHeadBackPercentage", TypeRangedF32, Offset(boxHeadBackPercentage, PlayerData), &CommonValidators::NormalizedFloat,
          "@brief Percentage of the player's bounding box depth that represents the back side of the head.\n\n"
          "@brief Percentage of the player's bounding box depth that represents the back side of the head.\n\n"
          "Used when computing the damage location.\n"
          "Used when computing the damage location.\n"
          "@see Player::getDamageLocation" );
          "@see Player::getDamageLocation" );
-      addField( "boxHeadFrontPercentage", TypeF32, Offset(boxHeadFrontPercentage, PlayerData),
+      addFieldV( "boxHeadFrontPercentage", TypeRangedF32, Offset(boxHeadFrontPercentage, PlayerData), &CommonValidators::NormalizedFloat,
          "@brief Percentage of the player's bounding box depth that represents the front side of the head.\n\n"
          "@brief Percentage of the player's bounding box depth that represents the front side of the head.\n\n"
          "Used when computing the damage location.\n"
          "Used when computing the damage location.\n"
          "@see Player::getDamageLocation" );
          "@see Player::getDamageLocation" );
@@ -1022,12 +1023,12 @@ void PlayerData::initPersistFields()
          "walks along the ground).\n\n"
          "walks along the ground).\n\n"
          "@note The generation of foot puffs requires the appropriate triggeres to be defined in the "
          "@note The generation of foot puffs requires the appropriate triggeres to be defined in the "
          "player's animation sequences.  Without these, no foot puffs will be generated.\n");
          "player's animation sequences.  Without these, no foot puffs will be generated.\n");
-      addField( "footPuffNumParts", TypeS32, Offset(footPuffNumParts, PlayerData),
+      addFieldV( "footPuffNumParts", TypeRangedS32, Offset(footPuffNumParts, PlayerData), &CommonValidators::PositiveInt,
          "@brief Number of footpuff particles to generate each step.\n\n"
          "@brief Number of footpuff particles to generate each step.\n\n"
          "Each foot puff is randomly placed within the defined foot puff radius.  This "
          "Each foot puff is randomly placed within the defined foot puff radius.  This "
          "includes having footPuffNumParts set to one.\n"
          "includes having footPuffNumParts set to one.\n"
          "@see footPuffRadius\n");
          "@see footPuffRadius\n");
-      addField( "footPuffRadius", TypeF32, Offset(footPuffRadius, PlayerData),
+      addFieldV( "footPuffRadius", TypeRangedF32, Offset(footPuffRadius, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Particle creation radius for footpuff particles.\n\n"
          "@brief Particle creation radius for footpuff particles.\n\n"
          "This is applied to each foot puff particle, even if footPuffNumParts is set to one.  So "
          "This is applied to each foot puff particle, even if footPuffNumParts is set to one.  So "
          "set this value to zero if you want a single foot puff placed at exactly the same location "
          "set this value to zero if you want a single foot puff placed at exactly the same location "
@@ -1038,7 +1039,7 @@ void PlayerData::initPersistFields()
 
 
       addField( "decalData", TYPEID< DecalData >(), Offset(decalData, PlayerData),
       addField( "decalData", TYPEID< DecalData >(), Offset(decalData, PlayerData),
          "@brief Decal to place on the ground for player footsteps.\n\n" );
          "@brief Decal to place on the ground for player footsteps.\n\n" );
-      addField( "decalOffset",TypeF32, Offset(decalOffset, PlayerData),
+      addFieldV( "decalOffset", TypeRangedF32, Offset(decalOffset, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Distance from the center of the model to the right foot.\n\n"
          "@brief Distance from the center of the model to the right foot.\n\n"
          "While this defines the distance to the right foot, it is also used to place "
          "While this defines the distance to the right foot, it is also used to place "
          "the left foot decal as well.  Just on the opposite side of the player." );
          "the left foot decal as well.  Just on the opposite side of the player." );
@@ -1054,37 +1055,37 @@ void PlayerData::initPersistFields()
       addField( "splash", TYPEID< SplashData >(), Offset(splash, PlayerData),
       addField( "splash", TYPEID< SplashData >(), Offset(splash, PlayerData),
          "@brief SplashData datablock used to create splashes when the player moves "
          "@brief SplashData datablock used to create splashes when the player moves "
          "through water.\n\n" );
          "through water.\n\n" );
-      addField( "splashVelocity", TypeF32, Offset(splashVelocity, PlayerData),
+      addFieldV( "splashVelocity", TypeRangedF32, Offset(splashVelocity, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum velocity when moving through water to generate splashes.\n\n" );
          "@brief Minimum velocity when moving through water to generate splashes.\n\n" );
-      addField( "splashAngle", TypeF32, Offset(splashAngle, PlayerData),
+      addFieldV( "splashAngle", TypeRangedF32, Offset(splashAngle, PlayerData), &CommonValidators::PosDegreeRange,
          "@brief Maximum angle (in degrees) from pure vertical movement in water to "
          "@brief Maximum angle (in degrees) from pure vertical movement in water to "
          "generate splashes.\n\n" );
          "generate splashes.\n\n" );
 
 
-      addField( "splashFreqMod", TypeF32, Offset(splashFreqMod, PlayerData),
+      addFieldV( "splashFreqMod", TypeRangedF32, Offset(splashFreqMod, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Multipled by speed to determine the number of splash particles to generate.\n\n" );
          "@brief Multipled by speed to determine the number of splash particles to generate.\n\n" );
-      addField( "splashVelEpsilon", TypeF32, Offset(splashVelEpsilon, PlayerData),
+      addFieldV( "splashVelEpsilon", TypeRangedF32, Offset(splashVelEpsilon, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum speed to generate splash particles.\n\n" );
          "@brief Minimum speed to generate splash particles.\n\n" );
-      addField( "bubbleEmitTime", TypeF32, Offset(bubbleEmitTime, PlayerData),
+      addFieldV( "bubbleEmitTime", TypeRangedF32, Offset(bubbleEmitTime, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Time in seconds to generate bubble particles after entering the water.\n\n" );
          "@brief Time in seconds to generate bubble particles after entering the water.\n\n" );
       addField( "splashEmitter", TYPEID< ParticleEmitterData >(), Offset(splashEmitterList, PlayerData), NUM_SPLASH_EMITTERS,
       addField( "splashEmitter", TYPEID< ParticleEmitterData >(), Offset(splashEmitterList, PlayerData), NUM_SPLASH_EMITTERS,
          "@brief Particle emitters used to generate splash particles.\n\n" );
          "@brief Particle emitters used to generate splash particles.\n\n" );
 
 
-      addField( "footstepSplashHeight", TypeF32, Offset(footSplashHeight, PlayerData),
+      addFieldV( "footstepSplashHeight", TypeRangedF32, Offset(footSplashHeight, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Water coverage level to choose between FootShallowSound and FootWadingSound.\n\n"
          "@brief Water coverage level to choose between FootShallowSound and FootWadingSound.\n\n"
          "@see FootShallowSound\n"
          "@see FootShallowSound\n"
          "@see FootWadingSound\n");
          "@see FootWadingSound\n");
 
 
-      addField( "mediumSplashSoundVelocity", TypeF32, Offset(medSplashSoundVel, PlayerData),
+      addFieldV( "mediumSplashSoundVelocity", TypeRangedF32, Offset(medSplashSoundVel, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum velocity when entering the water for choosing between the impactWaterEasy and "
          "@brief Minimum velocity when entering the water for choosing between the impactWaterEasy and "
          "impactWaterMedium sounds to play.\n\n"
          "impactWaterMedium sounds to play.\n\n"
          "@see impactWaterEasy\n"
          "@see impactWaterEasy\n"
          "@see impactWaterMedium\n" );
          "@see impactWaterMedium\n" );
-      addField( "hardSplashSoundVelocity", TypeF32, Offset(hardSplashSoundVel, PlayerData),
+      addFieldV( "hardSplashSoundVelocity", TypeRangedF32, Offset(hardSplashSoundVel, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum velocity when entering the water for choosing between the impactWaterMedium and "
          "@brief Minimum velocity when entering the water for choosing between the impactWaterMedium and "
          "impactWaterHard sound to play.\n\n"
          "impactWaterHard sound to play.\n\n"
          "@see impactWaterMedium\n"
          "@see impactWaterMedium\n"
          "@see impactWaterHard\n" );
          "@see impactWaterHard\n" );
-      addField( "exitSplashSoundVelocity", TypeF32, Offset(exitSplashSoundVel, PlayerData),
+      addFieldV( "exitSplashSoundVelocity", TypeRangedF32, Offset(exitSplashSoundVel, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum velocity when leaving the water for the exitingWater sound to "
          "@brief Minimum velocity when leaving the water for the exitingWater sound to "
          "play.\n\n"
          "play.\n\n"
          "@see exitingWater");
          "@see exitingWater");
@@ -1093,7 +1094,7 @@ void PlayerData::initPersistFields()
 
 
    addGroup( "Interaction: Ground Impact" );
    addGroup( "Interaction: Ground Impact" );
 
 
-      addField( "groundImpactMinSpeed", TypeF32, Offset(groundImpactMinSpeed, PlayerData),
+      addFieldV( "groundImpactMinSpeed", TypeRangedF32, Offset(groundImpactMinSpeed, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Minimum falling impact speed to apply damage and initiate the camera "
          "@brief Minimum falling impact speed to apply damage and initiate the camera "
          "shaking effect.\n\n" );
          "shaking effect.\n\n" );
       addField( "groundImpactShakeFreq", TypePoint3F, Offset(groundImpactShakeFreq, PlayerData),
       addField( "groundImpactShakeFreq", TypePoint3F, Offset(groundImpactShakeFreq, PlayerData),
@@ -1102,10 +1103,10 @@ void PlayerData::initPersistFields()
       addField( "groundImpactShakeAmp", TypePoint3F, Offset(groundImpactShakeAmp, PlayerData),
       addField( "groundImpactShakeAmp", TypePoint3F, Offset(groundImpactShakeAmp, PlayerData),
          "@brief Amplitude of the camera shake effect after falling.\n\n"
          "@brief Amplitude of the camera shake effect after falling.\n\n"
          "This is how much to shake the camera.\n");
          "This is how much to shake the camera.\n");
-      addField( "groundImpactShakeDuration", TypeF32, Offset(groundImpactShakeDuration, PlayerData),
+      addFieldV( "groundImpactShakeDuration", TypeRangedF32, Offset(groundImpactShakeDuration, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Duration (in seconds) of the camera shake effect after falling.\n\n"
          "@brief Duration (in seconds) of the camera shake effect after falling.\n\n"
          "This is how long to shake the camera.\n");
          "This is how long to shake the camera.\n");
-      addField( "groundImpactShakeFalloff", TypeF32, Offset(groundImpactShakeFalloff, PlayerData),
+      addFieldV( "groundImpactShakeFalloff", TypeRangedF32, Offset(groundImpactShakeFalloff, PlayerData), &CommonValidators::PositiveFloat,
          "@brief Falloff factor of the camera shake effect after falling.\n\n"
          "@brief Falloff factor of the camera shake effect after falling.\n\n"
          "This is how to fade the camera shake over the duration.\n");
          "This is how to fade the camera shake over the duration.\n");
 
 

+ 1 - 1
Engine/source/T3D/pointLight.cpp

@@ -102,7 +102,7 @@ void PointLight::initPersistFields()
    docsURL;
    docsURL;
    addGroup( "Light" );
    addGroup( "Light" );
 
 
-      addField( "radius", TypeF32, Offset( mRadius, PointLight ), "Controls the falloff of the light emission" );
+      addFieldV( "radius", TypeRangedF32, Offset( mRadius, PointLight ), &CommonValidators::PositiveFloat, "Controls the falloff of the light emission" );
 
 
    endGroup( "Light" );
    endGroup( "Light" );
 
 

+ 9 - 9
Engine/source/T3D/projectile.cpp

@@ -273,42 +273,42 @@ void ProjectileData::initPersistFields()
    endGroup("Light Emitter");   
    endGroup("Light Emitter");   
 
 
    addGroup("Physics");
    addGroup("Physics");
-      addProtectedField("lifetime", TypeS32, Offset(lifetime, ProjectileData), &setLifetime, &getScaledValue,
+      addProtectedFieldV("lifetime", TypeRangedS32, Offset(lifetime, ProjectileData), &setLifetime, &getScaledValue, &CommonValidators::NaturalNumber,
          "@brief Amount of time, in milliseconds, before the projectile is removed from the simulation.\n\n"
          "@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. "
          "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."
          "A projectile may exist up to a maximum of 131040ms (or 4095 ticks) as defined by Projectile::MaxLivingTicks in the source code."
          "@see fadeDelay");
          "@see fadeDelay");
-      addProtectedField("armingDelay", TypeS32, Offset(armingDelay, ProjectileData), &setArmingDelay, &getScaledValue,
+      addProtectedFieldV("armingDelay", TypeRangedS32, Offset(armingDelay, ProjectileData), &setArmingDelay, &getScaledValue, &CommonValidators::PositiveInt,
          "@brief Amount of time, in milliseconds, before the projectile will cause damage or explode on impact.\n\n"
          "@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"
          "This value must be equal to or less than the projectile's lifetime.\n\n"
          "@see lifetime");
          "@see lifetime");
-      addProtectedField("fadeDelay", TypeS32, Offset(fadeDelay, ProjectileData), &setFadeDelay, &getScaledValue,
+      addProtectedFieldV("fadeDelay", TypeRangedS32, Offset(fadeDelay, ProjectileData), &setFadeDelay, &getScaledValue, &CommonValidators::NaturalNumber,
          "@brief Amount of time, in milliseconds, before the projectile begins to fade out.\n\n"
          "@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.");
          "This value must be smaller than the projectile's lifetime to have an affect.");
       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),
+      addFieldV("velInheritFactor", TypeRangedF32, Offset(velInheritFactor, ProjectileData), &CommonValidators::F32Range,
          "@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. "
          "This value is never modified by the engine.\n"
          "This value is never modified by the engine.\n"
          "@note This value by default is not transmitted between the server and the client.");
          "@note This value by default is not transmitted between the server and the client.");
-      addField("muzzleVelocity", TypeF32, Offset(muzzleVelocity, ProjectileData),
+      addFieldV("muzzleVelocity", TypeRangedF32, Offset(muzzleVelocity, ProjectileData), &CommonValidators::PositiveFloat,
          "@brief Amount of velocity the projectile recieves from the \"muzzle\" of the gun.\n\n"
          "@brief Amount of velocity the projectile recieves from the \"muzzle\" of the gun.\n\n"
          "Used with velInheritFactor to determine the initial velocity of the projectile. "
          "Used with velInheritFactor to determine the initial velocity of the projectile. "
          "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("bounceElasticity", TypeF32, Offset(bounceElasticity, ProjectileData),
+      addFieldV("impactForce", TypeRangedF32, Offset(impactForce, ProjectileData), &CommonValidators::PositiveFloat);
+      addFieldV("bounceElasticity", TypeRangedF32, Offset(bounceElasticity, ProjectileData), &CommonValidators::PositiveFloat,
          "@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. "
          "A value of 1.0 will leave it's velocity unchanged while values greater than 1.0 will increase it.\n");
          "A value of 1.0 will leave it's velocity unchanged while values greater than 1.0 will increase it.\n");
-      addField("bounceFriction", TypeF32, Offset(bounceFriction, ProjectileData),
+      addFieldV("bounceFriction", TypeRangedF32, Offset(bounceFriction, ProjectileData), &CommonValidators::PositiveFloat,
          "@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),
+      addFieldV("gravityMod", TypeRangedF32, Offset(gravityMod, ProjectileData), &CommonValidators::F32Range,
          "@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"

+ 6 - 6
Engine/source/T3D/proximityMine.cpp

@@ -96,12 +96,12 @@ void ProximityMineData::initPersistFields()
    endGroup("Sounds");
    endGroup("Sounds");
 
 
    addGroup( "Arming" );
    addGroup( "Arming" );
-   addField( "armingDelay", TypeF32, Offset(armingDelay, ProximityMineData), 
+   addFieldV( "armingDelay", TypeRangedF32, Offset(armingDelay, ProximityMineData), &CommonValidators::PositiveFloat,
       "Delay (in seconds) from when the mine is placed to when it becomes active." );
       "Delay (in seconds) from when the mine is placed to when it becomes active." );
    endGroup( "Arming" );
    endGroup( "Arming" );
 
 
    addGroup( "Triggering" );
    addGroup( "Triggering" );
-   addField( "autoTriggerDelay", TypeF32, Offset(autoTriggerDelay, ProximityMineData),
+   addFieldV( "autoTriggerDelay", TypeRangedF32, Offset(autoTriggerDelay, ProximityMineData), &CommonValidators::PositiveFloat,
       "@brief Delay (in seconds) from arming until the mine automatically "
       "@brief Delay (in seconds) from arming until the mine automatically "
       "triggers and explodes, even if no object has entered the trigger area.\n\n"
       "triggers and explodes, even if no object has entered the trigger area.\n\n"
       "Set to 0 to disable." );
       "Set to 0 to disable." );
@@ -109,16 +109,16 @@ void ProximityMineData::initPersistFields()
       "@brief Controls whether the mine can be triggered by the object that owns it.\n\n"
       "@brief Controls whether the mine can be triggered by the object that owns it.\n\n"
       "For example, a player could deploy mines that are only dangerous to other "
       "For example, a player could deploy mines that are only dangerous to other "
       "players and not himself." );
       "players and not himself." );
-   addField( "triggerRadius", TypeF32, Offset(triggerRadius, ProximityMineData),
+   addFieldV( "triggerRadius", TypeRangedF32, Offset(triggerRadius, ProximityMineData), &CommonValidators::PositiveFloat,
       "Distance at which an activated mine will detect other objects and explode." );
       "Distance at which an activated mine will detect other objects and explode." );
-   addField( "triggerSpeed", TypeF32, Offset(triggerSpeed, ProximityMineData),
+   addFieldV( "triggerSpeed", TypeRangedF32, Offset(triggerSpeed, ProximityMineData), &CommonValidators::PositiveFloat,
       "Speed above which moving objects within the trigger radius will trigger the mine" );
       "Speed above which moving objects within the trigger radius will trigger the mine" );
-   addField( "triggerDelay", TypeF32, Offset(triggerDelay, ProximityMineData),
+   addFieldV( "triggerDelay", TypeRangedF32, Offset(triggerDelay, ProximityMineData), &CommonValidators::PositiveFloat,
       "Delay (in seconds) from when the mine is triggered until it explodes." );
       "Delay (in seconds) from when the mine is triggered until it explodes." );
    endGroup( "Triggering" );
    endGroup( "Triggering" );
 
 
    addGroup( "Explosion" );
    addGroup( "Explosion" );
-   addField( "explosionOffset", TypeF32, Offset(explosionOffset, ProximityMineData),
+   addFieldV( "explosionOffset", TypeRangedF32, Offset(explosionOffset, ProximityMineData), &CommonValidators::F32Range,
       "@brief Offset from the mine's origin where the explosion emanates from."
       "@brief Offset from the mine's origin where the explosion emanates from."
       "Sometimes a thrown mine may be slightly sunk into the ground.  This can be just "
       "Sometimes a thrown mine may be slightly sunk into the ground.  This can be just "
       "enough to cause the explosion to occur under the ground, especially on flat "
       "enough to cause the explosion to occur under the ground, especially on flat "

+ 24 - 24
Engine/source/T3D/rigidShape.cpp

@@ -517,12 +517,12 @@ void RigidShapeData::initPersistFields()
 
 
    addGroup( "Particle Effects" );
    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("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");
+      addFieldV("triggerDustHeight", TypeRangedF32,                      Offset(triggerDustHeight,  RigidShapeData), &CommonValidators::PositiveFloat, "Maximum height from the ground at which the object will generate dust.\n");
+      addFieldV("dustHeight", TypeRangedF32,                      Offset(dustHeight,         RigidShapeData), &CommonValidators::PositiveFloat, "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("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("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");  
+      addFieldV("splashFreqMod", TypeRangedF32,                Offset(splashFreqMod,   RigidShapeData), &CommonValidators::PositiveFloat, "The simulated frequency modulation of a splash generated by this object. Multiplied along with speed and time elapsed when determining splash emition rate.\n");
+      addFieldV("splashVelEpsilon", TypeRangedF32,              Offset(splashVelEpsilon, RigidShapeData), &CommonValidators::PositiveFloat, "The threshold speed at which we consider the object's movement to have stopped when updating splash effects.\n");
    endGroup( "Particle Effects" );
    endGroup( "Particle Effects" );
    
    
    addGroup( "Sounds" );
    addGroup( "Sounds" );
@@ -534,34 +534,34 @@ void RigidShapeData::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");
       addField("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("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("maxDrag", TypeF32, Offset(maxDrag, RigidShapeData), "Maximum 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("collisionTol", TypeF32, Offset(collisionTol, RigidShapeData), "Collision distance tolerance.");
-      addField("contactTol", TypeF32, Offset(contactTol, RigidShapeData), "Contact velocity tolerance.");
-      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.");
+      addFieldV("bodyRestitution", TypeRangedF32, Offset(body.restitution, RigidShapeData), &CommonValidators::PositiveFloat, "The percentage of kinetic energy kept by this object in a collision.");
+      addFieldV("bodyFriction", TypeRangedF32, Offset(body.friction, RigidShapeData), &CommonValidators::PositiveFloat, "How much friction this object has. Lower values will cause the object to appear to be more slippery.");
+      addFieldV("maxDrag", TypeRangedF32, Offset(maxDrag, RigidShapeData), &CommonValidators::PositiveFloat, "Maximum drag available to this object.");
+      addFieldV("minDrag", TypeRangedF32, Offset(minDrag, RigidShapeData), &CommonValidators::PositiveFloat, "Minimum drag available to this object.");
+      addFieldV("integration", TypeRangedS32, Offset(integration, RigidShapeData), &CommonValidators::NaturalNumber, "Number of physics steps to process per tick.");
+      addFieldV("collisionTol", TypeRangedF32, Offset(collisionTol, RigidShapeData), &CommonValidators::PositiveFloat, "Collision distance tolerance.");
+      addFieldV("contactTol", TypeRangedF32, Offset(contactTol, RigidShapeData), &CommonValidators::PositiveFloat, "Contact velocity tolerance.");
+      addFieldV("dragForce", TypeRangedF32, Offset(dragForce,            RigidShapeData), &CommonValidators::PositiveFloat, "Used to simulate the constant drag acting on the object");
+      addFieldV("vertFactor", TypeRangedF32, Offset(vertFactor,           RigidShapeData), &CommonValidators::PositiveFloat, "The scalar applied to the vertical portion of the velocity drag acting on a object.");
    endGroup("Physics");
    endGroup("Physics");
 
 
    addGroup("Collision");
    addGroup("Collision");
-      addField("minImpactSpeed", TypeF32, Offset(minImpactSpeed, RigidShapeData),
+      addFieldV("minImpactSpeed", TypeRangedF32, Offset(minImpactSpeed, RigidShapeData), &CommonValidators::PositiveFloat,
       "Minimum collision speed to classify collision as impact (triggers onImpact on server object)." );
       "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("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("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");
+      addFieldV("softImpactSpeed", TypeRangedF32, Offset(softImpactSpeed, RigidShapeData), &CommonValidators::PositiveFloat, "Minimum speed at which this object must be travelling for the soft impact sound to be played.");
+      addFieldV("hardImpactSpeed", TypeRangedF32, Offset(hardImpactSpeed, RigidShapeData), &CommonValidators::PositiveFloat, "Minimum speed at which the object must be travelling for the hard impact sound to be played.");
+      addFieldV("minRollSpeed", TypeRangedF32, Offset(minRollSpeed, RigidShapeData), &CommonValidators::PositiveFloat);
+      addFieldV("exitSplashSoundVelocity", TypeRangedF32,       Offset(exitSplashSoundVel, RigidShapeData), &CommonValidators::PositiveFloat, "The minimum velocity at which the exit splash sound will be played when emerging from water.\n");
+      addFieldV("softSplashSoundVelocity", TypeRangedF32,       Offset(softSplashSoundVel, RigidShapeData), &CommonValidators::PositiveFloat,"The minimum velocity at which the soft splash sound will be played when impacting water.\n");
+      addFieldV("mediumSplashSoundVelocity", TypeRangedF32,     Offset(medSplashSoundVel, RigidShapeData), &CommonValidators::PositiveFloat, "The minimum velocity at which the medium splash sound will be played when impacting water.\n");
+      addFieldV("hardSplashSoundVelocity", TypeRangedF32,       Offset(hardSplashSoundVel, RigidShapeData), &CommonValidators::PositiveFloat, "The minimum velocity at which the hard splash sound will be played when impacting water.\n");
    endGroup("Collision");   
    endGroup("Collision");   
    
    
    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("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");
+      addFieldV("cameraLag", TypeRangedF32,        Offset(cameraLag,      RigidShapeData), &CommonValidators::PositiveFloat, "Scalar amount by which the third person camera lags the object, relative to the object's linear velocity.\n");
+      addFieldV("cameraDecay", TypeRangedF32,        Offset(cameraDecay,  RigidShapeData), &CommonValidators::PositiveFloat, "Scalar rate at which the third person camera offset decays, per tick.\n");
+      addFieldV("cameraOffset", TypeRangedF32,        Offset(cameraOffset,   RigidShapeData), &CommonValidators::PositiveFloat, "The vertical offset of the object's camera.\n");
    endGroup( "Camera" );
    endGroup( "Camera" );
 }   
 }   
 
 

+ 9 - 9
Engine/source/T3D/sfx/sfxEmitter.cpp

@@ -327,19 +327,19 @@ void SFXEmitter::initPersistFields()
          "The SFXSource to which to assign the sound of this emitter as a child.\n"
          "The SFXSource to which to assign the sound of this emitter as a child.\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@see SFXDescription::sourceGroup" );
          "@see SFXDescription::sourceGroup" );
-      addField( "volume",              TypeF32,       Offset( mDescription.mVolume, SFXEmitter ),
+      addFieldV( "volume", TypeRangedF32,       Offset( mDescription.mVolume, SFXEmitter ), &CommonValidators::PositiveFloat,
          "Volume level to apply to the sound.\n"
          "Volume level to apply to the sound.\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@see SFXDescription::volume" );
          "@see SFXDescription::volume" );
-      addField( "pitch",               TypeF32,       Offset( mDescription.mPitch, SFXEmitter ),
+      addFieldV( "pitch", TypeRangedF32,       Offset( mDescription.mPitch, SFXEmitter ), &CommonValidators::PositiveFloat,
          "Pitch shift to apply to the sound.  Default is 1 = play at normal speed.\n"
          "Pitch shift to apply to the sound.  Default is 1 = play at normal speed.\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@see SFXDescription::pitch" );
          "@see SFXDescription::pitch" );
-      addField( "fadeInTime",          TypeF32,       Offset( mDescription.mFadeInTime, SFXEmitter ),
+      addFieldV( "fadeInTime", TypeRangedF32,       Offset( mDescription.mFadeInTime, SFXEmitter ), &CommonValidators::PositiveFloat,
          "Number of seconds to gradually fade in volume from zero when playback starts.\n"
          "Number of seconds to gradually fade in volume from zero when playback starts.\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@see SFXDescription::fadeInTime" );
          "@see SFXDescription::fadeInTime" );
-      addField( "fadeOutTime",         TypeF32,       Offset( mDescription.mFadeOutTime, SFXEmitter ),
+      addFieldV( "fadeOutTime", TypeRangedF32,       Offset( mDescription.mFadeOutTime, SFXEmitter ), &CommonValidators::PositiveFloat,
          "Number of seconds to gradually fade out volume down to zero when playback is stopped or paused.\n"
          "Number of seconds to gradually fade out volume down to zero when playback is stopped or paused.\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@see SFXDescription::fadeOutTime" );
          "@see SFXDescription::fadeOutTime" );
@@ -352,11 +352,11 @@ void SFXEmitter::initPersistFields()
          "Whether to play #fileName as a positional (3D) sound or not.\n"
          "Whether to play #fileName as a positional (3D) sound or not.\n"
          "If a #track is assigned, the value of this field is ignored.\n\n"
          "If a #track is assigned, the value of this field is ignored.\n\n"
          "@see SFXDescription::is3D" );
          "@see SFXDescription::is3D" );
-      addField( "referenceDistance",   TypeF32,       Offset( mDescription.mMinDistance, SFXEmitter ),
+      addFieldV( "referenceDistance", TypeRangedF32,       Offset( mDescription.mMinDistance, SFXEmitter ), &CommonValidators::PositiveFloat,
          "Distance at which to start volume attenuation of the 3D sound.\n"
          "Distance at which to start volume attenuation of the 3D sound.\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@see SFXDescription::referenceDistance" );
          "@see SFXDescription::referenceDistance" );
-      addField( "maxDistance",         TypeF32,       Offset( mDescription.mMaxDistance, SFXEmitter ),
+      addFieldV( "maxDistance", TypeRangedF32,       Offset( mDescription.mMaxDistance, SFXEmitter ), &CommonValidators::PositiveFloat,
          "Distance at which to stop volume attenuation of the 3D sound.\n"
          "Distance at which to stop volume attenuation of the 3D sound.\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@see SFXDescription::maxDistance" );
          "@see SFXDescription::maxDistance" );
@@ -364,15 +364,15 @@ void SFXEmitter::initPersistFields()
          "Bounds on random offset to apply to initial 3D sound position.\n"
          "Bounds on random offset to apply to initial 3D sound position.\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@see SFXDescription::scatterDistance" );
          "@see SFXDescription::scatterDistance" );
-      addField( "coneInsideAngle",     TypeS32,       Offset( mDescription.mConeInsideAngle, SFXEmitter ),
+      addFieldV( "coneInsideAngle",     TypeRangedS32,       Offset( mDescription.mConeInsideAngle, SFXEmitter ), &CommonValidators::S32_PosDegreeRange,
          "Angle of inner volume cone of 3D sound in degrees.\n"
          "Angle of inner volume cone of 3D sound in degrees.\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@see SFXDescription::coneInsideAngle" );
          "@see SFXDescription::coneInsideAngle" );
-      addField( "coneOutsideAngle",    TypeS32,       Offset( mDescription.mConeOutsideAngle, SFXEmitter ),
+      addFieldV( "coneOutsideAngle", TypeRangedS32,       Offset( mDescription.mConeOutsideAngle, SFXEmitter ), &CommonValidators::S32_PosDegreeRange,
          "Angle of outer volume cone of 3D sound in degrees\n"
          "Angle of outer volume cone of 3D sound in degrees\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@see SFXDescription::coneOutsideAngle" );
          "@see SFXDescription::coneOutsideAngle" );
-      addField( "coneOutsideVolume",   TypeF32,       Offset( mDescription.mConeOutsideVolume, SFXEmitter ),
+      addFieldV( "coneOutsideVolume", TypeRangedF32,       Offset( mDescription.mConeOutsideVolume, SFXEmitter ), &CommonValidators::NormalizedFloat,
          "Volume scale factor of outside of outer volume 3D sound cone.\n"
          "Volume scale factor of outside of outer volume 3D sound cone.\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@note This field is ignored if #useTrackDescriptionOnly is true.\n\n"
          "@see SFXDescription::coneOutsideVolume" );
          "@see SFXDescription::coneOutsideVolume" );

+ 15 - 14
Engine/source/T3D/shapeBase.cpp

@@ -557,26 +557,26 @@ void ShapeBaseData::initPersistFields()
    endGroup("Particle Effects");
    endGroup("Particle Effects");
 
 
    addGroup( "Physics" );   
    addGroup( "Physics" );   
-      addProtectedField("mass", TypeF32, Offset(mass, ShapeBaseData), &_setMass, &defaultProtectedGetFn, "Shape mass.\nUsed in simulation of moving objects.\n"  );
-      addField( "drag", TypeF32, Offset(drag, ShapeBaseData),
+      addProtectedFieldV("mass", TypeRangedF32, Offset(mass, ShapeBaseData), &_setMass, &defaultProtectedGetFn, &CommonValidators::PositiveFloat, "Shape mass.\nUsed in simulation of moving objects.\n"  );
+      addFieldV( "drag", TypeRangedF32, Offset(drag, ShapeBaseData), &CommonValidators::PositiveNonZeroFloat,
          "Drag factor.\nReduces velocity of moving objects." );
          "Drag factor.\nReduces velocity of moving objects." );
-      addField( "density", TypeF32, Offset(density, ShapeBaseData),
+      addFieldV( "density", TypeRangedF32, Offset(density, ShapeBaseData), &CommonValidators::PositiveNonZeroFloat,
          "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),
+      addFieldV( "maxEnergy", TypeRangedF32, Offset(maxEnergy, ShapeBaseData), &CommonValidators::PositiveFloat,
          "Maximum energy level for this object." );
          "Maximum energy level for this object." );
-      addField( "maxDamage", TypeF32, Offset(maxDamage, ShapeBaseData),
+      addFieldV( "maxDamage", TypeRangedF32, Offset(maxDamage, ShapeBaseData), &CommonValidators::PositiveFloat,
          "Maximum damage level for this object." );
          "Maximum damage level for this object." );
-      addField( "disabledLevel", TypeF32, Offset(disabledLevel, ShapeBaseData),
+      addFieldV( "disabledLevel", TypeRangedF32, Offset(disabledLevel, ShapeBaseData), &CommonValidators::PositiveFloat,
          "Damage level above which the object is disabled.\n"
          "Damage level above which the object is disabled.\n"
          "Currently unused." );
          "Currently unused." );
-      addField( "destroyedLevel", TypeF32, Offset(destroyedLevel, ShapeBaseData),
+      addFieldV( "destroyedLevel", TypeRangedF32, Offset(destroyedLevel, ShapeBaseData), &CommonValidators::PositiveFloat,
          "Damage level above which the object is destroyed.\n"
          "Damage level above which the object is destroyed.\n"
          "When the damage level increases above this value, the object damage "
          "When the damage level increases above this value, the object damage "
          "state is set to \"Destroyed\"." );
          "state is set to \"Destroyed\"." );
-      addField( "repairRate", TypeF32, Offset(repairRate, ShapeBaseData),
+      addFieldV( "repairRate", TypeRangedF32, Offset(repairRate, ShapeBaseData), &CommonValidators::PositiveFloat,
          "Rate at which damage is repaired in damage units/tick.\n"
          "Rate at which damage is repaired in damage units/tick.\n"
          "This value is subtracted from the damage level until it reaches 0." );
          "This value is subtracted from the damage level until it reaches 0." );
       addField( "inheritEnergyFromMount", TypeBool, Offset(inheritEnergyFromMount, ShapeBaseData),
       addField( "inheritEnergyFromMount", TypeBool, Offset(inheritEnergyFromMount, ShapeBaseData),
@@ -588,19 +588,19 @@ void ShapeBaseData::initPersistFields()
    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),
+      addFieldV( "cameraMaxDist", TypeRangedF32, Offset(cameraMaxDist, ShapeBaseData), &CommonValidators::PositiveFloat,
          "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"
          "@see observeThroughObject" );
          "@see observeThroughObject" );
-      addField( "cameraMinDist", TypeF32, Offset(cameraMinDist, ShapeBaseData),
+      addFieldV( "cameraMinDist", TypeRangedF32, Offset(cameraMinDist, ShapeBaseData), &CommonValidators::PositiveFloat,
          "The minimum distance from the camera to the object.\n"
          "The minimum 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"
          "@see observeThroughObject" );
          "@see observeThroughObject" );
-      addField( "cameraDefaultFov", TypeF32, Offset(cameraDefaultFov, ShapeBaseData),
+      addFieldV( "cameraDefaultFov", TypeRangedF32, Offset(cameraDefaultFov, ShapeBaseData), &CommonValidators::PosDegreeRange,
          "The default camera vertical FOV in degrees." );
          "The default camera vertical FOV in degrees." );
-      addField( "cameraMinFov", TypeF32, Offset(cameraMinFov, ShapeBaseData),
+      addFieldV( "cameraMinFov", TypeRangedF32, Offset(cameraMinFov, ShapeBaseData), &CommonValidators::PosDegreeRange,
          "The minimum camera vertical FOV allowed in degrees." );
          "The minimum camera vertical FOV allowed in degrees." );
-      addField( "cameraMaxFov", TypeF32, Offset(cameraMaxFov, ShapeBaseData),
+      addFieldV( "cameraMaxFov", TypeRangedF32, Offset(cameraMaxFov, ShapeBaseData), &CommonValidators::PosDegreeRange,
          "The maximum camera vertical FOV allowed in degrees." );
          "The maximum camera vertical FOV allowed in degrees." );
       addField( "cameraCanBank", TypeBool, Offset(cameraCanBank, ShapeBaseData),
       addField( "cameraCanBank", TypeBool, Offset(cameraCanBank, ShapeBaseData),
          "If the derrived class supports it, allow the camera to bank." );
          "If the derrived class supports it, allow the camera to bank." );
@@ -634,7 +634,7 @@ void ShapeBaseData::initPersistFields()
    onlyKeepClearSubstitutions("explosion");
    onlyKeepClearSubstitutions("explosion");
    onlyKeepClearSubstitutions("underwaterExplosion");
    onlyKeepClearSubstitutions("underwaterExplosion");
    Parent::initPersistFields();
    Parent::initPersistFields();
-
+   /*
    addGroup("BL Projected Shadows");
    addGroup("BL Projected Shadows");
       addField("shadowSize", TypeS32, Offset(shadowSize, ShapeBaseData),
       addField("shadowSize", TypeS32, Offset(shadowSize, ShapeBaseData),
          "Size of the projected shadow texture (must be power of 2).");
          "Size of the projected shadow texture (must be power of 2).");
@@ -647,6 +647,7 @@ void ShapeBaseData::initPersistFields()
          "Scalar applied to the radius of spot shadows (initial radius is based "
          "Scalar applied to the radius of spot shadows (initial radius is based "
          "on the shape bounds but can be adjusted with this field).");
          "on the shape bounds but can be adjusted with this field).");
    endGroup("BL Projected Shadows");
    endGroup("BL Projected Shadows");
+   */
 
 
 }
 }
 
 

+ 26 - 26
Engine/source/T3D/shapeImage.cpp

@@ -623,7 +623,7 @@ S32 ShapeBaseImageData::lookupState(const char* name)
    Con::errorf(ConsoleLogEntry::General,"ShapeBaseImageData:: Could not resolve state \"%s\" for image \"%s\"",name,getName());
    Con::errorf(ConsoleLogEntry::General,"ShapeBaseImageData:: Could not resolve state \"%s\" for image \"%s\"",name,getName());
    return 0;
    return 0;
 }
 }
-
+IRangeValidator mountRange(-1, SceneObject::NumMountPoints);
 void ShapeBaseImageData::initPersistFields()
 void ShapeBaseImageData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
@@ -636,10 +636,10 @@ void ShapeBaseImageData::initPersistFields()
       addField("shellExitDir", TypePoint3F, Offset(shellExitDir, ShapeBaseImageData),
       addField("shellExitDir", TypePoint3F, Offset(shellExitDir, ShapeBaseImageData),
          "@brief Vector direction to eject shell casings.\n\n"
          "@brief Vector direction to eject shell casings.\n\n"
          "@see casing");
          "@see casing");
-      addField("shellExitVariance", TypeF32, Offset(shellExitVariance, ShapeBaseImageData),
+      addFieldV("shellExitVariance", TypeRangedF32, Offset(shellExitVariance, ShapeBaseImageData), &CommonValidators::DegreeRange,
          "@brief Variance (in degrees) from the shellExitDir vector to eject casings.\n\n"
          "@brief Variance (in degrees) from the shellExitDir vector to eject casings.\n\n"
          "@see shellExitDir");
          "@see shellExitDir");
-      addField("shellVelocity", TypeF32, Offset(shellVelocity, ShapeBaseImageData),
+      addFieldV("shellVelocity", TypeRangedF32, Offset(shellVelocity, ShapeBaseImageData), &CommonValidators::PositiveFloat,
          "@brief Speed at which to eject casings.\n\n"
          "@brief Speed at which to eject casings.\n\n"
          "@see casing");
          "@see casing");
       addField("computeCRC", TypeBool, Offset(computeCRC, ShapeBaseImageData),
       addField("computeCRC", TypeBool, Offset(computeCRC, ShapeBaseImageData),
@@ -680,7 +680,7 @@ 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),
+      addFieldV( "scriptAnimTransitionTime", TypeRangedF32, Offset(scriptAnimTransitionTime, ShapeBaseImageData), &CommonValidators::PositiveFloat,
          "@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 "
          "will attempt to switch to the new animation sequence based on the given script prefix.  This is "
          "will attempt to switch to the new animation sequence based on the given script prefix.  This is "
@@ -697,12 +697,12 @@ void ShapeBaseImageData::initPersistFields()
    addField("usesEnergy", TypeBool, Offset(usesEnergy, ShapeBaseImageData),
    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"
       "@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()");
       "@see ShapeBase::setEnergyLevel()");
-   addField("minEnergy", TypeF32, Offset(minEnergy, ShapeBaseImageData),
+   addFieldV("minEnergy", TypeRangedF32, Offset(minEnergy, ShapeBaseImageData), &CommonValidators::PositiveFloat,
       "@brief Minimum Image energy for it to be operable.\n\n"
       "@brief Minimum Image energy for it to be operable.\n\n"
       "@see usesEnergy");
       "@see usesEnergy");
 
 
    addGroup("Mounting");
    addGroup("Mounting");
-   addField( "mountPoint", TypeS32, Offset(mountPoint, ShapeBaseImageData),
+   addFieldV( "mountPoint", TypeRangedS32, Offset(mountPoint, ShapeBaseImageData), &mountRange,
       "@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),
@@ -753,12 +753,12 @@ void ShapeBaseImageData::initPersistFields()
       addField( "camShakeAmp", TypePoint3F, Offset(camShakeAmp, ShapeBaseImageData),
       addField( "camShakeAmp", TypePoint3F, Offset(camShakeAmp, ShapeBaseImageData),
          "@brief Amplitude of the camera shaking effect.\n\n"
          "@brief Amplitude of the camera shaking effect.\n\n"
          "@see shakeCamera" );
          "@see shakeCamera" );
-      addField( "camShakeDuration", TypeF32, Offset(camShakeDuration, ShapeBaseImageData),
+      addFieldV( "camShakeDuration", TypeRangedF32, Offset(camShakeDuration, ShapeBaseImageData), &CommonValidators::PositiveFloat,
          "Duration (in seconds) to shake the camera." );
          "Duration (in seconds) to shake the camera." );
-      addField( "camShakeRadius", TypeF32, Offset(camShakeRadius, ShapeBaseImageData),
+      addFieldV( "camShakeRadius", TypeRangedF32, Offset(camShakeRadius, ShapeBaseImageData), &CommonValidators::PositiveFloat,
          "Radial distance that a camera's position must be within relative to the "
          "Radial distance that a camera's position must be within relative to the "
          "center of the explosion to be shaken." );
          "center of the explosion to be shaken." );
-      addField( "camShakeFalloff", TypeF32, Offset(camShakeFalloff, ShapeBaseImageData),
+      addFieldV( "camShakeFalloff", TypeRangedF32, Offset(camShakeFalloff, ShapeBaseImageData), &CommonValidators::PositiveFloat,
          "Falloff value for the camera shake." );
          "Falloff value for the camera shake." );
    endGroup("Camera Shake");
    endGroup("Camera Shake");
 
 
@@ -769,7 +769,7 @@ void ShapeBaseImageData::initPersistFields()
    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( "mass", TypeF32, Offset(mass, ShapeBaseImageData),
+   addFieldV( "mass", TypeRangedF32, Offset(mass, ShapeBaseImageData), &CommonValidators::PositiveFloat,
       "@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( "accuFire", TypeBool, Offset(accuFire, ShapeBaseImageData),
    addField( "accuFire", TypeBool, Offset(accuFire, ShapeBaseImageData),
@@ -785,13 +785,13 @@ void ShapeBaseImageData::initPersistFields()
       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),
+      addFieldV( "lightDuration", TypeRangedS32, Offset(lightDuration, ShapeBaseImageData), &CommonValidators::PositiveInt,
          "@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),
+      addFieldV( "lightRadius", TypeRangedF32, Offset(lightRadius, ShapeBaseImageData), &CommonValidators::PositiveFloat,
          "@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),
+      addFieldV( "lightBrightness", TypeRangedF32, Offset(lightBrightness, ShapeBaseImageData), &CommonValidators::PositiveFloat,
          "@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");
@@ -868,7 +868,7 @@ void ShapeBaseImageData::initPersistFields()
          "Name of the state to transition to when the generic trigger 3 state "
          "Name of the state to transition to when the generic trigger 3 state "
          "changes to false." );
          "changes to false." );
 
 
-      addField( "stateTimeoutValue", TypeF32, Offset(stateTimeoutValue, ShapeBaseImageData), MaxStates,
+      addFieldV( "stateTimeoutValue", TypeRangedF32, Offset(stateTimeoutValue, ShapeBaseImageData), &CommonValidators::PositiveFloat, MaxStates,
          "Time in seconds to wait before transitioning to stateTransitionOnTimeout." );
          "Time in seconds to wait before transitioning to stateTransitionOnTimeout." );
       addField( "stateWaitForTimeout", TypeBool, Offset(stateWaitForTimeout, ShapeBaseImageData), MaxStates,
       addField( "stateWaitForTimeout", TypeBool, Offset(stateWaitForTimeout, ShapeBaseImageData), MaxStates,
          "If false, this state ignores stateTimeoutValue and transitions "
          "If false, this state ignores stateTimeoutValue and transitions "
@@ -884,7 +884,7 @@ void ShapeBaseImageData::initPersistFields()
          "client when it receives the 'reload' event." );
          "client when it receives the 'reload' event." );
       addField( "stateEjectShell", TypeBool, Offset(stateEjectShell, ShapeBaseImageData), MaxStates,
       addField( "stateEjectShell", TypeBool, Offset(stateEjectShell, ShapeBaseImageData), MaxStates,
          "If true, a shell casing will be ejected in this state." );
          "If true, a shell casing will be ejected in this state." );
-      addField( "stateEnergyDrain", TypeF32, Offset(stateEnergyDrain, ShapeBaseImageData), MaxStates,
+      addFieldV( "stateEnergyDrain", TypeRangedF32, Offset(stateEnergyDrain, ShapeBaseImageData), &CommonValidators::PositiveFloat, MaxStates,
          "@brief Amount of energy to subtract from the Image in this state.\n\n"
          "@brief Amount of energy to subtract from the Image in this state.\n\n"
          "Energy is drained at stateEnergyDrain units/tick as long as we are in "
          "Energy is drained at stateEnergyDrain units/tick as long as we are in "
          "this state.\n"
          "this state.\n"
@@ -943,7 +943,7 @@ void ShapeBaseImageData::initPersistFields()
          "Do we transition to the new state's sequence when we leave the state?" );
          "Do we transition to the new state's sequence when we leave the state?" );
       addField( "stateSequenceNeverTransition", TypeBool, Offset(stateSequenceNeverTransition, ShapeBaseImageData), MaxStates,
       addField( "stateSequenceNeverTransition", TypeBool, Offset(stateSequenceNeverTransition, ShapeBaseImageData), MaxStates,
          "Never allow a transition to this sequence.  Often used for a fire sequence." );
          "Never allow a transition to this sequence.  Often used for a fire sequence." );
-      addField( "stateSequenceTransitionTime", TypeF32, Offset(stateSequenceTransitionTime, ShapeBaseImageData), MaxStates,
+      addFieldV( "stateSequenceTransitionTime", TypeRangedF32, Offset(stateSequenceTransitionTime, ShapeBaseImageData), &CommonValidators::PositiveFloat, MaxStates,
          "The time to transition in or out of a sequence." );
          "The time to transition in or out of a sequence." );
 
 
       addField( "stateShapeSequence", TypeString, Offset(stateShapeSequence, ShapeBaseImageData), MaxStates,
       addField( "stateShapeSequence", TypeString, Offset(stateShapeSequence, ShapeBaseImageData), MaxStates,
@@ -963,7 +963,7 @@ void ShapeBaseImageData::initPersistFields()
          "@brief Emitter to generate particles in this state (from muzzle point or "
          "@brief Emitter to generate particles in this state (from muzzle point or "
          "specified node).\n\n"
          "specified node).\n\n"
          "@see stateEmitterNode" );
          "@see stateEmitterNode" );
-      addField( "stateEmitterTime", TypeF32, Offset(stateEmitterTime, ShapeBaseImageData), MaxStates,
+      addFieldV( "stateEmitterTime", TypeRangedF32, Offset(stateEmitterTime, ShapeBaseImageData), &CommonValidators::PositiveFloat, MaxStates,
          "How long (in seconds) to emit particles on entry to this state." );
          "How long (in seconds) to emit particles on entry to this state." );
       addField( "stateEmitterNode", TypeString, Offset(stateEmitterNode, ShapeBaseImageData), MaxStates,
       addField( "stateEmitterNode", TypeString, Offset(stateEmitterNode, ShapeBaseImageData), MaxStates,
          "@brief Name of the node to emit particles from.\n\n"
          "@brief Name of the node to emit particles from.\n\n"
@@ -977,7 +977,7 @@ void ShapeBaseImageData::initPersistFields()
    endArray( "States" );
    endArray( "States" );
 
 
    addGroup("Sounds");
    addGroup("Sounds");
-      addField( "maxConcurrentSounds", TypeS32, Offset(maxConcurrentSounds, ShapeBaseImageData),
+      addFieldV( "maxConcurrentSounds", TypeRangedS32, Offset(maxConcurrentSounds, ShapeBaseImageData), &CommonValidators::PositiveInt,
          "@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");
    endGroup("Sounds");
@@ -1047,10 +1047,10 @@ void ShapeBaseImageData::packData(BitStream* stream)
    {
    {
       stream->write(lightRadius);
       stream->write(lightRadius);
       stream->write(lightDuration);
       stream->write(lightDuration);
-      stream->writeFloat(lightColor.red, 7);
-      stream->writeFloat(lightColor.green, 7);
-      stream->writeFloat(lightColor.blue, 7);
-      stream->writeFloat(lightColor.alpha, 7);
+      stream->writeFloat(lightColor.red, 8);
+      stream->writeFloat(lightColor.green, 8);
+      stream->writeFloat(lightColor.blue, 8);
+      stream->writeFloat(lightColor.alpha, 8);
       stream->write(lightBrightness);
       stream->write(lightBrightness);
    }
    }
 
 
@@ -1232,10 +1232,10 @@ void ShapeBaseImageData::unpackData(BitStream* stream)
    {
    {
       stream->read(&lightRadius);
       stream->read(&lightRadius);
       stream->read(&lightDuration);
       stream->read(&lightDuration);
-      lightColor.red = stream->readFloat(7);
-      lightColor.green = stream->readFloat(7);
-      lightColor.blue = stream->readFloat(7);
-      lightColor.alpha = stream->readFloat(7);
+      lightColor.red = stream->readFloat(8);
+      lightColor.green = stream->readFloat(8);
+      lightColor.blue = stream->readFloat(8);
+      lightColor.alpha = stream->readFloat(8);
       stream->read( &lightBrightness );
       stream->read( &lightBrightness );
    }
    }
 
 

+ 3 - 3
Engine/source/T3D/spotLight.cpp

@@ -98,9 +98,9 @@ void SpotLight::initPersistFields()
    docsURL;
    docsURL;
    addGroup( "Light" );
    addGroup( "Light" );
       
       
-      addField( "range", TypeF32, Offset( mRange, SpotLight ) );
-      addField( "innerAngle", TypeF32, Offset( mInnerConeAngle, SpotLight ) );
-      addField( "outerAngle", TypeF32, Offset( mOuterConeAngle, SpotLight ) );
+      addFieldV( "range", TypeRangedF32, Offset( mRange, SpotLight ), &CommonValidators::PositiveFloat);
+      addFieldV( "innerAngle", TypeRangedF32, Offset( mInnerConeAngle, SpotLight ), &CommonValidators::DegreeRangeQuarter);
+      addFieldV( "outerAngle", TypeRangedF32, Offset( mOuterConeAngle, SpotLight ), &CommonValidators::DegreeRangeQuarter);
 
 
    endGroup( "Light" );
    endGroup( "Light" );
 
 

+ 6 - 6
Engine/source/T3D/tsStatic.cpp

@@ -219,9 +219,9 @@ void TSStatic::initPersistFields()
    addGroup("Animation");
    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,
+   addFieldV("AnimOffset", TypeRangedF32, Offset(mAnimOffset, TSStatic), &percentValidator,
       "Percent Animation Offset.");
       "Percent Animation Offset.");
-   addFieldV("AnimSpeed", TypeF32, Offset(mAnimSpeed, TSStatic), &speedValidator,
+   addFieldV("AnimSpeed", TypeRangedF32, Offset(mAnimSpeed, TSStatic), &speedValidator,
       "Percent Animation Speed.");
       "Percent Animation Speed.");
    endGroup("Animation");
    endGroup("Animation");
 
 
@@ -253,16 +253,16 @@ void TSStatic::initPersistFields()
 
 
    addGroup("AlphaFade");
    addGroup("AlphaFade");
    addField("alphaFadeEnable", TypeBool, Offset(mUseAlphaFade, TSStatic), "Turn on/off Alpha Fade");
    addField("alphaFadeEnable", TypeBool, Offset(mUseAlphaFade, TSStatic), "Turn on/off Alpha Fade");
-   addField("alphaFadeStart", TypeF32, Offset(mAlphaFadeStart, TSStatic), "Distance of start Alpha Fade");
-   addField("alphaFadeEnd", TypeF32, Offset(mAlphaFadeEnd, TSStatic), "Distance of end Alpha Fade");
+   addFieldV("alphaFadeStart", TypeRangedF32, Offset(mAlphaFadeStart, TSStatic), &CommonValidators::PositiveFloat, "Distance of start Alpha Fade");
+   addFieldV("alphaFadeEnd", TypeRangedF32, Offset(mAlphaFadeEnd, TSStatic), &CommonValidators::PositiveFloat, "Distance of end Alpha Fade");
    addField("alphaFadeInverse", TypeBool, Offset(mInvertAlphaFade, TSStatic), "Invert Alpha Fade's Start & End Distance");
    addField("alphaFadeInverse", TypeBool, Offset(mInvertAlphaFade, TSStatic), "Invert Alpha Fade's Start & End Distance");
    endGroup("AlphaFade");
    endGroup("AlphaFade");
 
 
    addGroup("Debug");
    addGroup("Debug");
 
 
-   addField("renderNormals", TypeF32, Offset(mRenderNormalScalar, TSStatic),
+   addFieldV("renderNormals", TypeRangedF32, Offset(mRenderNormalScalar, TSStatic), &CommonValidators::PositiveFloat,
       "Debug rendering mode shows the normals for each point in the TSStatic's mesh.");
       "Debug rendering mode shows the normals for each point in the TSStatic's mesh.");
-   addField("forceDetail", TypeS32, Offset(mForceDetail, TSStatic),
+   addFieldV("forceDetail", TypeRangedS32, Offset(mForceDetail, TSStatic), &CommonValidators::PositiveInt,
       "Forces rendering to a particular detail level.");
       "Forces rendering to a particular detail level.");
 
 
    endGroup("Debug");
    endGroup("Debug");

+ 9 - 9
Engine/source/T3D/turret/aiTurretShape.cpp

@@ -127,28 +127,28 @@ void AITurretShapeData::initPersistFields()
    docsURL;
    docsURL;
    Parent::initPersistFields();
    Parent::initPersistFields();
    addGroup("AI Steering");
    addGroup("AI Steering");
-      addField("maxScanHeading",       TypeF32,       Offset(maxScanHeading,        AITurretShapeData),
+      addFieldV("maxScanHeading",       TypeRangedF32,       Offset(maxScanHeading,        AITurretShapeData), &CommonValidators::PosDegreeRangeQuarter,
          "@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");
-      addField("maxScanPitch",         TypeF32,       Offset(maxScanPitch,          AITurretShapeData),
+      addFieldV("maxScanPitch", TypeRangedF32,       Offset(maxScanPitch,          AITurretShapeData), &CommonValidators::PosDegreeRangeQuarter,
          "@brief Maximum number of degrees to scan up and down.\n\n"
          "@brief Maximum number of degrees to scan up and down.\n\n"
          "@note Maximum scan pitch is 90 degrees.\n");
          "@note Maximum scan pitch is 90 degrees.\n");
-      addField("maxScanDistance",      TypeF32,       Offset(maxScanDistance,       AITurretShapeData),
+      addFieldV("maxScanDistance", TypeRangedF32,       Offset(maxScanDistance,       AITurretShapeData), &CommonValidators::PositiveFloat,
          "@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),
+      addFieldV("scanTickFrequency",          TypeRangedS32,       Offset(scanTickFrequency,       AITurretShapeData), &CommonValidators::NaturalNumber,
          "@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),
+      addFieldV("scanTickFrequencyVariance", TypeRangedS32,       Offset(scanTickFrequencyVariance,       AITurretShapeData), &CommonValidators::PositiveInt,
          "@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),
+      addFieldV("trackLostTargetTime", TypeRangedF32,       Offset(trackLostTargetTime,       AITurretShapeData), &CommonValidators::PositiveFloat,
          "@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),
+   addFieldV("maxWeaponRange", TypeRangedF32,       Offset(maxWeaponRange,       AITurretShapeData), &CommonValidators::PositiveFloat,
       "@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),
+   addFieldV("weaponLeadVelocity", TypeRangedF32,       Offset(weaponLeadVelocity,   AITurretShapeData), &CommonValidators::PositiveFloat,
       "@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");
    endGroup("AI Steering");
@@ -173,7 +173,7 @@ void AITurretShapeData::initPersistFields()
       addField( "stateTransitionOnTimeout", TypeString, Offset(stateTransitionTimeout, AITurretShapeData), MaxStates,
       addField( "stateTransitionOnTimeout", TypeString, Offset(stateTransitionTimeout, AITurretShapeData), MaxStates,
          "Name of the state to transition to when we have been in this state "
          "Name of the state to transition to when we have been in this state "
          "for stateTimeoutValue seconds." );
          "for stateTimeoutValue seconds." );
-      addField( "stateTimeoutValue", TypeF32, Offset(stateTimeoutValue, AITurretShapeData), MaxStates,
+      addFieldV( "stateTimeoutValue", TypeRangedF32, Offset(stateTimeoutValue, AITurretShapeData), &CommonValidators::PositiveFloat, MaxStates,
          "Time in seconds to wait before transitioning to stateTransitionOnTimeout." );
          "Time in seconds to wait before transitioning to stateTransitionOnTimeout." );
       addField( "stateWaitForTimeout", TypeBool, Offset(stateWaitForTimeout, AITurretShapeData), MaxStates,
       addField( "stateWaitForTimeout", TypeBool, Offset(stateWaitForTimeout, AITurretShapeData), MaxStates,
          "If false, this state ignores stateTimeoutValue and transitions "
          "If false, this state ignores stateTimeoutValue and transitions "

+ 6 - 6
Engine/source/T3D/turret/turretShape.cpp

@@ -138,17 +138,17 @@ void TurretShapeData::initPersistFields()
          "@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("maxHeading",        TypeF32,       Offset(maxHeading,         TurretShapeData),
+      addFieldV("maxHeading", TypeRangedF32,       Offset(maxHeading,         TurretShapeData), &CommonValidators::PosDegreeRangeQuarter,
          "@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");
-      addField("minPitch",          TypeF32,       Offset(minPitch,           TurretShapeData),
+      addFieldV("minPitch", TypeRangedF32,       Offset(minPitch,           TurretShapeData), &CommonValidators::PosDegreeRangeQuarter,
          "@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),
+      addFieldV("maxPitch", TypeRangedF32,       Offset(maxPitch,           TurretShapeData), &CommonValidators::PosDegreeRangeQuarter,
          "@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),
+      addFieldV("headingRate", TypeRangedF32,       Offset(headingRate,        TurretShapeData), &CommonValidators::DegreeRange,
          "@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),
+      addFieldV("pitchRate", TypeRangedF32,       Offset(pitchRate,          TurretShapeData), &CommonValidators::DegreeRange,
          "@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");
    endGroup("Steering");
@@ -167,7 +167,7 @@ void TurretShapeData::initPersistFields()
    endGroup("Weapon State");
    endGroup("Weapon State");
 
 
    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("cameraOffset",      TypeF32,       Offset(cameraOffset,       TurretShapeData),
+   addFieldV("cameraOffset",      TypeRangedF32,       Offset(cameraOffset,       TurretShapeData), &CommonValidators::F32Range,
       "Vertical (Z axis) height of the camera above the turret." );
       "Vertical (Z axis) height of the camera above the turret." );
    endGroup("Camera");
    endGroup("Camera");
 }
 }

+ 15 - 15
Engine/source/T3D/vehicles/flyingVehicle.cpp

@@ -179,52 +179,52 @@ void FlyingVehicleData::initPersistFields()
    Parent::initPersistFields();
    Parent::initPersistFields();
 
 
    addGroup("Physics");
    addGroup("Physics");
-   addField( "rollForce", TypeF32, Offset(rollForce, FlyingVehicleData),
+   addFieldV( "rollForce", TypeRangedF32, Offset(rollForce, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "@brief Damping torque against rolling maneuvers (rotation about the y-axis), "
       "@brief Damping torque against rolling maneuvers (rotation about the y-axis), "
       "proportional to linear velocity.\n\n"
       "proportional to linear velocity.\n\n"
       "Acts to adjust roll to a stable position over time as the vehicle moves." );
       "Acts to adjust roll to a stable position over time as the vehicle moves." );
-   addField( "rotationalDrag", TypeF32, Offset(rotationalDrag, FlyingVehicleData),
+   addFieldV( "rotationalDrag", TypeRangedF32, Offset(rotationalDrag, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "Rotational drag factor (slows vehicle rotation speed in all axes)." );
       "Rotational drag factor (slows vehicle rotation speed in all axes)." );
-   addField( "horizontalSurfaceForce", TypeF32, Offset(horizontalSurfaceForce, FlyingVehicleData),
+   addFieldV( "horizontalSurfaceForce", TypeRangedF32, Offset(horizontalSurfaceForce, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "@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),
+   addFieldV( "hoverHeight", TypeRangedF32, Offset(hoverHeight, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "The vehicle's height off the ground when at rest." );
       "The vehicle's height off the ground when at rest." );
-   addField( "createHoverHeight", TypeF32, Offset(createHoverHeight, FlyingVehicleData),
+   addFieldV( "createHoverHeight", TypeRangedF32, Offset(createHoverHeight, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "@brief The vehicle's height off the ground when useCreateHeight is active.\n\n"
       "@brief The vehicle's height off the ground when useCreateHeight is active.\n\n"
       "This can help avoid problems with spawning the vehicle." );
       "This can help avoid problems with spawning the vehicle." );
    endGroup("Physics");
    endGroup("Physics");
 
 
    addGroup("Steering");
    addGroup("Steering");
-   addField( "maneuveringForce", TypeF32, Offset(maneuveringForce, FlyingVehicleData),
+   addFieldV( "maneuveringForce", TypeRangedF32, Offset(maneuveringForce, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "@brief Maximum X and Y (horizontal plane) maneuvering force.\n\n"
       "@brief Maximum X and Y (horizontal plane) maneuvering force.\n\n"
       "The actual force applied depends on the current thrust." );
       "The actual force applied depends on the current thrust." );
-   addField( "verticalSurfaceForce", TypeF32, Offset(verticalSurfaceForce, FlyingVehicleData),
+   addFieldV( "verticalSurfaceForce", TypeRangedF32, Offset(verticalSurfaceForce, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "@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." );
-   addField( "vertThrustMultiple", TypeF32, Offset(vertThrustMultiple, FlyingVehicleData),
+   addFieldV( "vertThrustMultiple", TypeRangedF32, Offset(vertThrustMultiple, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "Multiplier applied to the jetForce (defined in VehicleData) when thrusting vertically." );
       "Multiplier applied to the jetForce (defined in VehicleData) when thrusting vertically." );
-   addField( "steeringForce", TypeF32, Offset(steeringForce, FlyingVehicleData),
+   addFieldV( "steeringForce", TypeRangedF32, Offset(steeringForce, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "@brief Maximum X and Z (sideways and vertical) steering force.\n\n"
       "@brief Maximum X and Z (sideways and vertical) steering force.\n\n"
       "The actual force applied depends on the current steering input." );
       "The actual force applied depends on the current steering input." );
-   addField( "steeringRollForce", TypeF32, Offset(steeringRollForce, FlyingVehicleData),
+   addFieldV( "steeringRollForce", TypeRangedF32, Offset(steeringRollForce, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "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)." );
    endGroup("Steering");
    endGroup("Steering");
 
 
    addGroup("AutoCorrection");
    addGroup("AutoCorrection");
-   addField( "maxAutoSpeed", TypeF32, Offset(maxAutoSpeed, FlyingVehicleData),
+   addFieldV( "maxAutoSpeed", TypeRangedF32, Offset(maxAutoSpeed, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "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." );
-   addField( "autoInputDamping", TypeF32, Offset(autoInputDamping, FlyingVehicleData),
+   addFieldV( "autoInputDamping", TypeRangedF32, Offset(autoInputDamping, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "@brief Scale factor applied to steering input if speed is less than "
       "@brief Scale factor applied to steering input if speed is less than "
       "maxAutoSpeed to.improve handling at very low speeds.\n\n"
       "maxAutoSpeed to.improve handling at very low speeds.\n\n"
       "Smaller values make steering less sensitive." );
       "Smaller values make steering less sensitive." );
-   addField( "autoLinearForce", TypeF32, Offset(autoLinearForce, FlyingVehicleData),
+   addFieldV( "autoLinearForce", TypeRangedF32, Offset(autoLinearForce, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "@brief Corrective force applied to slow the vehicle when moving at less than "
       "@brief Corrective force applied to slow the vehicle when moving at less than "
       "maxAutoSpeed.\n\n"
       "maxAutoSpeed.\n\n"
       "The force is inversely proportional to vehicle speed." );
       "The force is inversely proportional to vehicle speed." );
-   addField( "autoAngularForce", TypeF32, Offset(autoAngularForce, FlyingVehicleData),
+   addFieldV( "autoAngularForce", TypeRangedF32, Offset(autoAngularForce, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "@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." );
@@ -245,7 +245,7 @@ void FlyingVehicleData::initPersistFields()
       "and JetNozzle3." );
       "and JetNozzle3." );
    addField( "trailEmitter",TYPEID< ParticleEmitterData >(), Offset(jetEmitter[TrailEmitter], FlyingVehicleData),
    addField( "trailEmitter",TYPEID< ParticleEmitterData >(), Offset(jetEmitter[TrailEmitter], FlyingVehicleData),
       "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),
+   addFieldV( "minTrailSpeed", TypeRangedF32, Offset(minTrailSpeed, FlyingVehicleData), &CommonValidators::PositiveFloat,
       "Minimum speed at which to start generating contrail particles." );
       "Minimum speed at which to start generating contrail particles." );
    endGroup("Particle Effects");
    endGroup("Particle Effects");
 
 

+ 6 - 6
Engine/source/T3D/vehicles/guiSpeedometer.cpp

@@ -111,15 +111,15 @@ void GuiSpeedometerHud::initPersistFields()
    docsURL;
    docsURL;
    addGroup("Needle");
    addGroup("Needle");
 
 
-   addField("maxSpeed", TypeF32, Offset( mMaxSpeed, GuiSpeedometerHud ),
+   addFieldV("maxSpeed", TypeRangedF32, Offset( mMaxSpeed, GuiSpeedometerHud ), &CommonValidators::PositiveFloat,
       "Maximum Vehicle speed (in Torque units per second) to represent on the "
       "Maximum Vehicle speed (in Torque units per second) to represent on the "
       "speedo (Vehicle speeds greater than this are clamped to maxSpeed)." );
       "speedo (Vehicle speeds greater than this are clamped to maxSpeed)." );
 
 
-   addField("minAngle", TypeF32, Offset( mMinAngle, GuiSpeedometerHud ),
+   addFieldV("minAngle", TypeRangedF32, Offset( mMinAngle, GuiSpeedometerHud ), &CommonValidators::DegreeRange,
       "Angle (in radians) of the needle when the Vehicle speed is 0. An angle "
       "Angle (in radians) of the needle when the Vehicle speed is 0. An angle "
       "of 0 points right, 90 points up etc)." );
       "of 0 points right, 90 points up etc)." );
 
 
-   addField("maxAngle", TypeF32, Offset( mMaxAngle, GuiSpeedometerHud ),
+   addFieldV("maxAngle", TypeRangedF32, Offset( mMaxAngle, GuiSpeedometerHud ), &CommonValidators::DegreeRange,
       "Angle (in radians) of the needle when the Vehicle speed is >= maxSpeed. "
       "Angle (in radians) of the needle when the Vehicle speed is >= maxSpeed. "
       "An angle of 0 points right, 90 points up etc)." );
       "An angle of 0 points right, 90 points up etc)." );
 
 
@@ -130,13 +130,13 @@ void GuiSpeedometerHud::initPersistFields()
       "Center of the needle, offset from the GuiSpeedometerHud control top "
       "Center of the needle, offset from the GuiSpeedometerHud control top "
       "left corner" );
       "left corner" );
 
 
-   addField("length", TypeF32, Offset( mNeedleLength, GuiSpeedometerHud ),
+   addFieldV("length", TypeRangedF32, Offset( mNeedleLength, GuiSpeedometerHud ), &CommonValidators::PositiveFloat,
       "Length of the needle from center to end" );
       "Length of the needle from center to end" );
 
 
-   addField("width", TypeF32, Offset( mNeedleWidth, GuiSpeedometerHud ),
+   addFieldV("width", TypeRangedF32, Offset( mNeedleWidth, GuiSpeedometerHud ), &CommonValidators::PositiveFloat,
       "Width of the needle" );
       "Width of the needle" );
 
 
-   addField("tail", TypeF32, Offset( mTailLength, GuiSpeedometerHud ),
+   addFieldV("tail", TypeRangedF32, Offset( mTailLength, GuiSpeedometerHud ), &CommonValidators::PositiveFloat,
       "Length of the needle from center to tail" );
       "Length of the needle from center to tail" );
 
 
    endGroup("Needle");
    endGroup("Needle");

+ 19 - 19
Engine/source/T3D/vehicles/hoverVehicle.cpp

@@ -175,11 +175,11 @@ void HoverVehicleData::initPersistFields()
    docsURL;
    docsURL;
    Parent::initPersistFields();
    Parent::initPersistFields();
    addGroup("Physics");
    addGroup("Physics");
-      addField( "normalForce", TypeF32, Offset(normalForce, HoverVehicleData),
+      addFieldV( "normalForce", TypeRangedF32, Offset(normalForce, HoverVehicleData), &CommonValidators::PositiveFloat,
          "Force generated in the ground normal direction when the vehicle is not "
          "Force generated in the ground normal direction when the vehicle is not "
          "floating (within stabalizer length from the ground).\n\n"
          "floating (within stabalizer length from the ground).\n\n"
          "@see stabLenMin" );
          "@see stabLenMin" );
-      addField( "stabLenMin", TypeF32, Offset(stabLenMin, HoverVehicleData),
+      addFieldV( "stabLenMin", TypeRangedF32, Offset(stabLenMin, HoverVehicleData), &CommonValidators::PositiveFloat,
          "Length of the base stabalizer when travelling at minimum speed (0).\n"
          "Length of the base stabalizer when travelling at minimum speed (0).\n"
          "Each tick, the vehicle performs 2 raycasts (from the center back and "
          "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 "
          "center front of the vehicle) to check for contact with the ground. The "
@@ -188,10 +188,10 @@ void HoverVehicleData::initPersistFields()
          "spring and ground normal forces are not applied.\n\n"
          "spring and ground normal forces are not applied.\n\n"
          "<img src=\"images/hoverVehicle_forces.png\">\n"
          "<img src=\"images/hoverVehicle_forces.png\">\n"
          "@see stabSpringConstant" );
          "@see stabSpringConstant" );
-      addField( "stabLenMax", TypeF32, Offset(stabLenMax, HoverVehicleData),
+      addFieldV( "stabLenMax", TypeRangedF32, Offset(stabLenMax, HoverVehicleData), &CommonValidators::PositiveFloat,
          "Length of the base stabalizer when travelling at maximum speed "
          "Length of the base stabalizer when travelling at maximum speed "
          "(maxThrustSpeed).\n\n@see stabLenMin\n\n@see mainThrustForce" );
          "(maxThrustSpeed).\n\n@see stabLenMin\n\n@see mainThrustForce" );
-      addField("vertFactor", TypeF32, Offset(vertFactor, HoverVehicleData),
+      addFieldV("vertFactor", TypeRangedF32, Offset(vertFactor, HoverVehicleData), &CommonValidators::PositiveFloat,
          "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 "
@@ -199,49 +199,49 @@ void HoverVehicleData::initPersistFields()
          "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("stabSpringConstant", TypeF32, Offset(stabSpringConstant, HoverVehicleData),
+      addFieldV("stabSpringConstant", TypeRangedF32, Offset(stabSpringConstant, HoverVehicleData), &CommonValidators::PositiveFloat,
          "Value used to generate stabalizer spring force. The force generated "
          "Value used to generate stabalizer spring force. The force generated "
          "depends on stabilizer compression, that is how close the vehicle is "
          "depends on stabilizer compression, that is how close the vehicle is "
          "to the ground proportional to current stabalizer length.\n\n"
          "to the ground proportional to current stabalizer length.\n\n"
          "@see stabLenMin");
          "@see stabLenMin");
-      addField("stabDampingConstant", TypeF32, Offset(stabDampingConstant, HoverVehicleData),
+      addFieldV("stabDampingConstant", TypeRangedF32, Offset(stabDampingConstant, HoverVehicleData), &CommonValidators::PositiveFloat,
          "Damping spring force acting against changes in the stabalizer length.\n\n"
          "Damping spring force acting against changes in the stabalizer length.\n\n"
          "@see stabLenMin");
          "@see stabLenMin");
    endGroup("Physics");
    endGroup("Physics");
 
 
    addGroup("Steering");
    addGroup("Steering");
-      addField( "steeringForce", TypeF32, Offset(steeringForce, HoverVehicleData),
+      addFieldV( "steeringForce", TypeRangedF32, Offset(steeringForce, HoverVehicleData), &CommonValidators::PositiveFloat,
          "Yaw (rotation about the Z-axis) force applied when steering in the x-axis direction."
          "Yaw (rotation about the Z-axis) force applied when steering in the x-axis direction."
          "about the vehicle's Z-axis)" );
          "about the vehicle's Z-axis)" );
-      addField( "rollForce", TypeF32, Offset(rollForce, HoverVehicleData),
+      addFieldV( "rollForce", TypeRangedF32, Offset(rollForce, HoverVehicleData), &CommonValidators::PositiveFloat,
       "Roll (rotation about the Y-axis) force applied when steering in the x-axis direction." );
       "Roll (rotation about the Y-axis) force applied when steering in the x-axis direction." );
-      addField( "pitchForce", TypeF32, Offset(pitchForce, HoverVehicleData),
+      addFieldV( "pitchForce", TypeRangedF32, Offset(pitchForce, HoverVehicleData), &CommonValidators::PositiveFloat,
       "Pitch (rotation about the X-axis) force applied when steering in the y-axis direction." );
       "Pitch (rotation about the X-axis) force applied when steering in the y-axis direction." );
-      addField( "dragForce", TypeF32, Offset(dragForce, HoverVehicleData),
+      addFieldV( "dragForce", TypeRangedF32, Offset(dragForce, HoverVehicleData), &CommonValidators::PositiveFloat,
       "Drag force factor that acts opposite to the vehicle velocity.\nAlso "
       "Drag force factor that acts opposite to the vehicle velocity.\nAlso "
       "used to determnine the vehicle's maxThrustSpeed.\n@see mainThrustForce" );
       "used to determnine the vehicle's maxThrustSpeed.\n@see mainThrustForce" );
-      addField( "mainThrustForce", TypeF32, Offset(mainThrustForce, HoverVehicleData),
+      addFieldV( "mainThrustForce", TypeRangedF32, Offset(mainThrustForce, HoverVehicleData), &CommonValidators::PositiveFloat,
          "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"
          "@tsexample\n"
          "@tsexample\n"
          "maxThrustSpeed = (mainThrustForce + strafeThrustForce) / dragForce;\n"
          "maxThrustSpeed = (mainThrustForce + strafeThrustForce) / dragForce;\n"
          "@endtsexample\n" );
          "@endtsexample\n" );
-      addField( "reverseThrustForce", TypeF32, Offset(reverseThrustForce, HoverVehicleData),
+      addFieldV( "reverseThrustForce", TypeRangedF32, Offset(reverseThrustForce, HoverVehicleData), &CommonValidators::PositiveFloat,
          "Force generated by thrusting the vehicle backward." );
          "Force generated by thrusting the vehicle backward." );
-      addField( "strafeThrustForce", TypeF32, Offset(strafeThrustForce, HoverVehicleData),
+      addFieldV( "strafeThrustForce", TypeRangedF32, Offset(strafeThrustForce, HoverVehicleData), &CommonValidators::PositiveFloat,
          "Force generated by thrusting the vehicle to one side.\nAlso used to "
          "Force generated by thrusting the vehicle to one side.\nAlso used to "
          "determine the vehicle's maxThrustSpeed.\n@see mainThrustForce" );
          "determine the vehicle's maxThrustSpeed.\n@see mainThrustForce" );
-      addField( "turboFactor", TypeF32, Offset(turboFactor, HoverVehicleData),
+      addFieldV( "turboFactor", TypeRangedF32, Offset(turboFactor, HoverVehicleData), &CommonValidators::PositiveFloat,
          "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),
+      addFieldV( "floatingThrustFactor", TypeRangedF32, Offset(floatingThrustFactor, HoverVehicleData), &CommonValidators::PositiveFloat,
          "Scalar applied to the vehicle's thrust force when the vehicle is floating.\n"
          "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)." );
          "@note The floatingThrustFactor must be between 0.0 and 1.0 (inclusive)." );
    endGroup("Steering");
    endGroup("Steering");
 
 
    addGroup("AutoCorrection");
    addGroup("AutoCorrection");
-   addField( "gyroDrag", TypeF32, Offset(gyroDrag, HoverVehicleData),
+   addFieldV( "gyroDrag", TypeRangedF32, Offset(gyroDrag, HoverVehicleData), &CommonValidators::PositiveFloat,
       "Damping torque that acts against the vehicle's current angular momentum." );
       "Damping torque that acts against the vehicle's current angular momentum." );
-   addField( "restorativeForce", TypeF32, Offset(restorativeForce, HoverVehicleData),
+   addFieldV( "restorativeForce", TypeRangedF32, Offset(restorativeForce, HoverVehicleData), &CommonValidators::PositiveFloat,
       "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" );
@@ -258,12 +258,12 @@ void HoverVehicleData::initPersistFields()
       "\"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 "
       "origin of the vehicle model." );
       "origin of the vehicle model." );
-   addField( "triggerTrailHeight", TypeF32, Offset(triggerTrailHeight, HoverVehicleData),
+   addFieldV( "triggerTrailHeight", TypeRangedF32, Offset(triggerTrailHeight, HoverVehicleData), &CommonValidators::PositiveFloat,
       "Maximum height above surface to emit dust trail particles.\nIf the vehicle "
       "Maximum height above surface to emit dust trail particles.\nIf the vehicle "
       "is less than triggerTrailHeight above a static surface with a material that "
       "is less than triggerTrailHeight above a static surface with a material that "
       "has 'showDust' set to true, the vehicle will emit particles from the "
       "has 'showDust' set to true, the vehicle will emit particles from the "
       "dustTrailEmitter." );
       "dustTrailEmitter." );
-   addField( "dustTrailFreqMod", TypeF32, Offset(dustTrailFreqMod, HoverVehicleData),
+   addFieldV( "dustTrailFreqMod", TypeRangedF32, Offset(dustTrailFreqMod, HoverVehicleData), &CommonValidators::PositiveFloat,
       "Number of dust trail particles to generate based on vehicle speed.\nThe "
       "Number of dust trail particles to generate based on vehicle speed.\nThe "
       "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 "

+ 10 - 10
Engine/source/T3D/vehicles/vehicle.cpp

@@ -297,12 +297,12 @@ void VehicleData::initPersistFields()
       "damageEmitterOffset[1] = \"-0.5 3 1\";\n"
       "damageEmitterOffset[1] = \"-0.5 3 1\";\n"
       "numDmgEmitterAreas = 2;\n"
       "numDmgEmitterAreas = 2;\n"
       "@endtsexample\n" );
       "@endtsexample\n" );
-   addField( "damageLevelTolerance", TypeF32, Offset(damageLevelTolerance, VehicleData), VC_NUM_DAMAGE_LEVELS,
+   addFieldV( "damageLevelTolerance", TypeRangedF32, Offset(damageLevelTolerance, VehicleData), &CommonValidators::PositiveFloat, VC_NUM_DAMAGE_LEVELS,
       "@brief Damage levels (as a percentage of maxDamage) above which to begin "
       "@brief Damage levels (as a percentage of maxDamage) above which to begin "
       "emitting particles from the associated damageEmitter.\n\n"
       "emitting particles from the associated damageEmitter.\n\n"
       "Levels should be in order of increasing damage.\n\n"
       "Levels should be in order of increasing damage.\n\n"
       "@see damageEmitterOffset" );
       "@see damageEmitterOffset" );
-   addField( "numDmgEmitterAreas", TypeF32, Offset(numDmgEmitterAreas, VehicleData),
+   addFieldV( "numDmgEmitterAreas", TypeRangedF32, Offset(numDmgEmitterAreas, VehicleData), &CommonValidators::PositiveFloat,
       "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" );
    endGroup("Particle Effects");
    endGroup("Particle Effects");
@@ -313,33 +313,33 @@ void VehicleData::initPersistFields()
    endGroup("Physics");
    endGroup("Physics");
 
 
    addGroup("Collision");
    addGroup("Collision");
-   addField( "collDamageThresholdVel", TypeF32, Offset(collDamageThresholdVel, VehicleData),
+   addFieldV( "collDamageThresholdVel", TypeRangedF32, Offset(collDamageThresholdVel, VehicleData), &CommonValidators::PositiveFloat,
       "Minimum collision velocity to cause damage to this vehicle.\nCurrently unused." );
       "Minimum collision velocity to cause damage to this vehicle.\nCurrently unused." );
-   addField( "collDamageMultiplier", TypeF32, Offset(collDamageMultiplier, VehicleData),
+   addFieldV( "collDamageMultiplier", TypeRangedF32, Offset(collDamageMultiplier, VehicleData), &CommonValidators::PositiveFloat,
       "@brief Damage to this vehicle after a collision (multiplied by collision "
       "@brief Damage to this vehicle after a collision (multiplied by collision "
       "velocity).\n\nCurrently unused." );
       "velocity).\n\nCurrently unused." );
    endGroup("Collision");
    endGroup("Collision");
 
 
    addGroup("Steering");
    addGroup("Steering");
-      addField( "jetForce", TypeF32, Offset(jetForce, VehicleData),
+      addFieldV( "jetForce", TypeRangedF32, Offset(jetForce, VehicleData), &CommonValidators::PositiveFloat,
          "@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 "
          "FlyingVehicles, the force is applied in the thrust direction." );
          "FlyingVehicles, the force is applied in the thrust direction." );
-      addField( "jetEnergyDrain", TypeF32, Offset(jetEnergyDrain, VehicleData),
+      addFieldV( "jetEnergyDrain", TypeRangedF32, Offset(jetEnergyDrain, VehicleData), &CommonValidators::PositiveFloat,
       "@brief Energy amount to drain for each tick the vehicle is jetting.\n\n"
       "@brief Energy amount to drain for each tick the vehicle is jetting.\n\n"
          "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),
+      addFieldV( "minJetEnergy", TypeRangedF32, Offset(minJetEnergy, VehicleData), &CommonValidators::PositiveFloat,
       "Minimum vehicle energy level to begin jetting." );
       "Minimum vehicle energy level to begin jetting." );
-      addField( "maxSteeringAngle", TypeF32, Offset(maxSteeringAngle, VehicleData),
+      addFieldV( "maxSteeringAngle", TypeRangedF32, Offset(maxSteeringAngle, VehicleData), &CommonValidators::PositiveFloat,
          "Maximum yaw (horizontal) and pitch (vertical) steering angle in radians." );
          "Maximum yaw (horizontal) and pitch (vertical) steering angle in radians." );
    endGroup("Steering");
    endGroup("Steering");
 
 
    addGroup("AutoCorrection");
    addGroup("AutoCorrection");
    addField( "powerSteering", TypeBool, Offset(powerSteering, VehicleData),
    addField( "powerSteering", TypeBool, Offset(powerSteering, VehicleData),
       "If true, steering does not auto-centre while the vehicle is being steered by its driver." );
       "If true, steering does not auto-centre while the vehicle is being steered by its driver." );
-   addField( "steeringReturn", TypeF32, Offset(steeringReturn, VehicleData),
+   addFieldV( "steeringReturn", TypeRangedF32, Offset(steeringReturn, VehicleData), &CommonValidators::PositiveFloat,
       "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),
+   addFieldV( "steeringReturnSpeedScale", TypeRangedF32, Offset(steeringReturnSpeedScale, VehicleData), &CommonValidators::PositiveFloat,
       "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." );
    endGroup("AutoCorrection");
    endGroup("AutoCorrection");
 }
 }

+ 19 - 19
Engine/source/T3D/vehicles/wheeledVehicle.cpp

@@ -115,20 +115,20 @@ void WheeledVehicleTire::initPersistFields()
    docsURL;
    docsURL;
    INITPERSISTFIELD_SHAPEASSET(Shape, WheeledVehicleTire, "The shape to use for the wheel.");
    INITPERSISTFIELD_SHAPEASSET(Shape, WheeledVehicleTire, "The shape to use for the wheel.");
 
 
-   addField( "mass", TypeF32, Offset(mass, WheeledVehicleTire),
+   addFieldV( "mass", TypeRangedF32, Offset(mass, WheeledVehicleTire), &CommonValidators::PositiveFloat,
       "The mass of the wheel.\nCurrently unused." );
       "The mass of the wheel.\nCurrently unused." );
-   addField( "radius", TypeF32, Offset(radius, WheeledVehicleTire),
+   addFieldV( "radius", TypeRangedF32, Offset(radius, WheeledVehicleTire), &CommonValidators::PositiveFloat,
       "@brief The radius of the wheel.\n\n"
       "@brief The radius of the wheel.\n\n"
       "The radius is determined from the bounding box of the shape provided "
       "The radius is determined from the bounding box of the shape provided "
       "in the shapefile field, and does not need to be specified in script. "
       "in the shapefile field, and does not need to be specified in script. "
       "The tire should be built with its hub axis along the object's Y-axis." );
       "The tire should be built with its hub axis along the object's Y-axis." );
-   addField( "staticFriction", TypeF32, Offset(staticFriction, WheeledVehicleTire),
+   addFieldV( "staticFriction", TypeRangedF32, Offset(staticFriction, WheeledVehicleTire), &CommonValidators::PositiveFloat,
       "Tire friction when the wheel is not slipping (has traction)." );
       "Tire friction when the wheel is not slipping (has traction)." );
-   addField( "kineticFriction", TypeF32, Offset(kineticFriction, WheeledVehicleTire),
+   addFieldV( "kineticFriction", TypeRangedF32, Offset(kineticFriction, WheeledVehicleTire), &CommonValidators::PositiveFloat,
       "Tire friction when the wheel is slipping (no traction)." );
       "Tire friction when the wheel is slipping (no traction)." );
-   addField( "restitution", TypeF32, Offset(restitution, WheeledVehicleTire),
+   addFieldV( "restitution", TypeRangedF32, Offset(restitution, WheeledVehicleTire), &CommonValidators::PositiveFloat,
       "Tire restitution.\nCurrently unused." );
       "Tire restitution.\nCurrently unused." );
-   addField( "lateralForce", TypeF32, Offset(lateralForce, WheeledVehicleTire),
+   addFieldV( "lateralForce", TypeRangedF32, Offset(lateralForce, WheeledVehicleTire, &CommonValidators::PositiveFloat), &CommonValidators::PositiveFloat,
       "@brief Tire force perpendicular to the direction of movement.\n\n"
       "@brief Tire force perpendicular to the direction of movement.\n\n"
       "Lateral force can in simple terms be considered left/right steering "
       "Lateral force can in simple terms be considered left/right steering "
       "force. WheeledVehicles are acted upon by forces generated by their tires "
       "force. WheeledVehicles are acted upon by forces generated by their tires "
@@ -146,14 +146,14 @@ void WheeledVehicleTire::initPersistFields()
       "For this field, the larger the value supplied for the lateralForce, the "
       "For this field, the larger the value supplied for the lateralForce, the "
       "larger the effect steering maneuvers can have. In Torque tire forces are "
       "larger the effect steering maneuvers can have. In Torque tire forces are "
       "applied at a vehicle's wheel hubs." );
       "applied at a vehicle's wheel hubs." );
-   addField( "lateralDamping", TypeF32, Offset(lateralDamping, WheeledVehicleTire),
+   addFieldV( "lateralDamping", TypeRangedF32, Offset(lateralDamping, WheeledVehicleTire), &CommonValidators::PositiveFloat,
       "Damping force applied against lateral forces generated by the tire.\n\n"
       "Damping force applied against lateral forces generated by the tire.\n\n"
       "@see lateralForce" );
       "@see lateralForce" );
-   addField( "lateralRelaxation", TypeF32, Offset(lateralRelaxation, WheeledVehicleTire),
+   addFieldV( "lateralRelaxation", TypeRangedF32, Offset(lateralRelaxation, WheeledVehicleTire), &CommonValidators::PositiveFloat,
       "@brief Relaxing force applied against lateral forces generated by the tire.\n\n"
       "@brief Relaxing force applied against lateral forces generated by the tire.\n\n"
       "The lateralRelaxation force measures how strongly the tire effectively "
       "The lateralRelaxation force measures how strongly the tire effectively "
       "un-deforms.\n\n@see lateralForce" );
       "un-deforms.\n\n@see lateralForce" );
-   addField( "longitudinalForce", TypeF32, Offset(longitudinalForce, WheeledVehicleTire),
+   addFieldV( "longitudinalForce", TypeRangedF32, Offset(longitudinalForce, WheeledVehicleTire), &CommonValidators::PositiveFloat,
       "@brief Tire force in the direction of movement.\n\n"
       "@brief Tire force in the direction of movement.\n\n"
       "Longitudinal force can in simple terms be considered forward/backward "
       "Longitudinal force can in simple terms be considered forward/backward "
       "movement force. WheeledVehicles are acted upon by forces generated by "
       "movement force. WheeledVehicles are acted upon by forces generated by "
@@ -162,10 +162,10 @@ void WheeledVehicleTire::initPersistFields()
       "For this field, the larger the value, the larger the effect "
       "For this field, the larger the value, the larger the effect "
       "acceleration/deceleration inputs have.\n\n"
       "acceleration/deceleration inputs have.\n\n"
       "@see lateralForce" );
       "@see lateralForce" );
-   addField( "longitudinalDamping", TypeF32, Offset(longitudinalDamping, WheeledVehicleTire),
+   addFieldV( "longitudinalDamping", TypeRangedF32, Offset(longitudinalDamping, WheeledVehicleTire), &CommonValidators::PositiveFloat,
       "Damping force applied against longitudinal forces generated by the tire.\n\n"
       "Damping force applied against longitudinal forces generated by the tire.\n\n"
       "@see longitudinalForce" );
       "@see longitudinalForce" );
-   addField( "longitudinalRelaxation", TypeF32, Offset(longitudinalRelaxation, WheeledVehicleTire),
+   addFieldV( "longitudinalRelaxation", TypeRangedF32, Offset(longitudinalRelaxation, WheeledVehicleTire), &CommonValidators::PositiveFloat,
       "@brief Relaxing force applied against longitudinal forces generated by the tire.\n\n"
       "@brief Relaxing force applied against longitudinal forces generated by the tire.\n\n"
       "The longitudinalRelaxation force measures how strongly the tire effectively "
       "The longitudinalRelaxation force measures how strongly the tire effectively "
       "un-deforms.\n\n"
       "un-deforms.\n\n"
@@ -235,20 +235,20 @@ WheeledVehicleSpring::WheeledVehicleSpring()
 void WheeledVehicleSpring::initPersistFields()
 void WheeledVehicleSpring::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-   addField( "length", TypeF32, Offset(length, WheeledVehicleSpring),
+   addFieldV( "length", TypeRangedF32, Offset(length, WheeledVehicleSpring), &CommonValidators::PositiveFloat,
       "@brief Maximum spring length. ie. how far the wheel can extend from the "
       "@brief Maximum spring length. ie. how far the wheel can extend from the "
       "root hub position.\n\n"
       "root hub position.\n\n"
       "This should be set to the vertical (Z) distance the hub travels in the "
       "This should be set to the vertical (Z) distance the hub travels in the "
       "associated spring animation." );
       "associated spring animation." );
-   addField( "force", TypeF32, Offset(force, WheeledVehicleSpring),
+   addFieldV( "force", TypeRangedF32, Offset(force, WheeledVehicleSpring), &CommonValidators::PositiveFloat,
       "@brief Maximum spring force (when compressed to minimum length, 0).\n\n"
       "@brief Maximum spring force (when compressed to minimum length, 0).\n\n"
       "Increasing this will make the vehicle suspension ride higher (for a given "
       "Increasing this will make the vehicle suspension ride higher (for a given "
       "vehicle mass), and also make the vehicle more bouncy when landing jumps." );
       "vehicle mass), and also make the vehicle more bouncy when landing jumps." );
-   addField( "damping", TypeF32, Offset(damping, WheeledVehicleSpring),
+   addFieldV( "damping", TypeRangedF32, Offset(damping, WheeledVehicleSpring), &CommonValidators::PositiveFloat,
       "@brief Force applied to slow changes to the extension of this spring.\n\n"
       "@brief Force applied to slow changes to the extension of this spring.\n\n"
       "Increasing this makes the suspension stiffer which can help stabilise "
       "Increasing this makes the suspension stiffer which can help stabilise "
       "bouncy vehicles." );
       "bouncy vehicles." );
-   addField( "antiSwayForce", TypeF32, Offset(antiSway, WheeledVehicleSpring),
+   addFieldV( "antiSwayForce", TypeRangedF32, Offset(antiSway, WheeledVehicleSpring), &CommonValidators::PositiveFloat,
       "@brief Force applied to equalize extension of the spring on the opposite "
       "@brief Force applied to equalize extension of the spring on the opposite "
       "wheel.\n\n"
       "wheel.\n\n"
       "This force helps to keep the suspension balanced when opposite wheels "
       "This force helps to keep the suspension balanced when opposite wheels "
@@ -465,17 +465,17 @@ void WheeledVehicleData::initPersistFields()
    endGroup("Sounds");
    endGroup("Sounds");
 
 
    addGroup("Steering");
    addGroup("Steering");
-   addField("maxWheelSpeed", TypeF32, Offset(maxWheelSpeed, WheeledVehicleData),
+   addFieldV("maxWheelSpeed", TypeRangedF32, Offset(maxWheelSpeed, WheeledVehicleData), &CommonValidators::PositiveFloat,
       "@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." );
-   addField("engineTorque", TypeF32, Offset(engineTorque, WheeledVehicleData),
+   addFieldV("engineTorque", TypeRangedF32, Offset(engineTorque, WheeledVehicleData), &CommonValidators::PositiveFloat,
       "@brief Torque available from the engine at 100% throttle.\n\n"
       "@brief Torque available from the engine at 100% throttle.\n\n"
       "This controls vehicle acceleration. ie. how fast it will reach maximum speed." );
       "This controls vehicle acceleration. ie. how fast it will reach maximum speed." );
-   addField("engineBrake", TypeF32, Offset(engineBrake, WheeledVehicleData),
+   addFieldV("engineBrake", TypeRangedF32, Offset(engineBrake, WheeledVehicleData), &CommonValidators::PositiveFloat,
       "@brief Braking torque applied by the engine when the throttle and brake "
       "@brief Braking torque applied by the engine when the throttle and brake "
       "are both 0.\n\n"
       "are both 0.\n\n"
       "This controls how quickly the vehicle will coast to a stop." );
       "This controls how quickly the vehicle will coast to a stop." );
-   addField("brakeTorque", TypeF32, Offset(brakeTorque, WheeledVehicleData),
+   addFieldV("brakeTorque", TypeRangedF32, Offset(brakeTorque, WheeledVehicleData), &CommonValidators::PositiveFloat,
       "@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." );
    addField("downforce", TypeF32, Offset(mDownForce, WheeledVehicleData),
    addField("downforce", TypeF32, Offset(mDownForce, WheeledVehicleData),

+ 5 - 5
Engine/source/afx/afxEffectGroup.cpp

@@ -143,20 +143,20 @@ void afxEffectGroupData::initPersistFields()
    docsURL;
    docsURL;
   addField("groupEnabled",   TypeBool,    myOffset(group_enabled),
   addField("groupEnabled",   TypeBool,    myOffset(group_enabled),
     "...");
     "...");
-  addField("count",          TypeS32,     myOffset(group_count),
+  addFieldV("count", TypeRangedS32,     myOffset(group_count), &CommonValidators::NaturalNumber,
     "...");
     "...");
   addField("indexOffset",    TypeS8,      myOffset(idx_offset),
   addField("indexOffset",    TypeS8,      myOffset(idx_offset),
     "...");
     "...");
   addField("assignIndices",  TypeBool,    myOffset(assign_idx),
   addField("assignIndices",  TypeBool,    myOffset(assign_idx),
     "...");
     "...");
 
 
-  addField("delay",          TypeF32,     myOffset(timing.delay),
+  addFieldV("delay",          TypeRangedF32,     myOffset(timing.delay), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("lifetime",       TypeF32,     myOffset(timing.lifetime),
+  addFieldV("lifetime", TypeRangedF32,     myOffset(timing.lifetime), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("fadeInTime",     TypeF32,     myOffset(timing.fade_in_time),
+  addFieldV("fadeInTime", TypeRangedF32,     myOffset(timing.fade_in_time), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("fadeOutTime",    TypeF32,     myOffset(timing.fade_out_time),
+  addFieldV("fadeOutTime", TypeRangedF32,     myOffset(timing.fade_out_time), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   // effect lists
   // effect lists

+ 15 - 14
Engine/source/afx/afxEffectWrapper.cpp

@@ -35,6 +35,7 @@
 #include "afx/afxEffectWrapper.h"
 #include "afx/afxEffectWrapper.h"
 #include "afx/util/afxAnimCurve.h"
 #include "afx/util/afxAnimCurve.h"
 #include "afx/util/afxEase.h"
 #include "afx/util/afxEase.h"
+#include "console/typeValidators.h"
 
 
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 // afxEffectWrapperData
 // afxEffectWrapperData
@@ -237,33 +238,33 @@ void afxEffectWrapperData::initPersistFields()
   addField("ghostIsConstraintSrc",    TypeBool,     myOffset(use_ghost_as_cons_obj),
   addField("ghostIsConstraintSrc",    TypeBool,     myOffset(use_ghost_as_cons_obj),
     "...");
     "...");
 
 
-  addField("delay",             TypeF32,          myOffset(ewd_timing.delay),
+  addFieldV("delay", TypeRangedF32,          myOffset(ewd_timing.delay), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("lifetime",          TypeF32,          myOffset(ewd_timing.lifetime),
+  addFieldV("lifetime", TypeRangedF32,          myOffset(ewd_timing.lifetime), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("fadeInTime",        TypeF32,          myOffset(ewd_timing.fade_in_time),
+  addFieldV("fadeInTime", TypeRangedF32,          myOffset(ewd_timing.fade_in_time), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("residueLifetime",   TypeF32,          myOffset(ewd_timing.residue_lifetime),
+  addFieldV("residueLifetime", TypeRangedF32,          myOffset(ewd_timing.residue_lifetime), &CommonValidators::PositiveFloat,
     "...");
     "...");
   addField("fadeInEase",        TypePoint2F,      myOffset(ewd_timing.fadein_ease),
   addField("fadeInEase",        TypePoint2F,      myOffset(ewd_timing.fadein_ease),
     "...");
     "...");
   addField("fadeOutEase",       TypePoint2F,      myOffset(ewd_timing.fadeout_ease),
   addField("fadeOutEase",       TypePoint2F,      myOffset(ewd_timing.fadeout_ease),
     "...");
     "...");
-  addField("lifetimeBias",      TypeF32,          myOffset(ewd_timing.life_bias),
+  addFieldV("lifetimeBias", TypeRangedF32,          myOffset(ewd_timing.life_bias), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("fadeOutTime",       TypeF32,          myOffset(user_fade_out_time),
+  addFieldV("fadeOutTime", TypeRangedF32,          myOffset(user_fade_out_time), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
-  addField("rateFactor",        TypeF32,          myOffset(rate_factor),
+  addFieldV("rateFactor", TypeRangedF32,          myOffset(rate_factor), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("scaleFactor",       TypeF32,          myOffset(scale_factor),
+  addFieldV("scaleFactor", TypeRangedF32,          myOffset(scale_factor), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   addField("isLooping",         TypeBool,         myOffset(is_looping),
   addField("isLooping",         TypeBool,         myOffset(is_looping),
     "...");
     "...");
-  addField("loopCount",         TypeS32,          myOffset(n_loops),
+  addFieldV("loopCount",         TypeRangedS32,          myOffset(n_loops), &CommonValidators::PositiveInt,
     "...");
     "...");
-  addField("loopGapTime",       TypeF32,          myOffset(loop_gap_time),
+  addFieldV("loopGapTime", TypeRangedF32,          myOffset(loop_gap_time), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   addField("ignoreTimeFactor",    TypeBool,       myOffset(ignore_time_factor),
   addField("ignoreTimeFactor",    TypeBool,       myOffset(ignore_time_factor),
@@ -296,9 +297,9 @@ void afxEffectWrapperData::initPersistFields()
     "...");
     "...");
   addField("direction",         TypePoint3F,      myOffset(direction),
   addField("direction",         TypePoint3F,      myOffset(direction),
     "...");
     "...");
-  addField("speed",             TypeF32,          myOffset(speed),
+  addFieldV("speed", TypeRangedF32,          myOffset(speed), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("mass",              TypeF32,          myOffset(mass),
+  addFieldV("mass", TypeRangedF32,          myOffset(mass), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   addField("borrowAltitudes",   TypeBool,         myOffset(borrow_altitudes),
   addField("borrowAltitudes",   TypeBool,         myOffset(borrow_altitudes),
@@ -739,9 +740,9 @@ afxEffectWrapper::~afxEffectWrapper()
 void afxEffectWrapper::initPersistFields()
 void afxEffectWrapper::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("liveScaleFactor",     TypeF32,    myOffset(mLive_scale_factor),
+  addFieldV("liveScaleFactor", TypeRangedF32,    myOffset(mLive_scale_factor), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("liveFadeFactor",      TypeF32,    myOffset(mLive_fade_factor),
+  addFieldV("liveFadeFactor", TypeRangedF32,    myOffset(mLive_fade_factor), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();

+ 2 - 2
Engine/source/afx/afxEffectron.cpp

@@ -111,9 +111,9 @@ void afxEffectronData::reloadReset()
 void afxEffectronData::initPersistFields()
 void afxEffectronData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("duration",    TypeF32,      myOffset(duration),
+  addFieldV("duration", TypeRangedF32,      myOffset(duration), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("numLoops",    TypeS32,      myOffset(n_loops),
+  addFieldV("numLoops", TypeRangedS32,      myOffset(n_loops), &CommonValidators::NegDefaultInt,
     "...");
     "...");
   // effect lists
   // effect lists
   // for each of these, dummy_fx_entry is set and then a validator adds it to the appropriate effects list 
   // for each of these, dummy_fx_entry is set and then a validator adds it to the appropriate effects list 

+ 21 - 20
Engine/source/afx/afxMagicMissile.cpp

@@ -324,8 +324,9 @@ afxMagicMissileData* afxMagicMissileData::cloneAndPerformSubstitutions(const Sim
 
 
 FRangeValidator muzzleVelocityValidator(0, 10000);
 FRangeValidator muzzleVelocityValidator(0, 10000);
 FRangeValidator missilePrecisionValidator(0.f, 100.f);
 FRangeValidator missilePrecisionValidator(0.f, 100.f);
-FRangeValidator missileTrackDelayValidator(0, 100000);
+IRangeValidator missileTrackDelayValidator(0, 100000);
 FRangeValidator missileBallisticCoefficientValidator(0, 1);
 FRangeValidator missileBallisticCoefficientValidator(0, 1);
+FRangeValidator missileFollowTerrainAdjustRateValidator(0.05f, FLT_MAX);
 
 
 void afxMagicMissileData::initPersistFields()
 void afxMagicMissileData::initPersistFields()
 {
 {
@@ -353,36 +354,36 @@ void afxMagicMissileData::initPersistFields()
    endGroup("Light Emitter");
    endGroup("Light Emitter");
 
 
    addGroup("Physics");
    addGroup("Physics");
-      addNamedFieldV(lifetime,    TypeS32,              afxMagicMissileData,  &ticksFromMS);
-      addFieldV("casterSafetyTime", TypeS32, myOffset(caster_safety_time), &ticksFromMS);
+      addNamedFieldV(lifetime,    TypeRangedS32,              afxMagicMissileData,  &ticksFromMS);
+      addFieldV("casterSafetyTime", TypeRangedS32, myOffset(caster_safety_time), &ticksFromMS);
       addField("isBallistic", TypeBool,   Offset(isBallistic, afxMagicMissileData));
       addField("isBallistic", TypeBool,   Offset(isBallistic, afxMagicMissileData));
-      addNamedFieldV(muzzleVelocity,    TypeF32,      afxMagicMissileData,  &muzzleVelocityValidator);
-      addNamedFieldV(ballisticCoefficient,  TypeF32,    afxMagicMissileData,  &missileBallisticCoefficientValidator);
-      addField("gravityMod", TypeF32, Offset(gravityMod, afxMagicMissileData));
+      addNamedFieldV(muzzleVelocity,    TypeRangedF32,      afxMagicMissileData,  &muzzleVelocityValidator);
+      addNamedFieldV(ballisticCoefficient,  TypeRangedF32,    afxMagicMissileData,  &missileBallisticCoefficientValidator);
+      addFieldV("gravityMod", TypeRangedF32, Offset(gravityMod, afxMagicMissileData), &CommonValidators::F32Range);
       addField("collisionMask",         TypeS32,      myOffset(collision_mask));
       addField("collisionMask",         TypeS32,      myOffset(collision_mask));
       addField("startingVelocityVector",TypePoint3F,  myOffset(starting_vel_vec));
       addField("startingVelocityVector",TypePoint3F,  myOffset(starting_vel_vec));
       addNamedField(acceleration,     TypeF32,  afxMagicMissileData);
       addNamedField(acceleration,     TypeF32,  afxMagicMissileData);
-      addNamedFieldV(accelDelay,      TypeS32,  afxMagicMissileData,  &ticksFromMS);
-      addNamedFieldV(accelLifetime,   TypeS32,  afxMagicMissileData,  &ticksFromMS);
+      addNamedFieldV(accelDelay, TypeRangedS32,  afxMagicMissileData,  &ticksFromMS);
+      addNamedFieldV(accelLifetime, TypeRangedS32,  afxMagicMissileData,  &ticksFromMS);
       addField("reverseTargeting", TypeBool, myOffset(reverse_targeting));
       addField("reverseTargeting", TypeBool, myOffset(reverse_targeting));
    endGroup("Physics");
    endGroup("Physics");
 
 
    addGroup("Physics-Tracking");
    addGroup("Physics-Tracking");
       addNamedField(isGuided,               TypeBool,   afxMagicMissileData);
       addNamedField(isGuided,               TypeBool,   afxMagicMissileData);
-      addNamedFieldV(precision,             TypeF32,    afxMagicMissileData,  &missilePrecisionValidator); 
-      addNamedFieldV(trackDelay,            TypeS32,    afxMagicMissileData,  &missileTrackDelayValidator);
+      addNamedFieldV(precision,             TypeRangedF32,    afxMagicMissileData,  &missilePrecisionValidator);
+      addNamedFieldV(trackDelay,            TypeRangedS32,    afxMagicMissileData,  &missileTrackDelayValidator);
    endGroup("Physics-Tracking");
    endGroup("Physics-Tracking");
 
 
    addGroup("Physics-Avoidance");
    addGroup("Physics-Avoidance");
       addField("followTerrain",             TypeBool, myOffset(followTerrain));
       addField("followTerrain",             TypeBool, myOffset(followTerrain));
-      addField("followTerrainHeight",       TypeF32,  myOffset(followTerrainHeight));
-      addField("followTerrainAdjustRate",   TypeF32,  myOffset(followTerrainAdjustRate));
-      addFieldV("followTerrainAdjustDelay", TypeS32,  myOffset(followTerrainAdjustDelay), &ticksFromMS);
-
-      addField("hoverAltitude",       TypeF32,    myOffset(hover_altitude));
-      addField("hoverAttackDistance", TypeF32,    myOffset(hover_attack_distance));
-      addField("hoverAttackGradient", TypeF32,    myOffset(hover_attack_gradient));
-      addFieldV("hoverTime",          TypeS32,    myOffset(hover_time), &ticksFromMS); 
+      addFieldV("followTerrainHeight", TypeRangedS32,  myOffset(followTerrainHeight), &CommonValidators::PositiveFloat);
+      addFieldV("followTerrainAdjustRate", TypeRangedS32,  myOffset(followTerrainAdjustRate), &missileFollowTerrainAdjustRateValidator);
+      addFieldV("followTerrainAdjustDelay", TypeRangedS32,  myOffset(followTerrainAdjustDelay), &ticksFromMS);
+
+      addFieldV("hoverAltitude", TypeRangedF32,    myOffset(hover_altitude), &CommonValidators::PositiveFloat);
+      addFieldV("hoverAttackDistance", TypeRangedF32,    myOffset(hover_attack_distance), &CommonValidators::PositiveFloat);
+      addFieldV("hoverAttackGradient", TypeRangedF32,    myOffset(hover_attack_gradient), &CommonValidators::PositiveNonZeroFloat);
+      addFieldV("hoverTime", TypeRangedS32,    myOffset(hover_time), &ticksFromMS);
    endGroup("Physics-Avoidance");
    endGroup("Physics-Avoidance");
 
 
    addGroup("Physics-Launch");
    addGroup("Physics-Launch");
@@ -391,8 +392,8 @@ void afxMagicMissileData::initPersistFields()
       addField("launchOffsetServer",TypePoint3F,  myOffset(launch_offset_server));
       addField("launchOffsetServer",TypePoint3F,  myOffset(launch_offset_server));
       addField("launchOffsetClient",TypePoint3F,  myOffset(launch_offset_client));
       addField("launchOffsetClient",TypePoint3F,  myOffset(launch_offset_client));
       addField("launchNodeOffset",  TypePoint3F,  myOffset(launch_node_offset));
       addField("launchNodeOffset",  TypePoint3F,  myOffset(launch_node_offset));
-      addField("launchAimPitch",    TypeF32,      myOffset(launch_pitch));
-      addField("launchAimPan",      TypeF32,      myOffset(launch_pan));
+      addFieldV("launchAimPitch",    TypeRangedF32,      myOffset(launch_pitch), &CommonValidators::DegreeRange);
+      addFieldV("launchAimPan", TypeRangedF32,      myOffset(launch_pan), &CommonValidators::DegreeRange);
       addField("launchConstraintServer",  TypeString,   myOffset(launch_cons_s_spec));
       addField("launchConstraintServer",  TypeString,   myOffset(launch_cons_s_spec));
       addField("launchConstraintClient",  TypeString,   myOffset(launch_cons_c_spec));
       addField("launchConstraintClient",  TypeString,   myOffset(launch_cons_c_spec));
       addField("echoLaunchOffset",  TypeBool,     myOffset(echo_launch_offset));
       addField("echoLaunchOffset",  TypeBool,     myOffset(echo_launch_offset));

+ 10 - 10
Engine/source/afx/afxMagicSpell.cpp

@@ -220,22 +220,22 @@ void afxMagicSpellData::initPersistFields()
   // for each effect list, dummy_fx_entry is set and then a validator adds it to the appropriate effects list
   // for each effect list, dummy_fx_entry is set and then a validator adds it to the appropriate effects list
 
 
   addGroup("Casting Stage");
   addGroup("Casting Stage");
-  addField("castingDur",            TypeF32,        myOffset(mCasting_dur),
+  addFieldV("castingDur",            TypeRangedF32,        myOffset(mCasting_dur), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("numCastingLoops",       TypeS32,        myOffset(mNum_casting_loops),
+  addFieldV("numCastingLoops",       TypeRangedS32,        myOffset(mNum_casting_loops), &CommonValidators::NaturalNumber,
     "...");
     "...");
-  addField("extraCastingTime",      TypeF32,        myOffset(mExtra_casting_time),
+  addFieldV("extraCastingTime", TypeRangedF32,        myOffset(mExtra_casting_time), &CommonValidators::PositiveFloat,
     "...");
     "...");
   addFieldV("addCastingEffect", TYPEID<afxEffectBaseData>(), Offset(mDummy_fx_entry, afxMagicSpellData), &_castingPhrase,
   addFieldV("addCastingEffect", TYPEID<afxEffectBaseData>(), Offset(mDummy_fx_entry, afxMagicSpellData), &_castingPhrase,
     "...");
     "...");
   endGroup("Casting Stage");
   endGroup("Casting Stage");
 
 
   addGroup("Delivery Stage");
   addGroup("Delivery Stage");
-  addField("deliveryDur",           TypeF32,        myOffset(mDelivery_dur),
+  addFieldV("deliveryDur", TypeRangedF32,        myOffset(mDelivery_dur), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("numDeliveryLoops",      TypeS32,        myOffset(mNum_delivery_loops),
+  addFieldV("numDeliveryLoops", TypeRangedS32,        myOffset(mNum_delivery_loops), &CommonValidators::NaturalNumber,
     "...");
     "...");
-  addField("extraDeliveryTime",     TypeF32,        myOffset(mExtra_delivery_time),
+  addFieldV("extraDeliveryTime", TypeRangedF32,        myOffset(mExtra_delivery_time), &CommonValidators::PositiveFloat,
     "...");
     "...");
   addFieldV("addLaunchEffect", TYPEID<afxEffectBaseData>(), Offset(mDummy_fx_entry, afxMagicSpellData), &_launchPhrase,
   addFieldV("addLaunchEffect", TYPEID<afxEffectBaseData>(), Offset(mDummy_fx_entry, afxMagicSpellData), &_launchPhrase,
     "...");
     "...");
@@ -244,11 +244,11 @@ void afxMagicSpellData::initPersistFields()
   endGroup("Delivery Stage");
   endGroup("Delivery Stage");
 
 
   addGroup("Linger Stage");
   addGroup("Linger Stage");
-  addField("lingerDur",             TypeF32,        myOffset(mLinger_dur),
+  addFieldV("lingerDur", TypeRangedF32,        myOffset(mLinger_dur), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("numLingerLoops",        TypeS32,        myOffset(mNum_linger_loops),
+  addFieldV("numLingerLoops", TypeRangedS32,        myOffset(mNum_linger_loops), &CommonValidators::NaturalNumber,
     "...");
     "...");
-  addField("extraLingerTime",       TypeF32,        myOffset(mExtra_linger_time),
+  addFieldV("extraLingerTime", TypeRangedF32,        myOffset(mExtra_linger_time), &CommonValidators::PositiveFloat,
     "...");
     "...");
   addFieldV("addImpactEffect", TYPEID<afxEffectBaseData>(), Offset(mDummy_fx_entry, afxMagicSpellData), &_impactPhrase,
   addFieldV("addImpactEffect", TYPEID<afxEffectBaseData>(), Offset(mDummy_fx_entry, afxMagicSpellData), &_impactPhrase,
     "...");
     "...");
@@ -259,7 +259,7 @@ void afxMagicSpellData::initPersistFields()
   // interrupt flags
   // interrupt flags
   addField("allowMovementInterrupts", TypeBool,     myOffset(mDo_move_interrupts),
   addField("allowMovementInterrupts", TypeBool,     myOffset(mDo_move_interrupts),
     "...");
     "...");
-  addField("movementInterruptSpeed",  TypeF32,      myOffset(mMove_interrupt_speed),
+  addFieldV("movementInterruptSpeed", TypeRangedF32,      myOffset(mMove_interrupt_speed), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   // delivers projectile spells
   // delivers projectile spells

+ 9 - 9
Engine/source/afx/afxSelectron.cpp

@@ -153,17 +153,17 @@ void afxSelectronData::initPersistFields()
    static ewValidator _selectPhrase(SELECT_PHRASE);
    static ewValidator _selectPhrase(SELECT_PHRASE);
    static ewValidator _deselectPhrase(DESELECT_PHRASE);
    static ewValidator _deselectPhrase(DESELECT_PHRASE);
 
 
-  addField("mainDur",                   TypeF32,    myOffset(main_dur),
+  addFieldV("mainDur",                   TypeRangedF32,    myOffset(main_dur), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("selectDur",                 TypeF32,    myOffset(select_dur),
+  addFieldV("selectDur",                 TypeRangedF32,    myOffset(select_dur), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("deselectDur",               TypeF32,    myOffset(deselect_dur),
+  addFieldV("deselectDur",               TypeRangedF32,    myOffset(deselect_dur), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("mainRepeats",               TypeS32,    myOffset(n_main_loops),
+  addFieldV("mainRepeats", TypeRangedS32,    myOffset(n_main_loops), &CommonValidators::NaturalNumber,
     "...");
     "...");
-  addField("selectRepeats",             TypeS32,    myOffset(n_select_loops),
+  addFieldV("selectRepeats", TypeRangedS32,    myOffset(n_select_loops), &CommonValidators::NaturalNumber,
     "...");
     "...");
-  addField("deselectRepeats",           TypeS32,    myOffset(n_deselect_loops),
+  addFieldV("deselectRepeats", TypeRangedS32,    myOffset(n_deselect_loops), &CommonValidators::NaturalNumber,
     "...");
     "...");
   addField("selectionTypeMask",         TypeS32,    myOffset(obj_type_mask),
   addField("selectionTypeMask",         TypeS32,    myOffset(obj_type_mask),
     "...");
     "...");
@@ -180,11 +180,11 @@ void afxSelectronData::initPersistFields()
     "...");
     "...");
 
 
   // deprecated
   // deprecated
-  addField("numMainLoops",      TypeS32,      myOffset(n_main_loops),
+  addFieldV("numMainLoops", TypeRangedS32,      myOffset(n_main_loops), &CommonValidators::NaturalNumber,
     "...");
     "...");
-  addField("numSelectLoops",    TypeS32,      myOffset(n_select_loops),
+  addFieldV("numSelectLoops", TypeRangedS32,      myOffset(n_select_loops), &CommonValidators::NaturalNumber,
     "...");
     "...");
-  addField("numDeselectLoops",  TypeS32,      myOffset(n_deselect_loops),
+  addFieldV("numDeselectLoops", TypeRangedS32,      myOffset(n_deselect_loops), &CommonValidators::NaturalNumber,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();

+ 2 - 2
Engine/source/afx/ce/afxAnimClip.cpp

@@ -106,11 +106,11 @@ void afxAnimClipData::initPersistFields()
     "The name of an animation sequence to be played by a ShapeBase-derived object to which this effect is "
     "The name of an animation sequence to be played by a ShapeBase-derived object to which this effect is "
     "constrained. Also works on afxModel effects.\n"
     "constrained. Also works on afxModel effects.\n"
     "default: \"\"\n");
     "default: \"\"\n");
-  addField("rate",              TYPEID< F32 >(),               myOffset(rate),                  
+  addFieldV("rate", TypeRangedF32,               myOffset(rate), &CommonValidators::F32Range,
     "The desired playback speed for the sequence. A value of 1.0 indicates forward playback at a normal rate. Negative "
     "The desired playback speed for the sequence. A value of 1.0 indicates forward playback at a normal rate. Negative "
     "values cause the sequence to play backwards.\n"
     "values cause the sequence to play backwards.\n"
     "default: 1.0\n");
     "default: 1.0\n");
-  addField("posOffset",         TYPEID< F32 >(),               myOffset(pos_offset),
+  addFieldV("posOffset", TypeRangedF32,               myOffset(pos_offset), &CommonValidators::NormalizedFloat,
     "Sets a starting offset for the selected animation clip. It directly specifies an animation thread position in the 0.0 to "
     "Sets a starting offset for the selected animation clip. It directly specifies an animation thread position in the 0.0 to "
     "1.0 range as a fraction of the clip's duration.\n"
     "1.0 range as a fraction of the clip's duration.\n"
     "default: 1.0\n");
     "default: 1.0\n");

+ 3 - 3
Engine/source/afx/ce/afxAreaDamage.cpp

@@ -79,13 +79,13 @@ void afxAreaDamageData::initPersistFields()
     "An arbitrary string which is passed as an argument to a spell's onDamage() script "
     "An arbitrary string which is passed as an argument to a spell's onDamage() script "
     "method. It is used to classify a type of damage such as 'melee', 'magical', or "
     "method. It is used to classify a type of damage such as 'melee', 'magical', or "
     "'fire'.");
     "'fire'.");
-  addField("damage",                    TypeF32,        myOffset(amount),
+  addFieldV("damage", TypeRangedF32,        myOffset(amount), &CommonValidators::F32Range,
     "An amount of area damage to inflict on a target. Objects within half the radius "
     "An amount of area damage to inflict on a target. Objects within half the radius "
     "receive full damage which then diminishes out to the full distance of the specified "
     "receive full damage which then diminishes out to the full distance of the specified "
     "radius.");
     "radius.");
-  addField("radius",                    TypeF32,        myOffset(radius),
+  addFieldV("radius", TypeRangedF32,        myOffset(radius), &CommonValidators::PositiveFloat,
     "Radius centered at the effect position in which damage will be applied.");
     "Radius centered at the effect position in which damage will be applied.");
-  addField("impulse",                   TypeF32,        myOffset(impulse),
+  addFieldV("impulse", TypeRangedF32,        myOffset(impulse), &CommonValidators::F32Range,
     "Specifies an amount of force to apply to damaged objects. Objects within half the "
     "Specifies an amount of force to apply to damaged objects. Objects within half the "
     "radius receive full impulse which then diminishes out to the full distance of the "
     "radius receive full impulse which then diminishes out to the full distance of the "
     "specified radius.");
     "specified radius.");

+ 2 - 1
Engine/source/afx/ce/afxAudioBank.cpp

@@ -30,6 +30,7 @@
 #include "sfx/sfxDescription.h"
 #include "sfx/sfxDescription.h"
 
 
 #include "afx/ce/afxAudioBank.h"
 #include "afx/ce/afxAudioBank.h"
+#include "console/typeValidators.h"
 
 
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 
 
@@ -133,7 +134,7 @@ void afxAudioBank::initPersistFields()
     "SFXDescription datablock to use with this set of sounds.");
     "SFXDescription datablock to use with this set of sounds.");
   addField("preload",     TypeBool,                 Offset(mPreload, afxAudioBank),
   addField("preload",     TypeBool,                 Offset(mPreload, afxAudioBank),
     "If set to true, file is pre-loaded, otherwise it is loaded on-demand.");
     "If set to true, file is pre-loaded, otherwise it is loaded on-demand.");
-  addField("playIndex",   TypeS32,                  Offset(play_index, afxAudioBank),
+  addFieldV("playIndex", TypeRangedS32,                  Offset(play_index, afxAudioBank), &CommonValidators::NegDefaultInt,
     "An array index that selects a sound to play from the filenames[] field. Values "
     "An array index that selects a sound to play from the filenames[] field. Values "
     "outside of the range of assigned filename[] entries will not play any sound.");
     "outside of the range of assigned filename[] entries will not play any sound.");
 
 

+ 2 - 2
Engine/source/afx/ce/afxCameraShake.cpp

@@ -71,9 +71,9 @@ void afxCameraShakeData::initPersistFields()
     "The camera shake frequencies for all three axes: X, Y, Z.");
     "The camera shake frequencies for all three axes: X, Y, Z.");
   addField("amplitude", TypePoint3F,   Offset(camShakeAmp,        afxCameraShakeData),
   addField("amplitude", TypePoint3F,   Offset(camShakeAmp,        afxCameraShakeData),
     "The camera shake amplitudes for all three axes: X, Y, Z.");
     "The camera shake amplitudes for all three axes: X, Y, Z.");
-  addField("radius",    TypeF32,       Offset(camShakeRadius,     afxCameraShakeData),
+  addFieldV("radius", TypeRangedF32,       Offset(camShakeRadius,     afxCameraShakeData), &CommonValidators::PositiveFloat,
     "Radius about the effect position in which shaking will be applied.");
     "Radius about the effect position in which shaking will be applied.");
-  addField("falloff",   TypeF32,       Offset(camShakeFalloff,    afxCameraShakeData),
+  addFieldV("falloff", TypeRangedF32,       Offset(camShakeFalloff,    afxCameraShakeData), &CommonValidators::PositiveFloat,
     "Magnitude by which shaking decreases over distance to radius.");
     "Magnitude by which shaking decreases over distance to radius.");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();

+ 4 - 4
Engine/source/afx/ce/afxDamage.cpp

@@ -83,19 +83,19 @@ void afxDamageData::initPersistFields()
     "An arbitrary string which is passed as an argument to a spell's onDamage() script "
     "An arbitrary string which is passed as an argument to a spell's onDamage() script "
     "method. It is used to classify a type of damage such as 'melee', 'magical', or "
     "method. It is used to classify a type of damage such as 'melee', 'magical', or "
     "'fire'.");
     "'fire'.");
-  addField("directDamage",        TypeF32,        myOffset(amount),
+  addFieldV("directDamage",        TypeRangedF32,        myOffset(amount), &CommonValidators::F32Range,
     "An amount of direct damage to inflict on a target.");
     "An amount of direct damage to inflict on a target.");
   addField("directDamageRepeats", TypeS8,         myOffset(repeats),
   addField("directDamageRepeats", TypeS8,         myOffset(repeats),
     "The number of times to inflict the damage specified by directDamage. Values "
     "The number of times to inflict the damage specified by directDamage. Values "
     "greater than 1 inflict damage over time, with the amount of directDamage "
     "greater than 1 inflict damage over time, with the amount of directDamage "
     "repeatedly dealt at evenly spaced intervals over the lifetime of the effect.");
     "repeatedly dealt at evenly spaced intervals over the lifetime of the effect.");
-  addField("areaDamage",          TypeF32,        myOffset(ad_amount),
+  addFieldV("areaDamage", TypeRangedF32,        myOffset(ad_amount), &CommonValidators::F32Range,
     "An amount of area damage to inflict on a target. Objects within half the radius "
     "An amount of area damage to inflict on a target. Objects within half the radius "
     "receive full damage which then diminishes out to the full distance of "
     "receive full damage which then diminishes out to the full distance of "
     "areaDamageRadius.");
     "areaDamageRadius.");
-  addField("areaDamageRadius",    TypeF32,        myOffset(radius),
+  addFieldV("areaDamageRadius", TypeRangedF32,        myOffset(radius), &CommonValidators::PositiveFloat,
     "Radius centered at the effect position in which damage will be applied.");
     "Radius centered at the effect position in which damage will be applied.");
-  addField("areaDamageImpulse",   TypeF32,        myOffset(impulse),
+  addFieldV("areaDamageImpulse", TypeRangedF32,        myOffset(impulse), &CommonValidators::F32Range,
     "Specifies an amount of force to apply to damaged objects. Objects within half the "
     "Specifies an amount of force to apply to damaged objects. Objects within half the "
     "radius receive full impulse which then diminishes out to the full distance of "
     "radius receive full impulse which then diminishes out to the full distance of "
     "areaDamageRadius.");
     "areaDamageRadius.");

+ 5 - 5
Engine/source/afx/ce/afxLightBase_T3D.cpp

@@ -104,11 +104,11 @@ void afxT3DLightBaseData::initPersistFields()
         "Enables/Disables the object rendering and functionality in the scene.");
         "Enables/Disables the object rendering and functionality in the scene.");
       addField( "color", TypeColorF, Offset( mColor, afxT3DLightBaseData ),
       addField( "color", TypeColorF, Offset( mColor, afxT3DLightBaseData ),
         "Changes the base color hue of the light.");
         "Changes the base color hue of the light.");
-      addField( "brightness", TypeF32, Offset( mBrightness, afxT3DLightBaseData ),
+      addFieldV( "brightness", TypeRangedF32, Offset( mBrightness, afxT3DLightBaseData ), &CommonValidators::PositiveFloat,
         "Adjusts the lights power, 0 being off completely.");
         "Adjusts the lights power, 0 being off completely.");
       addField( "castShadows", TypeBool, Offset( mCastShadows, afxT3DLightBaseData ),
       addField( "castShadows", TypeBool, Offset( mCastShadows, afxT3DLightBaseData ),
         "Enables/disables shadow casts by this light.");
         "Enables/disables shadow casts by this light.");
-      addField( "priority", TypeF32, Offset( mPriority, afxT3DLightBaseData ),
+      addFieldV( "priority", TypeRangedF32, Offset( mPriority, afxT3DLightBaseData ), &CommonValidators::PositiveFloat,
         "Used for sorting of lights by the light manager. Priority determines if a light "
         "Used for sorting of lights by the light manager. Priority determines if a light "
         "has a stronger effect than, those with a lower value");
         "has a stronger effect than, those with a lower value");
       addField( "localRenderViz", TypeBool, Offset( mLocalRenderViz, afxT3DLightBaseData ),
       addField( "localRenderViz", TypeBool, Offset( mLocalRenderViz, afxT3DLightBaseData ),
@@ -123,9 +123,9 @@ void afxT3DLightBaseData::initPersistFields()
         "Toggles animation for the light on and off");
         "Toggles animation for the light on and off");
       addField( "animationType", TYPEID<LightAnimData>(), Offset( mAnimationData, afxT3DLightBaseData ),
       addField( "animationType", TYPEID<LightAnimData>(), Offset( mAnimationData, afxT3DLightBaseData ),
         "Datablock containing light animation information (LightAnimData)");
         "Datablock containing light animation information (LightAnimData)");
-      addField( "animationPeriod", TypeF32, Offset( mAnimState.animationPeriod, afxT3DLightBaseData ),
+      addFieldV( "animationPeriod", TypeRangedF32, Offset( mAnimState.animationPeriod, afxT3DLightBaseData ), &CommonValidators::PositiveFloat,
         "The length of time in seconds for a single playback of the light animation");
         "The length of time in seconds for a single playback of the light animation");
-      addField( "animationPhase", TypeF32, Offset( mAnimState.animationPhase, afxT3DLightBaseData ),
+      addFieldV( "animationPhase", TypeRangedF32, Offset( mAnimState.animationPhase, afxT3DLightBaseData ), &CommonValidators::PositiveFloat,
         "The phase used to offset the animation start time to vary the animation of "
         "The phase used to offset the animation start time to vary the animation of "
         "nearby lights.");
         "nearby lights.");
 
 
@@ -135,7 +135,7 @@ void afxT3DLightBaseData::initPersistFields()
 
 
       addField( "flareType", TYPEID<LightFlareData>(), Offset( mFlareData, afxT3DLightBaseData ),
       addField( "flareType", TYPEID<LightFlareData>(), Offset( mFlareData, afxT3DLightBaseData ),
         "Datablock containing light flare information (LightFlareData)");
         "Datablock containing light flare information (LightFlareData)");
-      addField( "flareScale", TypeF32, Offset( mFlareScale, afxT3DLightBaseData ),
+      addFieldV( "flareScale", TypeRangedF32, Offset( mFlareScale, afxT3DLightBaseData ), &CommonValidators::PositiveFloat,
         "Globally scales all features of the light flare");
         "Globally scales all features of the light flare");
 
 
    endGroup( "Misc" );
    endGroup( "Misc" );

+ 2 - 1
Engine/source/afx/ce/afxMachineGun.cpp

@@ -31,6 +31,7 @@
 #include "T3D/projectile.h"
 #include "T3D/projectile.h"
 
 
 #include "afx/ce/afxMachineGun.h"
 #include "afx/ce/afxMachineGun.h"
+#include "console/typeValidators.h"
 
 
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 // afxMachineGunData
 // afxMachineGunData
@@ -68,7 +69,7 @@ void afxMachineGunData::initPersistFields()
    docsURL;
    docsURL;
   addField("projectile", TYPEID<ProjectileData>(), myOffset(projectile_data),
   addField("projectile", TYPEID<ProjectileData>(), myOffset(projectile_data),
     "A ProjectileData datablock describing the projectile to be launched.");
     "A ProjectileData datablock describing the projectile to be launched.");
-  addField("roundsPerMinute", TypeS32, myOffset(rounds_per_minute),
+  addFieldV("roundsPerMinute", TypeRangedS32, myOffset(rounds_per_minute), &CommonValidators::PositiveInt,
     "Specifies the number of projectiles fired over a minute of time. A value of 1200 "
     "Specifies the number of projectiles fired over a minute of time. A value of 1200 "
     "will create 20 projectiles per second.\n"
     "will create 20 projectiles per second.\n"
     "Sample values for real machine guns:\n"
     "Sample values for real machine guns:\n"

+ 4 - 4
Engine/source/afx/ce/afxModel.cpp

@@ -180,18 +180,18 @@ void afxModelData::initPersistFields()
    addGroup("Animation");
    addGroup("Animation");
       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),
+      addFieldV("sequenceRate", TypeRangedF32,      myOffset(seq_rate), &CommonValidators::F32Range,
          "The rate of playback for the sequence.");
          "The rate of playback for the sequence.");
-      addField("sequenceOffset",        TypeF32,      myOffset(seq_offset),
+      addFieldV("sequenceOffset", TypeRangedF32,      myOffset(seq_offset), &CommonValidators::F32Range,
          "An offset in seconds indicating a starting point for the animation sequence "
          "An offset in seconds indicating a starting point for the animation sequence "
          "specified by the sequence field. A rate of 1.0 (rather than sequenceRate) is used "
          "specified by the sequence field. A rate of 1.0 (rather than sequenceRate) is used "
          "to convert from seconds to the thread offset.");
          "to convert from seconds to the thread offset.");
    endGroup("Animation");
    endGroup("Animation");
 
 
    addGroup("Rendering");
    addGroup("Rendering");
-      addField("alphaMult",             TypeF32,      myOffset(alpha_mult),
+      addFieldV("alphaMult", TypeRangedF32,      myOffset(alpha_mult), &CommonValidators::PositiveFloat,
          "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), "");
+      addFieldV("fogMult", TypeRangedF32,      myOffset(fog_mult), &CommonValidators::PositiveFloat, "");
       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"

+ 5 - 5
Engine/source/afx/ce/afxParticleEmitter.cpp

@@ -292,9 +292,9 @@ afxParticleEmitterConeData::afxParticleEmitterConeData(const afxParticleEmitterC
 void afxParticleEmitterConeData::initPersistFields()
 void afxParticleEmitterConeData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("spreadMin",   TypeF32,    Offset(spread_min, afxParticleEmitterConeData),
+  addFieldV("spreadMin",   TypeRangedF32,    Offset(spread_min, afxParticleEmitterConeData), &CommonValidators::PosDegreeRangeHalf,
     "...");
     "...");
-  addField("spreadMax",   TypeF32,    Offset(spread_max, afxParticleEmitterConeData),
+  addFieldV("spreadMax", TypeRangedF32,    Offset(spread_max, afxParticleEmitterConeData), &CommonValidators::PosDegreeRangeHalf,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();
@@ -416,7 +416,7 @@ void afxParticleEmitterPathData::initPersistFields()
     "...");
     "...");
   addField("groundConformInteriors",  TypeBool, Offset(ground_conform_interiors,  afxParticleEmitterPathData),
   addField("groundConformInteriors",  TypeBool, Offset(ground_conform_interiors,  afxParticleEmitterPathData),
     "...");
     "...");
-  addField("groundConformHeight",     TypeF32,  Offset(ground_conform_height,     afxParticleEmitterPathData),
+  addFieldV("groundConformHeight",     TypeRangedF32,  Offset(ground_conform_height,     afxParticleEmitterPathData), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();
@@ -647,9 +647,9 @@ afxParticleEmitterDiscData::afxParticleEmitterDiscData(const afxParticleEmitterD
 void afxParticleEmitterDiscData::initPersistFields()
 void afxParticleEmitterDiscData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("radiusMin",   TypeF32,    Offset(pe_radius_min, afxParticleEmitterDiscData),
+  addFieldV("radiusMin",   TypeRangedF32,    Offset(pe_radius_min, afxParticleEmitterDiscData), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("radiusMax",   TypeF32,    Offset(pe_radius_max, afxParticleEmitterDiscData),
+  addFieldV("radiusMax", TypeRangedF32,    Offset(pe_radius_max, afxParticleEmitterDiscData), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();

+ 2 - 2
Engine/source/afx/ce/afxPhraseEffect.cpp

@@ -140,11 +140,11 @@ EndImplementEnumType;
 void afxPhraseEffectData::initPersistFields()
 void afxPhraseEffectData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("duration",    TypeF32,      myOffset(duration),
+  addFieldV("duration",    TypeRangedF32,      myOffset(duration), &CommonValidators::NegDefaultF32,
     "Specifies a duration for the phrase-effect. If set to infinity, the phrase-effect "
     "Specifies a duration for the phrase-effect. If set to infinity, the phrase-effect "
     "needs to have a phraseType of continuous. Set infinite duration using "
     "needs to have a phraseType of continuous. Set infinite duration using "
     "$AFX::INFINITE_TIME.");
     "$AFX::INFINITE_TIME.");
-  addField("numLoops",    TypeS32,      myOffset(n_loops),
+  addFieldV("numLoops", TypeRangedS32,      myOffset(n_loops), &CommonValidators::NegDefaultInt,
     "Specifies the number of times the phrase-effect should loop. If set to infinity, "
     "Specifies the number of times the phrase-effect should loop. If set to infinity, "
     "the phrase-effect needs to have a phraseType of continuous. Set infinite looping "
     "the phrase-effect needs to have a phraseType of continuous. Set infinite looping "
     "using $AFX::INFINITE_REPEATS.");
     "using $AFX::INFINITE_REPEATS.");

+ 4 - 2
Engine/source/afx/ce/afxPhysicalZone.cpp

@@ -73,13 +73,15 @@ afxPhysicalZoneData::afxPhysicalZoneData(const afxPhysicalZoneData& other, bool
 
 
 #define myOffset(field) Offset(field, afxPhysicalZoneData)
 #define myOffset(field) Offset(field, afxPhysicalZoneData)
 
 
+FRangeValidator afxVelocityModRange(-40.0f, 40.0f);
+FRangeValidator afxGravityModRange(-40.0f, 40.0f);
 void afxPhysicalZoneData::initPersistFields()
 void afxPhysicalZoneData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("velocityMod",               TypeF32,         myOffset(mVelocityMod),
+  addFieldV("velocityMod", TypeRangedF32,         myOffset(mVelocityMod), &afxVelocityModRange,
     "A multiplier that biases the velocity of an object every tick it is within the "
     "A multiplier that biases the velocity of an object every tick it is within the "
     "zone.");
     "zone.");
-  addField("gravityMod",                TypeF32,         myOffset(mGravityMod),
+  addFieldV("gravityMod", TypeRangedF32,         myOffset(mGravityMod), &afxGravityModRange,
     "A multiplier that biases the influence of gravity on objects within the zone.");
     "A multiplier that biases the influence of gravity on objects within the zone.");
   addField("appliedForce",              TypePoint3F,     myOffset(mAppliedForce),
   addField("appliedForce",              TypePoint3F,     myOffset(mAppliedForce),
     "A three-valued vector representing a directional force applied to objects withing "
     "A three-valued vector representing a directional force applied to objects withing "

+ 1 - 1
Engine/source/afx/ce/afxPlayerMovement.cpp

@@ -81,7 +81,7 @@ EndImplementEnumType;
 void afxPlayerMovementData::initPersistFields()
 void afxPlayerMovementData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("speedBias",     TypeF32,        myOffset(speed_bias),
+  addFieldV("speedBias",     TypeRangedF32,        myOffset(speed_bias), &CommonValidators::F32Range,
     "A floating-point multiplier that scales the constraint Player's movement speed.");
     "A floating-point multiplier that scales the constraint Player's movement speed.");
   addField("movement",      TypePoint3F,    myOffset(movement),
   addField("movement",      TypePoint3F,    myOffset(movement),
     "");
     "");

+ 1 - 1
Engine/source/afx/ce/afxPointLight_T3D.cpp

@@ -65,7 +65,7 @@ void afxT3DPointLightData::initPersistFields()
    docsURL;
    docsURL;
    addGroup( "Light" );
    addGroup( "Light" );
       
       
-      addField( "radius", TypeF32, Offset( mRadius, afxT3DPointLightData ),
+      addFieldV( "radius", TypeRangedF32, Offset( mRadius, afxT3DPointLightData ), &CommonValidators::PositiveFloat,
         "Controls the falloff of the light emission");
         "Controls the falloff of the light emission");
 
 
    endGroup( "Light" );
    endGroup( "Light" );

+ 3 - 3
Engine/source/afx/ce/afxSpotLight_T3D.cpp

@@ -69,11 +69,11 @@ void afxT3DSpotLightData::initPersistFields()
    docsURL;
    docsURL;
    addGroup( "Light" );
    addGroup( "Light" );
       
       
-      addField( "range", TypeF32, Offset( mRange, afxT3DSpotLightData ),
+      addFieldV( "range", TypeRangedF32, Offset( mRange, afxT3DSpotLightData ), &CommonValidators::PositiveFloat,
         "...");
         "...");
-      addField( "innerAngle", TypeF32, Offset( mInnerConeAngle, afxT3DSpotLightData ),
+      addFieldV( "innerAngle", TypeRangedF32, Offset( mInnerConeAngle, afxT3DSpotLightData ), &CommonValidators::DegreeRangeQuarter,
         "...");
         "...");
-      addField( "outerAngle", TypeF32, Offset( mOuterConeAngle, afxT3DSpotLightData ),
+      addFieldV( "outerAngle", TypeRangedF32, Offset( mOuterConeAngle, afxT3DSpotLightData ), &CommonValidators::DegreeRangeQuarter,
         "...");
         "...");
 
 
    endGroup( "Light" );
    endGroup( "Light" );

+ 10 - 10
Engine/source/afx/ce/afxZodiac.cpp

@@ -158,7 +158,7 @@ void afxZodiacData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
    INITPERSISTFIELD_IMAGEASSET(Texture, afxZodiacData, "An image to use as the zodiac's texture.");
    INITPERSISTFIELD_IMAGEASSET(Texture, afxZodiacData, "An image to use as the zodiac's texture.");
-  addField("radius",                TypeF32,        Offset(radius_xy,         afxZodiacData),
+  addFieldV("radius",                TypeRangedF32,        Offset(radius_xy,         afxZodiacData), &CommonValidators::PositiveFloat,
     "The zodiac's radius in scene units.");
     "The zodiac's radius in scene units.");
   addField("verticalRange",         TypePoint2F,    Offset(vert_range,        afxZodiacData),
   addField("verticalRange",         TypePoint2F,    Offset(vert_range,        afxZodiacData),
     "For interior zodiacs only, verticalRange specifies distances above and below the "
     "For interior zodiacs only, verticalRange specifies distances above and below the "
@@ -167,18 +167,18 @@ void afxZodiacData::initPersistFields()
     "Specifies if the zodiac's verticalRange should scale according to changes in the "
     "Specifies if the zodiac's verticalRange should scale according to changes in the "
     "radius. When a zodiacs is used as an expanding shockwave, this value should be set "
     "radius. When a zodiacs is used as an expanding shockwave, this value should be set "
     "to false, otherwise the zodiac can expand to cover an entire interior.");
     "to false, otherwise the zodiac can expand to cover an entire interior.");
-  addField("startAngle",            TypeF32,        Offset(start_ang,         afxZodiacData),
+  addFieldV("startAngle", TypeRangedF32,        Offset(start_ang,         afxZodiacData), &CommonValidators::DegreeRange,
     "The starting angle in degrees of the zodiac's rotation.");
     "The starting angle in degrees of the zodiac's rotation.");
-  addField("rotationRate",          TypeF32,        Offset(ang_per_sec,       afxZodiacData),
+  addFieldV("rotationRate", TypeRangedF32,        Offset(ang_per_sec,       afxZodiacData), &CommonValidators::DegreeRange,
     "The rate of rotation in degrees-per-second. Zodiacs with a positive rotationRate "
     "The rate of rotation in degrees-per-second. Zodiacs with a positive rotationRate "
     "rotate clockwise, while those with negative values turn counter-clockwise.");
     "rotate clockwise, while those with negative values turn counter-clockwise.");
-  addField("growInTime",            TypeF32,        Offset(grow_in_time,      afxZodiacData),
+  addFieldV("growInTime", TypeRangedF32,        Offset(grow_in_time,      afxZodiacData), &CommonValidators::PositiveFloat,
     "A duration of time in seconds over which the zodiac grows from a zero size to its "
     "A duration of time in seconds over which the zodiac grows from a zero size to its "
     "full size as specified by the radius.");
     "full size as specified by the radius.");
-  addField("shrinkOutTime",         TypeF32,        Offset(shrink_out_time,   afxZodiacData),
+  addFieldV("shrinkOutTime", TypeRangedF32,        Offset(shrink_out_time,   afxZodiacData), &CommonValidators::PositiveFloat,
     "A duration of time in seconds over which the zodiac shrinks from full size to "
     "A duration of time in seconds over which the zodiac shrinks from full size to "
     "invisible.");
     "invisible.");
-  addField("growthRate",            TypeF32,        Offset(growth_rate,       afxZodiacData),
+  addFieldV("growthRate", TypeRangedF32,        Offset(growth_rate,       afxZodiacData), &CommonValidators::F32Range,
     "A rate in meters-per-second at which the zodiac grows in size. A negative value will "
     "A rate in meters-per-second at which the zodiac grows in size. A negative value will "
     "shrink the zodiac.");
     "shrink the zodiac.");
   addField("color",                 TypeColorF,     Offset(color,             afxZodiacData),
   addField("color",                 TypeColorF,     Offset(color,             afxZodiacData),
@@ -215,20 +215,20 @@ void afxZodiacData::initPersistFields()
   addField("interiorIgnoreTransparent", TypeBool,   Offset(interior_transp_ignore, afxZodiacData),
   addField("interiorIgnoreTransparent", TypeBool,   Offset(interior_transp_ignore, afxZodiacData),
     "");
     "");
 
 
-  addField("altitudeMax",           TypeF32,      Offset(altitude_max, afxZodiacData),
+  addFieldV("altitudeMax", TypeRangedF32,      Offset(altitude_max, afxZodiacData), &CommonValidators::F32Range,
     "The altitude at which zodiac becomes invisible as the result of fading out or "
     "The altitude at which zodiac becomes invisible as the result of fading out or "
     "becoming too small.");
     "becoming too small.");
-  addField("altitudeFalloff",       TypeF32,      Offset(altitude_falloff, afxZodiacData),
+  addFieldV("altitudeFalloff", TypeRangedF32,      Offset(altitude_falloff, afxZodiacData), &CommonValidators::F32Range,
     "The altitude at which zodiac begins to fade and/or shrink.");
     "The altitude at which zodiac begins to fade and/or shrink.");
   addField("altitudeShrinks",       TypeBool,     Offset(altitude_shrinks, afxZodiacData),
   addField("altitudeShrinks",       TypeBool,     Offset(altitude_shrinks, afxZodiacData),
     "When true, zodiac becomes smaller as altitude increases.");
     "When true, zodiac becomes smaller as altitude increases.");
   addField("altitudeFades",         TypeBool,     Offset(altitude_fades, afxZodiacData),
   addField("altitudeFades",         TypeBool,     Offset(altitude_fades, afxZodiacData),
     "When true, zodiac fades out as altitude increases.");
     "When true, zodiac fades out as altitude increases.");
 
 
-  addField("distanceMax",           TypeF32,      Offset(distance_max, afxZodiacData),
+  addFieldV("distanceMax", TypeRangedF32,      Offset(distance_max, afxZodiacData), &CommonValidators::PositiveFloat,
     "The distance from camera at which the zodiac becomes invisible as the result of "
     "The distance from camera at which the zodiac becomes invisible as the result of "
     "fading out.");
     "fading out.");
-  addField("distanceFalloff",       TypeF32,      Offset(distance_falloff, afxZodiacData),
+  addFieldV("distanceFalloff", TypeRangedF32,      Offset(distance_falloff, afxZodiacData), &CommonValidators::PositiveFloat,
     "The distance from camera at which the zodiac begins to fade out.");
     "The distance from camera at which the zodiac begins to fade out.");
 
 
   addField("useGradientRange",      TypeBool,     Offset(use_grade_range, afxZodiacData),
   addField("useGradientRange",      TypeBool,     Offset(use_grade_range, afxZodiacData),

+ 6 - 6
Engine/source/afx/ce/afxZodiacPlane.cpp

@@ -114,20 +114,20 @@ void afxZodiacPlaneData::initPersistFields()
    docsURL;
    docsURL;
    INITPERSISTFIELD_IMAGEASSET(Texture, afxZodiacPlaneData, "An image to use as the zodiac's texture.");
    INITPERSISTFIELD_IMAGEASSET(Texture, afxZodiacPlaneData, "An image to use as the zodiac's texture.");
 
 
-  addField("radius",          TypeF32,        myOffset(radius_xy),
+  addFieldV("radius", TypeRangedF32,        myOffset(radius_xy), &CommonValidators::PositiveFloat,
     "The zodiac's radius in scene units.");
     "The zodiac's radius in scene units.");
-  addField("startAngle",      TypeF32,        myOffset(start_ang),
+  addFieldV("startAngle", TypeRangedF32,        myOffset(start_ang), &CommonValidators::DegreeRange,
     "The starting angle in degrees of the zodiac's rotation.");
     "The starting angle in degrees of the zodiac's rotation.");
-  addField("rotationRate",    TypeF32,        myOffset(ang_per_sec),
+  addFieldV("rotationRate", TypeRangedF32,        myOffset(ang_per_sec), &CommonValidators::DegreeRange,
     "The rate of rotation in degrees-per-second. Zodiacs with a positive rotationRate "
     "The rate of rotation in degrees-per-second. Zodiacs with a positive rotationRate "
     "rotate clockwise, while those with negative values turn counter-clockwise.");
     "rotate clockwise, while those with negative values turn counter-clockwise.");
-  addField("growInTime",      TypeF32,        myOffset(grow_in_time),
+  addFieldV("growInTime", TypeRangedF32,        myOffset(grow_in_time), &CommonValidators::PositiveFloat,
     "A duration of time in seconds over which the zodiac grows from a zero size to its "
     "A duration of time in seconds over which the zodiac grows from a zero size to its "
     "full size as specified by the radius.");
     "full size as specified by the radius.");
-  addField("shrinkOutTime",   TypeF32,        myOffset(shrink_out_time),
+  addFieldV("shrinkOutTime", TypeRangedF32,        myOffset(shrink_out_time), &CommonValidators::PositiveFloat,
     "A duration of time in seconds over which the zodiac shrinks from full size to "
     "A duration of time in seconds over which the zodiac shrinks from full size to "
     "invisible.");
     "invisible.");
-  addField("growthRate",      TypeF32,        myOffset(growth_rate),
+  addFieldV("growthRate", TypeRangedF32,        myOffset(growth_rate), &CommonValidators::F32Range,
     "A rate in meters-per-second at which the zodiac grows in size. A negative value will "
     "A rate in meters-per-second at which the zodiac grows in size. A negative value will "
     "shrink the zodiac.");
     "shrink the zodiac.");
   addField("color",           TypeColorF,     myOffset(color),
   addField("color",           TypeColorF,     myOffset(color),

+ 1 - 1
Engine/source/afx/ea/afxEA_Zodiac.cpp

@@ -399,7 +399,7 @@ void afxEA_Zodiac::initPersistFields()
    docsURL;
    docsURL;
   addField("liveColor",         TypeColorF,     myOffset(live_color),
   addField("liveColor",         TypeColorF,     myOffset(live_color),
     "...");
     "...");
-  addField("liveColorFactor",   TypeF32,        myOffset(live_color_factor),
+  addFieldV("liveColorFactor",   TypeRangedF32,        myOffset(live_color_factor), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();

+ 2 - 2
Engine/source/afx/forces/afxF_Drag.cpp

@@ -103,9 +103,9 @@ afxF_DragData::afxF_DragData(const afxF_DragData& other, bool temp_clone) : afxF
 void afxF_DragData::initPersistFields()
 void afxF_DragData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("drag",                TypeF32,      myOffset(drag_coefficient),
+  addFieldV("drag",                TypeRangedF32,      myOffset(drag_coefficient), &CommonValidators::PositiveNonZeroFloat,
     "...");
     "...");
-  addField("airDensity",          TypeF32,      myOffset(air_density),
+  addFieldV("airDensity", TypeRangedF32,      myOffset(air_density), &CommonValidators::PositiveNonZeroFloat,
     "...");
     "...");
   addField("crossSectionalArea",  TypeF32,      myOffset(cross_sectional_area),
   addField("crossSectionalArea",  TypeF32,      myOffset(cross_sectional_area),
     "...");
     "...");

+ 1 - 1
Engine/source/afx/forces/afxF_Gravity.cpp

@@ -95,7 +95,7 @@ afxF_GravityData::afxF_GravityData(const afxF_GravityData& other, bool temp_clon
 void afxF_GravityData::initPersistFields()
 void afxF_GravityData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("gravity",   TypeF32,     myOffset(gravity),
+  addFieldV("gravity", TypeRangedF32,     myOffset(gravity), &CommonValidators::F32Range,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();

+ 3 - 3
Engine/source/afx/rpg/afxRPGMagicSpell.cpp

@@ -91,9 +91,9 @@ void afxRPGMagicSpellData::initPersistFields()
   addField("target", TYPEID< afxRPGMagicSpellData::TargetType >(), myOffset(spell_target),
   addField("target", TYPEID< afxRPGMagicSpellData::TargetType >(), myOffset(spell_target),
     "...");
     "...");
 
 
-  addField("range",             TypeF32,        myOffset(spell_range),
+  addFieldV("range",             TypeRangedF32,        myOffset(spell_range), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("manaCost",          TypeS32,        myOffset(mana_cost),
+  addFieldV("manaCost",          TypeRangedS32,        myOffset(mana_cost), &CommonValidators::PositiveInt,
     "...");
     "...");
   addField("reagentCost",       TypeS8,         myOffset(reagent_cost), MAX_REAGENTS_PER_SPELL,
   addField("reagentCost",       TypeS8,         myOffset(reagent_cost), MAX_REAGENTS_PER_SPELL,
     "...");
     "...");
@@ -101,7 +101,7 @@ void afxRPGMagicSpellData::initPersistFields()
     "...");
     "...");
 
 
   // spell phase timing
   // spell phase timing
-  addField("castingDur",        TypeF32,        myOffset(casting_dur));
+  addFieldV("castingDur", TypeRangedF32,        myOffset(casting_dur), &CommonValidators::PositiveFloat);
 
 
   // interface elements
   // interface elements
   addField("iconBitmap",        TypeFilename,   myOffset(icon_name));
   addField("iconBitmap",        TypeFilename,   myOffset(icon_name));

+ 2 - 2
Engine/source/afx/ui/afxGuiTextHud.cpp

@@ -75,9 +75,9 @@ void afxGuiTextHud::initPersistFields()
     "...");
     "...");
    addField( "showFrame",  TypeBool, Offset( mShowFrame, afxGuiTextHud ),
    addField( "showFrame",  TypeBool, Offset( mShowFrame, afxGuiTextHud ),
     "...");
     "...");
-   addField( "verticalOffset", TypeF32, Offset( mVerticalOffset, afxGuiTextHud  ),
+   addFieldV( "verticalOffset", TypeRangedF32, Offset( mVerticalOffset, afxGuiTextHud  ), &CommonValidators::F32Range,
     "...");
     "...");
-   addField( "distanceFade", TypeF32, Offset( mDistanceFade, afxGuiTextHud ),
+   addFieldV( "distanceFade", TypeRangedF32, Offset( mDistanceFade, afxGuiTextHud ), &CommonValidators::PositiveFloat,
     "...");
     "...");
    addField( "labelAllShapes",  TypeBool, Offset( mLabelAllShapes, afxGuiTextHud ),
    addField( "labelAllShapes",  TypeBool, Offset( mLabelAllShapes, afxGuiTextHud ),
     "...");
     "...");

+ 1 - 1
Engine/source/afx/util/afxParticlePool.cpp

@@ -75,7 +75,7 @@ void afxParticlePoolData::initPersistFields()
     "...");
     "...");
   addField("baseColor",   TypeColorF,  Offset(base_color,   afxParticlePoolData),
   addField("baseColor",   TypeColorF,  Offset(base_color,   afxParticlePoolData),
     "...");
     "...");
-  addField("blendWeight", TypeF32,     Offset(blend_weight, afxParticlePoolData),
+  addFieldV("blendWeight", TypeRangedF32,     Offset(blend_weight, afxParticlePoolData), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();

+ 4 - 4
Engine/source/afx/util/afxPath.cpp

@@ -151,13 +151,13 @@ void afxPathData::initPersistFields()
     "...");
     "...");
   addField("loop",       TypeString,  Offset(loop_string,   afxPathData),
   addField("loop",       TypeString,  Offset(loop_string,   afxPathData),
     "...");
     "...");
-  addField("mult",       TypeF32,     Offset(mult,          afxPathData),
+  addFieldV("mult", TypeRangedF32,     Offset(mult,          afxPathData), &CommonValidators::F32Range,
     "...");
     "...");
-  addField("delay",      TypeF32,     Offset(delay,         afxPathData),
+  addFieldV("delay", TypeRangedF32,     Offset(delay,         afxPathData), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("lifetime",   TypeF32,     Offset(lifetime,      afxPathData),
+  addFieldV("lifetime",   TypeRangedF32,     Offset(lifetime,      afxPathData), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("timeOffset", TypeF32,     Offset(time_offset,   afxPathData),
+  addFieldV("timeOffset", TypeRangedF32,     Offset(time_offset,   afxPathData), &CommonValidators::F32Range,
     "...");
     "...");
   addField("reverse",    TypeBool,    Offset(reverse,       afxPathData),
   addField("reverse",    TypeBool,    Offset(reverse,       afxPathData),
     "...");
     "...");

+ 1 - 1
Engine/source/afx/xm/afxXM_AltitudeConform.cpp

@@ -109,7 +109,7 @@ afxXM_AltitudeConformData::afxXM_AltitudeConformData(const afxXM_AltitudeConform
 void afxXM_AltitudeConformData::initPersistFields()
 void afxXM_AltitudeConformData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("height",              TypeF32,      Offset(height, afxXM_AltitudeConformData),
+  addFieldV("height",              TypeRangedF32,      Offset(height, afxXM_AltitudeConformData), &CommonValidators::F32Range,
     "...");
     "...");
   addField("conformToTerrain",    TypeBool,     Offset(do_terrain, afxXM_AltitudeConformData),
   addField("conformToTerrain",    TypeBool,     Offset(do_terrain, afxXM_AltitudeConformData),
     "...");
     "...");

+ 1 - 1
Engine/source/afx/xm/afxXM_BoxAdapt.cpp

@@ -99,7 +99,7 @@ afxXM_BoxAdaptData::afxXM_BoxAdaptData(const afxXM_BoxAdaptData& other, bool tem
 void afxXM_BoxAdaptData::initPersistFields()
 void afxXM_BoxAdaptData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("scaleFactor",     TypeF32,        Offset(scale_factor, afxXM_BoxAdaptData),
+  addFieldV("scaleFactor",     TypeRangedF32,        Offset(scale_factor, afxXM_BoxAdaptData), &CommonValidators::PositiveFloat,
     "...");
     "...");
   addField("dimensionRange",  TypePoint2F,    Offset(dim_range, afxXM_BoxAdaptData),
   addField("dimensionRange",  TypePoint2F,    Offset(dim_range, afxXM_BoxAdaptData),
     "...");
     "...");

+ 1 - 1
Engine/source/afx/xm/afxXM_Freeze.cpp

@@ -163,7 +163,7 @@ void afxXM_FreezeData::initPersistFields()
    docsURL;
    docsURL;
   addField("mask",  TypeS32,    Offset(mask, afxXM_FreezeData),
   addField("mask",  TypeS32,    Offset(mask, afxXM_FreezeData),
     "...");
     "...");
-  addField("delay", TypeF32,    Offset(delay, afxXM_FreezeData),
+  addFieldV("delay", TypeRangedF32,    Offset(delay, afxXM_FreezeData), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();

+ 1 - 1
Engine/source/afx/xm/afxXM_GroundConform.cpp

@@ -101,7 +101,7 @@ afxXM_GroundConformData::afxXM_GroundConformData(const afxXM_GroundConformData&
 void afxXM_GroundConformData::initPersistFields()
 void afxXM_GroundConformData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("height",              TypeF32,      Offset(height, afxXM_GroundConformData),
+  addFieldV("height", TypeRangedF32,      Offset(height, afxXM_GroundConformData), &CommonValidators::F32Range,
     "...");
     "...");
   addField("conformToTerrain",    TypeBool,     Offset(do_terrain, afxXM_GroundConformData),
   addField("conformToTerrain",    TypeBool,     Offset(do_terrain, afxXM_GroundConformData),
     "...");
     "...");

+ 1 - 1
Engine/source/afx/xm/afxXM_Oscillate.cpp

@@ -166,7 +166,7 @@ void afxXM_OscillateData::initPersistFields()
     "...");
     "...");
   addField("max",                 TypePoint3F,  Offset(max,   afxXM_OscillateData),
   addField("max",                 TypePoint3F,  Offset(max,   afxXM_OscillateData),
     "...");
     "...");
-  addField("speed",               TypeF32,      Offset(speed, afxXM_OscillateData),
+  addFieldV("speed",               TypeRangedF32,      Offset(speed, afxXM_OscillateData), &CommonValidators::PositiveFloat,
     "...");
     "...");
   addField("axis",                TypePoint3F,  Offset(axis,  afxXM_OscillateData),
   addField("axis",                TypePoint3F,  Offset(axis,  afxXM_OscillateData),
     "...");
     "...");

+ 1 - 1
Engine/source/afx/xm/afxXM_OscillateZodiacColor.cpp

@@ -94,7 +94,7 @@ void afxXM_OscillateZodiacColorData::initPersistFields()
     "...");
     "...");
   addField("colorB",              TypeColorF,   Offset(color_b,   afxXM_OscillateZodiacColorData),
   addField("colorB",              TypeColorF,   Offset(color_b,   afxXM_OscillateZodiacColorData),
     "...");
     "...");
-  addField("speed",               TypeF32,      Offset(speed, afxXM_OscillateZodiacColorData),
+  addFieldV("speed",               TypeRangedF32,      Offset(speed, afxXM_OscillateZodiacColorData), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();

+ 4 - 4
Engine/source/afx/xm/afxXM_RandomRot.cpp

@@ -109,13 +109,13 @@ void afxXM_RandomRotData::initPersistFields()
    docsURL;
    docsURL;
   addField("axis",      TypePoint3F,  Offset(axis, afxXM_RandomRotData),
   addField("axis",      TypePoint3F,  Offset(axis, afxXM_RandomRotData),
     "...");
     "...");
-  addField("thetaMin",  TypeF32,      Offset(theta_min, afxXM_RandomRotData),
+  addFieldV("thetaMin", TypeRangedF32,      Offset(theta_min, afxXM_RandomRotData), &CommonValidators::PosDegreeRangeHalf,
     "...");
     "...");
-  addField("thetaMax",  TypeF32,      Offset(theta_max, afxXM_RandomRotData),
+  addFieldV("thetaMax", TypeRangedF32,      Offset(theta_max, afxXM_RandomRotData), &CommonValidators::PosDegreeRangeHalf,
     "...");
     "...");
-  addField("phiMin",    TypeF32,      Offset(phi_min, afxXM_RandomRotData),
+  addFieldV("phiMin", TypeRangedF32,      Offset(phi_min, afxXM_RandomRotData), &CommonValidators::PosDegreeRange,
     "...");
     "...");
-  addField("phiMax",    TypeF32,      Offset(phi_max, afxXM_RandomRotData),
+  addFieldV("phiMax", TypeRangedF32,      Offset(phi_max, afxXM_RandomRotData), &CommonValidators::PosDegreeRange,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();

+ 1 - 1
Engine/source/afx/xm/afxXM_Shockwave.cpp

@@ -103,7 +103,7 @@ afxXM_ShockwaveData::afxXM_ShockwaveData(const afxXM_ShockwaveData& other, bool
 void afxXM_ShockwaveData::initPersistFields()
 void afxXM_ShockwaveData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("rate",      TypeF32,      Offset(rate, afxXM_ShockwaveData),
+  addFieldV("rate",      TypeRangedF32,      Offset(rate, afxXM_ShockwaveData), &CommonValidators::PositiveFloat,
     "...");
     "...");
   addField("aimZOnly",  TypeBool,     Offset(aim_z_only, afxXM_ShockwaveData),
   addField("aimZOnly",  TypeBool,     Offset(aim_z_only, afxXM_ShockwaveData),
     "...");
     "...");

+ 4 - 4
Engine/source/afx/xm/afxXM_Spin.cpp

@@ -122,13 +122,13 @@ void afxXM_SpinData::initPersistFields()
    docsURL;
    docsURL;
   addField("spinAxis",            TypePoint3F,  Offset(spin_axis, afxXM_SpinData),
   addField("spinAxis",            TypePoint3F,  Offset(spin_axis, afxXM_SpinData),
     "...");
     "...");
-  addField("spinAngle",           TypeF32,      Offset(spin_angle, afxXM_SpinData),
+  addFieldV("spinAngle",           TypeRangedF32,      Offset(spin_angle, afxXM_SpinData), &CommonValidators::DegreeRange,
     "...");
     "...");
-  addField("spinAngleVariance",   TypeF32,      Offset(spin_angle_var, afxXM_SpinData),
+  addFieldV("spinAngleVariance", TypeRangedF32,      Offset(spin_angle_var, afxXM_SpinData), &CommonValidators::DegreeRange,
     "...");
     "...");
-  addField("spinRate",            TypeF32,      Offset(spin_rate, afxXM_SpinData),
+  addFieldV("spinRate", TypeRangedF32,      Offset(spin_rate, afxXM_SpinData), &CommonValidators::DegreeRange,
     "...");
     "...");
-  addField("spinRateVariance",    TypeF32,      Offset(spin_rate_var, afxXM_SpinData),
+  addFieldV("spinRateVariance", TypeRangedF32,      Offset(spin_rate_var, afxXM_SpinData), &CommonValidators::DegreeRange,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();

+ 1 - 1
Engine/source/afx/xm/afxXM_VelocityOffset.cpp

@@ -166,7 +166,7 @@ afxXM_VelocityOffsetData::afxXM_VelocityOffsetData(const afxXM_VelocityOffsetDat
 void afxXM_VelocityOffsetData::initPersistFields()
 void afxXM_VelocityOffsetData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("offsetFactor",    TypeF32,      Offset(offset_factor, afxXM_VelocityOffsetData),
+  addFieldV("offsetFactor",    TypeRangedF32,      Offset(offset_factor, afxXM_VelocityOffsetData), &CommonValidators::F32Range,
     "...");
     "...");
   addField("offsetPos2",      TypeBool,     Offset(offset_pos2, afxXM_VelocityOffsetData),
   addField("offsetPos2",      TypeBool,     Offset(offset_pos2, afxXM_VelocityOffsetData),
     "...");
     "...");

+ 9 - 9
Engine/source/afx/xm/afxXM_WaveBase.cpp

@@ -151,28 +151,28 @@ void afxXM_WaveBaseData::initPersistFields()
   addField("op",            TYPEID< afxXM_WaveBaseData::WaveOpType >(),    Offset(op, afxXM_WaveBaseData),
   addField("op",            TYPEID< afxXM_WaveBaseData::WaveOpType >(),    Offset(op, afxXM_WaveBaseData),
     "...");
     "...");
 
 
-  addField("speed",         TypeF32,      Offset(speed, afxXM_WaveBaseData), 
+  addFieldV("speed",         TypeRangedF32,      Offset(speed, afxXM_WaveBaseData), &CommonValidators::PositiveFloat,
     "waves per second");
     "waves per second");
-  addField("speedVariance", TypeF32,      Offset(speed_vari, afxXM_WaveBaseData),
+  addFieldV("speedVariance", TypeRangedF32,      Offset(speed_vari, afxXM_WaveBaseData), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("acceleration",  TypeF32,      Offset(accel, afxXM_WaveBaseData),
+  addFieldV("acceleration", TypeRangedF32,      Offset(accel, afxXM_WaveBaseData), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("phaseShift",    TypeF32,      Offset(phase_shift, afxXM_WaveBaseData),
+  addFieldV("phaseShift", TypeRangedF32,      Offset(phase_shift, afxXM_WaveBaseData), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("dutyCycle",     TypeF32,      Offset(duty_cycle, afxXM_WaveBaseData),
+  addFieldV("dutyCycle", TypeRangedF32,      Offset(duty_cycle, afxXM_WaveBaseData), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("dutyShift",     TypeF32,      Offset(duty_shift, afxXM_WaveBaseData),
+  addFieldV("dutyShift", TypeRangedF32,      Offset(duty_shift, afxXM_WaveBaseData), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("offDutyT",      TypeF32,      Offset(off_duty_t, afxXM_WaveBaseData),
+  addFieldV("offDutyT", TypeRangedF32,      Offset(off_duty_t, afxXM_WaveBaseData), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   addField("wavesPerPulse", TypeByteRange2,      Offset(waves_per_pulse, afxXM_WaveBaseData),
   addField("wavesPerPulse", TypeByteRange2,      Offset(waves_per_pulse, afxXM_WaveBaseData),
     "...");
     "...");
   addField("wavesPerRest",  TypeByteRange2,      Offset(waves_per_rest, afxXM_WaveBaseData),
   addField("wavesPerRest",  TypeByteRange2,      Offset(waves_per_rest, afxXM_WaveBaseData),
     "...");
     "...");
-  addField("restDuration",          TypeF32,      Offset(rest_dur, afxXM_WaveBaseData),
+  addFieldV("restDuration", TypeRangedF32,      Offset(rest_dur, afxXM_WaveBaseData), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("restDurationVariance",  TypeF32,      Offset(rest_dur_vari, afxXM_WaveBaseData),
+  addFieldV("restDurationVariance", TypeRangedF32,      Offset(rest_dur_vari, afxXM_WaveBaseData), &CommonValidators::PositiveFloat,
     "...");
     "...");
 
 
   addField("axis",          TypePoint3F,  Offset(axis, afxXM_WaveBaseData),
   addField("axis",          TypePoint3F,  Offset(axis, afxXM_WaveBaseData),

+ 5 - 5
Engine/source/afx/xm/afxXfmMod.cpp

@@ -215,19 +215,19 @@ F32 afxXM_WeightedBaseData::getWeightFactor() const
 void afxXM_WeightedBaseData::initPersistFields()
 void afxXM_WeightedBaseData::initPersistFields()
 {
 {
    docsURL;
    docsURL;
-  addField("delay",         TypeF32,      Offset(delay,         afxXM_WeightedBaseData),
+  addFieldV("delay", TypeRangedF32,      Offset(delay,         afxXM_WeightedBaseData), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("lifetime",      TypeF32,      Offset(lifetime,      afxXM_WeightedBaseData),
+  addFieldV("lifetime",      TypeRangedF32,      Offset(lifetime,      afxXM_WeightedBaseData), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("fadeInTime",    TypeF32,      Offset(fade_in_time,  afxXM_WeightedBaseData),
+  addFieldV("fadeInTime", TypeRangedF32,      Offset(fade_in_time,  afxXM_WeightedBaseData), &CommonValidators::PositiveFloat,
     "...");
     "...");
-  addField("fadeOutTime",   TypeF32,      Offset(fade_out_time, afxXM_WeightedBaseData),
+  addFieldV("fadeOutTime", TypeRangedF32,      Offset(fade_out_time, afxXM_WeightedBaseData), &CommonValidators::PositiveFloat,
     "...");
     "...");
   addField("fadeInEase",    TypePoint2F,  Offset(fadein_ease,   afxXM_WeightedBaseData),
   addField("fadeInEase",    TypePoint2F,  Offset(fadein_ease,   afxXM_WeightedBaseData),
     "...");
     "...");
   addField("fadeOutEase",   TypePoint2F,  Offset(fadeout_ease,  afxXM_WeightedBaseData),
   addField("fadeOutEase",   TypePoint2F,  Offset(fadeout_ease,  afxXM_WeightedBaseData),
     "...");
     "...");
-  addField("lifetimeBias",  TypeF32,      Offset(life_bias,     afxXM_WeightedBaseData),
+  addFieldV("lifetimeBias", TypeRangedF32,      Offset(life_bias,     afxXM_WeightedBaseData), &CommonValidators::F32Range,
     "...");
     "...");
 
 
   Parent::initPersistFields();
   Parent::initPersistFields();

+ 8 - 8
Engine/source/environment/VolumetricFog.cpp

@@ -174,22 +174,22 @@ void VolumetricFog::initPersistFields()
    addGroup("VolumetricFogData");
    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), 
+   addFieldV("FogDensity", TypeRangedF32, Offset(mFogDensity, VolumetricFog), &CommonValidators::PositiveFloat,
       "Overal fog density value (0 disables the fog).");
       "Overal fog density value (0 disables the fog).");
    addField("IgnoreWater", TypeBool, Offset(mIgnoreWater, VolumetricFog), 
    addField("IgnoreWater", TypeBool, Offset(mIgnoreWater, VolumetricFog), 
       "Set to true if volumetric fog should continue while submerged.");
       "Set to true if volumetric fog should continue while submerged.");
-   addField("MinSize", TypeF32, Offset(mMinDisplaySize, VolumetricFog), 
+   addFieldV("MinSize", TypeRangedF32, Offset(mMinDisplaySize, VolumetricFog), &CommonValidators::PositiveFloat,
       "Min size (in pixels) for fog to be rendered.");
       "Min size (in pixels) for fog to be rendered.");
-   addField("FadeSize", TypeF32, Offset(mFadeSize, VolumetricFog), 
+   addFieldV("FadeSize", TypeRangedF32, Offset(mFadeSize, VolumetricFog), &CommonValidators::PositiveFloat,
       "Object size in pixels at which the FX-fading kicks in (0 disables fading).");
       "Object size in pixels at which the FX-fading kicks in (0 disables fading).");
    endGroup("VolumetricFogData");
    endGroup("VolumetricFogData");
 
 
    addGroup("VolumetricFogModulation");
    addGroup("VolumetricFogModulation");
    INITPERSISTFIELD_IMAGEASSET(Texture, VolumetricFog, "A texture which contains Fogdensity modulator in the red channel and color with 1-green channel. No texture disables modulation.");
    INITPERSISTFIELD_IMAGEASSET(Texture, VolumetricFog, "A texture which contains Fogdensity modulator in the red channel and color with 1-green channel. No texture disables modulation.");
 
 
-   addField("tiles", TypeF32, Offset(mTexTiles, VolumetricFog), 
+   addFieldV("tiles", TypeRangedF32, Offset(mTexTiles, VolumetricFog), &CommonValidators::PositiveFloat,
       "How many times the texture is mapped to the object.");
       "How many times the texture is mapped to the object.");
-   addField("modStrength", TypeF32, Offset(mStrength, VolumetricFog),
+   addFieldV("modStrength", TypeRangedF32, Offset(mStrength, VolumetricFog), &CommonValidators::PositiveFloat,
       "Overall strength of the density modulation (0 disables modulation).");
       "Overall strength of the density modulation (0 disables modulation).");
    addField("PrimSpeed", TypePoint2F, Offset(mSpeed1, VolumetricFog),
    addField("PrimSpeed", TypePoint2F, Offset(mSpeed1, VolumetricFog),
       "Overall primary speed of the density modulation (x-speed(u) y-speed(v))");
       "Overall primary speed of the density modulation (x-speed(u) y-speed(v))");
@@ -200,18 +200,18 @@ void VolumetricFog::initPersistFields()
    addGroup("Reflections");
    addGroup("Reflections");
    addField("Reflectable", TypeBool, Offset(mReflect, VolumetricFog), 
    addField("Reflectable", TypeBool, Offset(mReflect, VolumetricFog), 
       "Set to true if volumetric fog should be reflected.");
       "Set to true if volumetric fog should be reflected.");
-   addField("ReflectStrength", TypeF32, Offset(mFogReflStrength, VolumetricFog), 
+   addFieldV("ReflectStrength", TypeRangedF32, Offset(mFogReflStrength, VolumetricFog), &CommonValidators::NormalizedFloat,
       "Strength of the reflections (0 disables the fog).");
       "Strength of the reflections (0 disables the fog).");
    endGroup("Reflections");
    endGroup("Reflections");
 
 
    addGroup("PostFX");
    addGroup("PostFX");
    addField("useGlow", TypeBool, Offset(mUseGlow, VolumetricFog), 
    addField("useGlow", TypeBool, Offset(mUseGlow, VolumetricFog), 
       "Set to true if volumetric fog should use glow PostFX.");
       "Set to true if volumetric fog should use glow PostFX.");
-   addField("glowStrength", TypeF32, Offset(mGlowStrength, VolumetricFog),
+   addFieldV("glowStrength", TypeRangedF32, Offset(mGlowStrength, VolumetricFog), &CommonValidators::PositiveFloat,
       "Overall strength of the glow PostFX.");
       "Overall strength of the glow PostFX.");
    addField("modLightRay", TypeBool, Offset(mModifLightRays, VolumetricFog), 
    addField("modLightRay", TypeBool, Offset(mModifLightRays, VolumetricFog), 
       "Set to true if volumetric fog should modify the brightness of the Lightrays.");
       "Set to true if volumetric fog should modify the brightness of the Lightrays.");
-   addField("lightRayMod", TypeF32, Offset(mLightRayMod, VolumetricFog),
+   addFieldV("lightRayMod", TypeRangedF32, Offset(mLightRayMod, VolumetricFog), &CommonValidators::PositiveFloat,
       "Modifier for LightRay PostFX when inside Fog.");
       "Modifier for LightRay PostFX when inside Fog.");
    endGroup("PostFX");
    endGroup("PostFX");
 }
 }

+ 3 - 3
Engine/source/environment/basicClouds.cpp

@@ -179,19 +179,19 @@ void BasicClouds::initPersistFields()
 
 
          INITPERSISTFIELD_IMAGEASSET_ARRAY(Texture, TEX_COUNT, BasicClouds, "Texture for this layer.");
          INITPERSISTFIELD_IMAGEASSET_ARRAY(Texture, TEX_COUNT, BasicClouds, "Texture for this layer.");
 
 
-         addField( "texScale", TypeF32, Offset( mTexScale, BasicClouds ), TEX_COUNT,
+         addFieldV( "texScale", TypeRangedF32, Offset( mTexScale, BasicClouds ), &CommonValidators::PositiveFloat, TEX_COUNT,
             "Texture repeat for this layer." );
             "Texture repeat for this layer." );
 
 
          addField( "texDirection", TypePoint2F, Offset( mTexDirection, BasicClouds ), TEX_COUNT,
          addField( "texDirection", TypePoint2F, Offset( mTexDirection, BasicClouds ), TEX_COUNT,
             "Texture scroll direction for this layer, relative to the world axis." );
             "Texture scroll direction for this layer, relative to the world axis." );
 
 
-         addField( "texSpeed", TypeF32, Offset( mTexSpeed, BasicClouds ), TEX_COUNT,
+         addFieldV( "texSpeed", TypeRangedF32, Offset( mTexSpeed, BasicClouds ), &CommonValidators::PositiveFloat, TEX_COUNT,
             "Texture scroll speed for this layer." );   
             "Texture scroll speed for this layer." );   
 
 
          addField( "texOffset", TypePoint2F, Offset( mTexOffset, BasicClouds ), TEX_COUNT,
          addField( "texOffset", TypePoint2F, Offset( mTexOffset, BasicClouds ), TEX_COUNT,
             "UV offset for this layer." );
             "UV offset for this layer." );
 
 
-         addField( "height", TypeF32, Offset( mHeight, BasicClouds ), TEX_COUNT,
+         addFieldV( "height", TypeRangedF32, Offset( mHeight, BasicClouds ), &CommonValidators::F32Range, TEX_COUNT,
             "Abstract number which controls the curvature and height of the dome mesh" );
             "Abstract number which controls the curvature and height of the dome mesh" );
 
 
       endArray( "Layers" );      
       endArray( "Layers" );      

+ 6 - 6
Engine/source/environment/cloudLayer.cpp

@@ -198,13 +198,13 @@ void CloudLayer::initPersistFields()
       
       
       addArray( "Textures", TEX_COUNT );
       addArray( "Textures", TEX_COUNT );
 
 
-         addField( "texScale", TypeF32, Offset( mTexScale, CloudLayer ), TEX_COUNT,
+         addFieldV( "texScale", TypeRangedF32, Offset( mTexScale, CloudLayer ), &CommonValidators::PositiveFloat, TEX_COUNT,
             "Controls the texture repeat of this slot." );
             "Controls the texture repeat of this slot." );
 
 
          addField( "texDirection", TypePoint2F, Offset( mTexDirection, CloudLayer ), TEX_COUNT,
          addField( "texDirection", TypePoint2F, Offset( mTexDirection, CloudLayer ), TEX_COUNT,
             "Controls the direction this slot scrolls." );
             "Controls the direction this slot scrolls." );
 
 
-         addField( "texSpeed", TypeF32, Offset( mTexSpeed, CloudLayer ), TEX_COUNT,
+         addFieldV( "texSpeed", TypeRangedF32, Offset( mTexSpeed, CloudLayer ), &CommonValidators::PositiveFloat, TEX_COUNT,
             "Controls the speed this slot scrolls." );
             "Controls the speed this slot scrolls." );
 
 
       endArray( "Textures" );
       endArray( "Textures" );
@@ -212,16 +212,16 @@ void CloudLayer::initPersistFields()
       addField( "baseColor", TypeColorF, Offset( mBaseColor, CloudLayer ),
       addField( "baseColor", TypeColorF, Offset( mBaseColor, CloudLayer ),
          "Base cloud color before lighting." );
          "Base cloud color before lighting." );
 
 
-      addField( "exposure", TypeF32, Offset( mExposure, CloudLayer ),
+      addFieldV( "exposure", TypeRangedF32, Offset( mExposure, CloudLayer ), &CommonValidators::PositiveFloat,
          "Brightness scale so CloudLayer can be overblown if desired." );
          "Brightness scale so CloudLayer can be overblown if desired." );
       
       
-      addField( "coverage", TypeF32, Offset( mCoverage, CloudLayer ),
+      addFieldV( "coverage", TypeRangedF32, Offset( mCoverage, CloudLayer ), &CommonValidators::NormalizedFloat,
          "Fraction of sky covered by clouds 0-1." );
          "Fraction of sky covered by clouds 0-1." );
 
 
-      addField( "windSpeed", TypeF32, Offset( mWindSpeed, CloudLayer ),
+      addFieldV( "windSpeed", TypeRangedF32, Offset( mWindSpeed, CloudLayer ), &CommonValidators::NormalizedFloat,
          "Overall scalar to texture scroll speed." );
          "Overall scalar to texture scroll speed." );
 
 
-      addField( "height", TypeF32, Offset( mHeight, CloudLayer ),
+      addFieldV( "height", TypeRangedF32, Offset( mHeight, CloudLayer ), &CommonValidators::F32Range,
          "Abstract number which controls the curvature and height of the dome mesh." );
          "Abstract number which controls the curvature and height of the dome mesh." );
 
 
    endGroup( "CloudLayer" );
    endGroup( "CloudLayer" );

Some files were not shown because too many files changed in this diff