Browse Source

add numerous new validators
as well as inspector support to treat a significant chunk of the codebase as range-clmped values which can take a guisliderbarctrl with a configurable at the validator level fidelity variable
additionally adds a new addfieldV and addprotetedfieldV for further callback validated slider-presented variables
*also* adds an on additional callbacks to the inspector itself, like onPreinspectobject, onPostinspectObject, and onPostInspectorfieldModified
in addition to *that*, adds a new hidefield command to tag a given specific field not to show in inspector

AzaezelX 7 months ago
parent
commit
fa760fa746

+ 106 - 0
Engine/source/console/consoleObject.cpp

@@ -624,6 +624,86 @@ void ConsoleObject::addProtectedField(const char*  in_pFieldname,
    sg_tempFieldList.push_back(f);
    sg_tempFieldList.push_back(f);
 }
 }
 
 
+void ConsoleObject::addProtectedFieldV(const char* in_pFieldname,
+   const U32 in_fieldType,
+   const dsize_t in_fieldOffset,
+   AbstractClassRep::SetDataNotify in_setDataFn,
+   AbstractClassRep::GetDataNotify in_getDataFn,
+   AbstractClassRep::WriteDataNotify in_writeDataFn,
+   TypeValidator* v,
+   const U32 in_elementCount,
+   const char* in_pFieldDocs,
+   U32 flags)
+{
+   AbstractClassRep::Field f;
+   f.pFieldname = StringTable->insert(in_pFieldname);
+
+   if (in_pFieldDocs)
+      f.pFieldDocs = in_pFieldDocs;
+
+   f.type = in_fieldType;
+   f.offset = in_fieldOffset;
+   f.elementCount = in_elementCount;
+   f.validator = v;
+   f.flag = flags;
+
+   f.setDataFn = in_setDataFn;
+   f.getDataFn = in_getDataFn;
+   f.writeDataFn = in_writeDataFn;
+   f.networkMask = 0;
+
+   ConsoleBaseType* conType = ConsoleBaseType::getType(in_fieldType);
+   AssertFatal(conType, "ConsoleObject::addProtectedField - invalid console type");
+   f.table = conType->getEnumTable();
+
+   sg_tempFieldList.push_back(f);
+}
+
+void ConsoleObject::addProtectedFieldV(const char* in_pFieldname,
+   const U32     in_fieldType,
+   const dsize_t in_fieldOffset,
+   AbstractClassRep::SetDataNotify in_setDataFn,
+   AbstractClassRep::GetDataNotify in_getDataFn,
+   TypeValidator* v,
+   const U32 in_elementCount,
+   const char* in_pFieldDocs,
+   U32 flags)
+{
+   addProtectedFieldV(
+      in_pFieldname,
+      in_fieldType,
+      in_fieldOffset,
+      in_setDataFn,
+      in_getDataFn,
+      &defaultProtectedWriteFn,
+      v,
+      in_elementCount,
+      in_pFieldDocs,
+      flags);
+}
+
+void ConsoleObject::addProtectedFieldV(const char* in_pFieldname,
+   const U32     in_fieldType,
+   const dsize_t in_fieldOffset,
+   AbstractClassRep::SetDataNotify in_setDataFn,
+   AbstractClassRep::GetDataNotify in_getDataFn,
+   TypeValidator* v,
+   const char* in_pFieldDocs,
+   U32 flags)
+{
+   addProtectedFieldV(
+      in_pFieldname,
+      in_fieldType,
+      in_fieldOffset,
+      in_setDataFn,
+      in_getDataFn,
+      &defaultProtectedWriteFn,
+      v,
+      1,
+      in_pFieldDocs,
+      flags);
+}
+
 void ConsoleObject::addFieldV(const char*  in_pFieldname,
 void ConsoleObject::addFieldV(const char*  in_pFieldname,
                        const U32 in_fieldType,
                        const U32 in_fieldType,
                        const dsize_t in_fieldOffset,
                        const dsize_t in_fieldOffset,
@@ -648,6 +728,32 @@ void ConsoleObject::addFieldV(const char*  in_pFieldname,
    sg_tempFieldList.push_back(f);
    sg_tempFieldList.push_back(f);
 }
 }
 
 
+void ConsoleObject::addFieldV(const char* in_pFieldname,
+   const U32 in_fieldType,
+   const dsize_t in_fieldOffset,
+   TypeValidator* v,
+   const U32 in_elementCount,
+   const char* in_pFieldDocs)
+{
+   AbstractClassRep::Field f;
+   f.pFieldname = StringTable->insert(in_pFieldname);
+   if (in_pFieldDocs)
+      f.pFieldDocs = in_pFieldDocs;
+   f.type = in_fieldType;
+   f.offset = in_fieldOffset;
+   f.elementCount = 1;
+   f.table = NULL;
+   f.setDataFn = &defaultProtectedSetFn;
+   f.getDataFn = &defaultProtectedGetFn;
+   f.writeDataFn = &defaultProtectedWriteFn;
+   f.elementCount = in_elementCount;
+   f.validator = v;
+   f.networkMask = 0;
+   v->fieldIndex = sg_tempFieldList.size();
+
+   sg_tempFieldList.push_back(f);
+}
+
 void ConsoleObject::addDeprecatedField(const char *fieldName)
 void ConsoleObject::addDeprecatedField(const char *fieldName)
 {
 {
    AbstractClassRep::Field f;
    AbstractClassRep::Field f;

+ 38 - 0
Engine/source/console/consoleObject.h

@@ -945,6 +945,13 @@ public:
       TypeValidator *v,
       TypeValidator *v,
       const char *   in_pFieldDocs = NULL);
       const char *   in_pFieldDocs = NULL);
 
 
+   static void addFieldV(const char* in_pFieldname,
+      const U32      in_fieldType,
+      const dsize_t  in_fieldOffset,
+      TypeValidator* v,
+      const U32     in_elementCount,
+      const char* in_pFieldDocs = NULL);
+
    /// Register a complex protected field.
    /// Register a complex protected field.
    ///
    ///
    /// @param  in_pFieldname     Name of the field.
    /// @param  in_pFieldname     Name of the field.
@@ -998,6 +1005,37 @@ public:
       const char* in_pFieldDocs = NULL,
       const char* in_pFieldDocs = NULL,
       U32 flags = 0);
       U32 flags = 0);
 
 
+
+   static void addProtectedFieldV(const char* in_pFieldname,
+      const U32     in_fieldType,
+      const dsize_t in_fieldOffset,
+      AbstractClassRep::SetDataNotify in_setDataFn,
+      AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
+      AbstractClassRep::WriteDataNotify in_writeDataFn = &defaultProtectedWriteFn,
+      TypeValidator* v  = NULL,
+      const U32     in_elementCount = 1,
+      const char* in_pFieldDocs = NULL,
+      U32 flags = 0);
+
+   static void addProtectedFieldV(const char* in_pFieldname,
+      const U32     in_fieldType,
+      const dsize_t in_fieldOffset,
+      AbstractClassRep::SetDataNotify in_setDataFn,
+      AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
+      TypeValidator* v = NULL,
+      const U32     in_elementCount = 1,
+      const char* in_pFieldDocs = NULL,
+      U32 flags = 0);
+
+   static void addProtectedFieldV(const char* in_pFieldname,
+      const U32     in_fieldType,
+      const dsize_t in_fieldOffset,
+      AbstractClassRep::SetDataNotify in_setDataFn,
+      AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
+      TypeValidator* v = NULL,
+      const char* in_pFieldDocs = NULL,
+      U32 flags = 0);
+
    /// Add a deprecated field.
    /// Add a deprecated field.
    ///
    ///
    /// A deprecated field will always be undefined, even if you assign a value to it. This
    /// A deprecated field will always be undefined, even if you assign a value to it. This

+ 42 - 0
Engine/source/console/consoleTypes.cpp

@@ -473,6 +473,48 @@ ConsoleSetType( TypeF32 )
       Con::printf("(TypeF32) Cannot set multiple args to a single F32.");
       Con::printf("(TypeF32) Cannot set multiple args to a single F32.");
 }
 }
 
 
+//-----------------------------------------------------------------------------
+// TypeRangedF32
+//-----------------------------------------------------------------------------
+ConsoleType(float, TypeRangedF32, F32, "")
+
+ConsoleGetType(TypeRangedF32)
+{
+   static const U32 bufSize = 256;
+   char* returnBuffer = Con::getReturnBuffer(bufSize);
+   dSprintf(returnBuffer, bufSize, "%g", *((F32*)dptr));
+   return returnBuffer;
+}
+ConsoleSetType(TypeRangedF32)
+{
+   if (argc == 1)
+      *((F32*)dptr) = dAtof(argv[0]);
+   else
+      Con::printf("(TypeF32) Cannot set multiple args to a single F32.");
+}
+
+//-----------------------------------------------------------------------------
+// TypeRangedS32
+//-----------------------------------------------------------------------------
+ConsoleType(int, TypeRangedS32, S32, "")
+
+ConsoleGetType(TypeRangedS32)
+{
+   static const U32 bufSize = 512;
+   char* returnBuffer = Con::getReturnBuffer(bufSize);
+   dSprintf(returnBuffer, bufSize, "%d", *((S32*)dptr));
+   return returnBuffer;
+}
+
+ConsoleSetType(TypeRangedS32)
+{
+   if (argc == 1)
+      *((S32*)dptr) = dAtoi(argv[0]);
+   else
+      Con::printf("(TypeRangedS32) Cannot set multiple args to a single S32.");
+}
+
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // TypeF32Vector
 // TypeF32Vector
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 2 - 0
Engine/source/console/consoleTypes.h

@@ -66,9 +66,11 @@ DefineConsoleType( TypeBoolVector, Vector<bool>)
 DefineConsoleType( TypeS8,  S8 )
 DefineConsoleType( TypeS8,  S8 )
 DefineConsoleType( TypeS16, S16)
 DefineConsoleType( TypeS16, S16)
 DefineConsoleType( TypeS32, S32 )
 DefineConsoleType( TypeS32, S32 )
+DefineConsoleType(TypeRangedS32, S32)
 DefineConsoleType( TypeS32Vector, Vector<S32> )
 DefineConsoleType( TypeS32Vector, Vector<S32> )
 DefineConsoleType( TypeF64, F64 )
 DefineConsoleType( TypeF64, F64 )
 DefineConsoleType( TypeF32, F32 )
 DefineConsoleType( TypeF32, F32 )
+DefineConsoleType( TypeRangedF32, F32)
 DefineConsoleType( TypeF32Vector, Vector<F32> )
 DefineConsoleType( TypeF32Vector, Vector<F32> )
 DefineUnmappedConsoleType( TypeString, const char * ) // plain UTF-8 strings are not supported in new interop
 DefineUnmappedConsoleType( TypeString, const char * ) // plain UTF-8 strings are not supported in new interop
 DefineConsoleType( TypeCaseString, const char * )
 DefineConsoleType( TypeCaseString, const char * )

+ 34 - 1
Engine/source/console/typeValidators.cpp

@@ -100,9 +100,42 @@ void Point3NormalizeValidator::validateType(SimObject *object, void *typePtr)
 
 
 namespace CommonValidators
 namespace CommonValidators
 {
 {
-   FRangeValidator PositiveFloat(0.0f, F32_MAX);
+   FRangeValidator F32Range(F32_MIN, F32_MAX, F32_MAX);
+   FRangeValidator DirFloat(-1.0f, 1.0f);
+   FRangeValidator NegDefaultF32(-1.0f, F32_MAX, F32_MAX);
+   FRangeValidator PositiveFloat(0.0f, F32_MAX, F32_MAX);
    FRangeValidator PositiveNonZeroFloat((F32)POINT_EPSILON, F32_MAX);
    FRangeValidator PositiveNonZeroFloat((F32)POINT_EPSILON, F32_MAX);
    FRangeValidator NormalizedFloat(0.0f, 1.0f);
    FRangeValidator NormalizedFloat(0.0f, 1.0f);
+
+   FRangeValidator F32_8BitPercent(0.0f, 1.0f, 1 << 8);
+   FRangeValidator F32_16BitPercent(0.0f, 1.0f, 1 << 16);
+   FRangeValidator ValidSlopeAngle(0.0f, 89.9f, 89.9f);
+   FRangeValidator CornerAngle(0.0f, 90.0f, 90.0f);
+
+   IRangeValidator S32Range(S32_MIN, S32_MAX);
+   IRangeValidator DirInt(-1,1);
+   IRangeValidator NegDefaultInt(-1, S32_MAX);
+   IRangeValidator PositiveInt(0, S32_MAX);
+   IRangeValidator NaturalNumber(1, S32_MAX);
+   //see "T3D/gameBase/processList.h" for TickMs = 32
+   IRangeValidator MSTickRange(32, S32_MAX);
+
+   IRangeValidator S32_8BitCap(0, 1 << 8);
+   IRangeValidator S32_16BitCap(0, 1 << 16);
    Point3NormalizeValidator NormalizedPoint3(1.0f);
    Point3NormalizeValidator NormalizedPoint3(1.0f);
+
+   FRangeValidator DegreeRange(-360.0f, 360.0f, 720.0f);
+   FRangeValidator PosDegreeRange(0.0f, 360.0f, 360.0f);
+   FRangeValidator DegreeRangeHalf(-180.0f, 180.0f, 360.0f);
+   FRangeValidator PosDegreeRangeHalf(0.0f, 180.0f, 180.0f);
+   FRangeValidator DegreeRangeQuarter(-90.0f, 90.0f, 180.0f);
+   FRangeValidator PosDegreeRangeQuarter(0.0f, 90.0f, 90.0f);
+
+   IRangeValidator S32_DegreeRange(-360, 360);
+   IRangeValidator S32_PosDegreeRange(0, 360);
+   IRangeValidator S32_DegreeRangeHalf(-180, 180);
+   IRangeValidator S32_PosDegreeRangeHalf(0, 180);
+   IRangeValidator S32_DegreeRangeQuarter(-90, 90);
+   IRangeValidator S32_PosDegreeRangeQuarter(0, 90);
 };
 };
 
 

+ 43 - 6
Engine/source/console/typeValidators.h

@@ -46,31 +46,35 @@ class TypeValidator
 /// Floating point min/max range validator
 /// Floating point min/max range validator
 class FRangeValidator : public TypeValidator
 class FRangeValidator : public TypeValidator
 {
 {
-   F32 minV, maxV;
+   F32 minV, maxV, mFidelity;
 public:
 public:
-   FRangeValidator(F32 minValue, F32 maxValue)
+   FRangeValidator(F32 minValue, F32 maxValue, F32 fidelity = 0.0f)
    {
    {
       minV = minValue;
       minV = minValue;
       maxV = maxValue;
       maxV = maxValue;
+      mFidelity = fidelity;
    }
    }
    void validateType(SimObject *object, void *typePtr) override;
    void validateType(SimObject *object, void *typePtr) override;
    F32 getMin() { return minV; };
    F32 getMin() { return minV; };
    F32 getMax() { return maxV; };
    F32 getMax() { return maxV; };
+   F32 getFidelity() { return mFidelity; };
 };
 };
 
 
 /// Signed integer min/max range validator
 /// Signed integer min/max range validator
 class IRangeValidator : public TypeValidator
 class IRangeValidator : public TypeValidator
 {
 {
-   S32 minV, maxV;
+   S32 minV, maxV, mFidelity;
 public:
 public:
-   IRangeValidator(S32 minValue, S32 maxValue)
+   IRangeValidator(S32 minValue, S32 maxValue, S32 fidelity = 1)
    {
    {
       minV = minValue;
       minV = minValue;
       maxV = maxValue;
       maxV = maxValue;
+      mFidelity = fidelity;
    }
    }
    void validateType(SimObject *object, void *typePtr) override;
    void validateType(SimObject *object, void *typePtr) override;
-   F32 getMin() { return minV; };
-   F32 getMax() { return maxV; };
+   S32 getMin() { return minV; };
+   S32 getMax() { return maxV; };
+   S32 getFidelity() { return mFidelity; };
 };
 };
 
 
 /// Scaled integer field validator
 /// Scaled integer field validator
@@ -89,6 +93,9 @@ public:
       factor = scaleFactor;
       factor = scaleFactor;
    }
    }
    void validateType(SimObject *object, void *typePtr) override;
    void validateType(SimObject *object, void *typePtr) override;
+   S32 getMin() { return minV; };
+   S32 getMax() { return maxV; };
+   S32 getScaleFactor() { return factor; };
 };
 };
 
 
 /// Vector normalization validator
 /// Vector normalization validator
@@ -104,12 +111,42 @@ public:
 namespace CommonValidators
 namespace CommonValidators
 {
 {
    // Floats
    // Floats
+   extern FRangeValidator F32Range;
+   extern FRangeValidator DirFloat;
+   extern FRangeValidator NegDefaultF32;   
    extern FRangeValidator PositiveFloat;
    extern FRangeValidator PositiveFloat;
    extern FRangeValidator PositiveNonZeroFloat;
    extern FRangeValidator PositiveNonZeroFloat;
    extern FRangeValidator NormalizedFloat;
    extern FRangeValidator NormalizedFloat;
+   extern FRangeValidator F32_8BitPercent;
+   extern FRangeValidator F32_16BitPercent;
+   extern FRangeValidator ValidSlopeAngle;
+   extern FRangeValidator CornerAngle;
 
 
+   extern IRangeValidator S32Range;
+   extern IRangeValidator DirInt;
+   extern IRangeValidator NegDefaultInt;
+   extern IRangeValidator PositiveInt;
+   extern IRangeValidator NaturalNumber;
+   extern IRangeValidator MSTickRange;
+   extern IRangeValidator S32_8BitCap;
+   extern IRangeValidator S32_16BitCap;
    // Other Math Types
    // Other Math Types
    extern Point3NormalizeValidator NormalizedPoint3;
    extern Point3NormalizeValidator NormalizedPoint3;
+
+   // orbital mechanics
+   extern FRangeValidator DegreeRange;
+   extern FRangeValidator PosDegreeRange;
+   extern FRangeValidator DegreeRangeHalf;
+   extern FRangeValidator PosDegreeRangeHalf;
+   extern FRangeValidator DegreeRangeQuarter;
+   extern FRangeValidator PosDegreeRangeQuarter;
+
+   extern IRangeValidator S32_DegreeRange;
+   extern IRangeValidator S32_PosDegreeRange;
+   extern IRangeValidator S32_DegreeRangeHalf;
+   extern IRangeValidator S32_PosDegreeRangeHalf;
+   extern IRangeValidator S32_DegreeRangeQuarter;
+   extern IRangeValidator S32_PosDegreeRangeQuarter;
 };
 };
 
 
 #endif
 #endif

+ 32 - 5
Engine/source/gui/editor/guiInspector.cpp

@@ -28,6 +28,7 @@
 #include "gui/editor/inspector/dynamicGroup.h"
 #include "gui/editor/inspector/dynamicGroup.h"
 #include "gui/containers/guiScrollCtrl.h"
 #include "gui/containers/guiScrollCtrl.h"
 #include "gui/editor/inspector/customField.h"
 #include "gui/editor/inspector/customField.h"
+#include "console/typeValidators.h"
 
 
 IMPLEMENT_CONOBJECT(GuiInspector);
 IMPLEMENT_CONOBJECT(GuiInspector);
 
 
@@ -38,6 +39,12 @@ ConsoleDocClass( GuiInspector,
 );
 );
 
 
 
 
+IMPLEMENT_CALLBACK(GuiInspector, onPreInspectObject, void, (SimObject* object), (object),
+   "Called prior to inspecting a new object.\n");
+
+IMPLEMENT_CALLBACK(GuiInspector, onPostInspectObject, void, (SimObject* object), (object),
+   "Called after inspecting a new object.\n");
+
 //#define DEBUG_SPEW
 //#define DEBUG_SPEW
 
 
 
 
@@ -71,7 +78,7 @@ void GuiInspector::initPersistFields()
    docsURL;
    docsURL;
    addGroup( "Inspector" );
    addGroup( "Inspector" );
    
    
-      addField( "dividerMargin", TypeS32, Offset( mDividerMargin, GuiInspector ) );
+      addFieldV( "dividerMargin", TypeRangedS32, Offset( mDividerMargin, GuiInspector ), &CommonValidators::PositiveInt);
 
 
       addField( "groupFilters", TypeRealString, Offset( mGroupFilters, GuiInspector ), 
       addField( "groupFilters", TypeRealString, Offset( mGroupFilters, GuiInspector ), 
          "Specify groups that should be shown or not. Specifying 'shown' implicitly does 'not show' all other groups. Example string: +name -otherName" );
          "Specify groups that should be shown or not. Specifying 'shown' implicitly does 'not show' all other groups. Example string: +name -otherName" );
@@ -79,7 +86,7 @@ void GuiInspector::initPersistFields()
       addField( "showCustomFields", TypeBool, Offset( mShowCustomFields, GuiInspector ),
       addField( "showCustomFields", TypeBool, Offset( mShowCustomFields, GuiInspector ),
          "If false the custom fields Name, Id, and Source Class will not be shown." );
          "If false the custom fields Name, Id, and Source Class will not be shown." );
 
 
-      addField("forcedArrayIndex", TypeS32, Offset(mForcedArrayIndex, GuiInspector));
+      addFieldV("forcedArrayIndex", TypeRangedS32, Offset(mForcedArrayIndex, GuiInspector), &CommonValidators::NegDefaultInt);
 
 
       addField("searchText", TypeString, Offset(mSearchText, GuiInspector), "A string that, if not blank, is used to filter shown fields");
       addField("searchText", TypeString, Offset(mSearchText, GuiInspector), "A string that, if not blank, is used to filter shown fields");
    endGroup( "Inspector" );
    endGroup( "Inspector" );
@@ -325,11 +332,14 @@ bool GuiInspector::isInspectingObject( SimObject* object )
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 void GuiInspector::inspectObject( SimObject *object )
 void GuiInspector::inspectObject( SimObject *object )
-{  
+{
+   onPreInspectObject_callback((mTargets.size() > 1)? mTargets[0] : NULL);
+
    if( mTargets.size() > 1 || !isInspectingObject( object ) )
    if( mTargets.size() > 1 || !isInspectingObject( object ) )
       clearInspectObjects();
       clearInspectObjects();
          
          
    addInspectObject( object );
    addInspectObject( object );
+   onPostInspectObject_callback(object);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -349,7 +359,8 @@ void GuiInspector::clearInspectObjects()
 void GuiInspector::addInspectObject( SimObject* object, bool autoSync )
 void GuiInspector::addInspectObject( SimObject* object, bool autoSync )
 {   
 {   
    // If we are already inspecting the object, just update the groups.
    // If we are already inspecting the object, just update the groups.
-   
+
+   onPreInspectObject_callback((mTargets.size() > 1) ? mTargets[0] : NULL);
    if( isInspectingObject( object ) )
    if( isInspectingObject( object ) )
    {
    {
       #ifdef DEBUG_SPEW
       #ifdef DEBUG_SPEW
@@ -379,6 +390,7 @@ void GuiInspector::addInspectObject( SimObject* object, bool autoSync )
    
    
 	if( autoSync )
 	if( autoSync )
 		refresh();
 		refresh();
+   onPostInspectObject_callback(object);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -629,7 +641,7 @@ void GuiInspector::refresh()
                GuiInspectorGroup *newGroup = new GuiInspectorGroup( itr->pGroupname, this );
                GuiInspectorGroup *newGroup = new GuiInspectorGroup( itr->pGroupname, this );
                newGroup->setForcedArrayIndex(mForcedArrayIndex);
                newGroup->setForcedArrayIndex(mForcedArrayIndex);
 
 
-			   newGroup->registerObject();
+			      newGroup->registerObject();
                if( !newGroup->getNumFields() )
                if( !newGroup->getNumFields() )
                {
                {
                   #ifdef DEBUG_SPEW
                   #ifdef DEBUG_SPEW
@@ -995,6 +1007,21 @@ DefineEngineMethod(GuiInspector, findExistentGroup, S32, (const char* groupName)
    return group ? group->getId() : 0;
    return group ? group->getId() : 0;
 }
 }
 
 
+DefineEngineMethod(GuiInspector, getInspectedGroupCount, S32, (), ,
+   "How many inspected groups there are.\n"
+   "@return how many inspected groups there are")
+{
+   return object->getGroups().size();
+}
+
+DefineEngineMethod(GuiInspector, getInspectedGroup, GuiInspectorGroup*, (S32 key), ,
+   "Finds an existing GuiInspectorGroup if it exists and returns it's Id.\n"
+   "@param key nth group out of the list of groups."
+   "@return id of the GuiInspectorGroup")
+{
+   return object->getGroups()[key];
+}
+
 DefineEngineMethod(GuiInspector, removeGroup, void, (const char* groupName), ,
 DefineEngineMethod(GuiInspector, removeGroup, void, (const char* groupName), ,
    "Finds an existing GuiInspectorGroup if it exists removes it.\n"
    "Finds an existing GuiInspectorGroup if it exists removes it.\n"
    "@param groupName Name of the new GuiInspectorGroup to find in this Inspector.")
    "@param groupName Name of the new GuiInspectorGroup to find in this Inspector.")

+ 3 - 1
Engine/source/gui/editor/guiInspector.h

@@ -174,7 +174,9 @@ public:
    StringTableEntry getSearchText() { return mSearchText; }
    StringTableEntry getSearchText() { return mSearchText; }
 
 
    void setSearchText(StringTableEntry searchText);
    void setSearchText(StringTableEntry searchText);
-
+   Vector<GuiInspectorGroup*> getGroups() { return mGroups; };
+   DECLARE_CALLBACK(void, onPreInspectObject, (SimObject* object) );
+   DECLARE_CALLBACK(void, onPostInspectObject, (SimObject* object) );
 protected:
 protected:
       
       
    typedef Vector< SimObjectPtr< SimObject > > TargetVector;
    typedef Vector< SimObjectPtr< SimObject > > TargetVector;

+ 112 - 1
Engine/source/gui/editor/guiInspectorTypes.cpp

@@ -41,7 +41,7 @@
 #include "math/mEase.h"
 #include "math/mEase.h"
 #include "math/mathTypes.h"
 #include "math/mathTypes.h"
 #include "sim/actionMap.h"
 #include "sim/actionMap.h"
-
+#include "console/typeValidators.h"
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // GuiInspectorTypeMenuBase
 // GuiInspectorTypeMenuBase
@@ -1350,6 +1350,117 @@ void GuiInspectorTypeS32::setValue( StringTableEntry newValue )
       ctrl->setText( newValue );
       ctrl->setText( newValue );
 }
 }
 
 
+//-----------------------------------------------------------------------------
+// GuiInspectorTypeRangedF32
+//-----------------------------------------------------------------------------
+IMPLEMENT_CONOBJECT(GuiInspectorTypeRangedF32);
+
+ConsoleDocClass(GuiInspectorTypeRangedF32,
+   "@brief Inspector field type for range-clamped F32\n\n"
+   "Editor use only.\n\n"
+   "@internal"
+);
+
+void GuiInspectorTypeRangedF32::consoleInit()
+{
+   Parent::consoleInit();
+
+   ConsoleBaseType::getType(TypeRangedF32)->setInspectorFieldType("GuiInspectorTypeRangedF32");
+}
+
+GuiControl* GuiInspectorTypeRangedF32::constructEditControl()
+{
+   GuiControl* retCtrl = new GuiTextEditSliderCtrl();
+
+   retCtrl->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
+
+   // Don't forget to register ourselves
+   _registerEditControl(retCtrl);
+
+   char szBuffer[512];
+   dSprintf(szBuffer, 512, "%d.apply(%d.getText());", getId(), retCtrl->getId());
+   retCtrl->setField("AltCommand", szBuffer);
+   FRangeValidator* validator = dynamic_cast<FRangeValidator*>(mField->validator);
+   if (validator)
+   {
+      retCtrl->setField("format", "%g");
+      retCtrl->setField("range", String::ToString("%g %g", validator->getMin(), validator->getMax()));
+      if (validator->getFidelity()>0.0f)
+         retCtrl->setField("increment", String::ToString("%g", (validator->getMax()-validator->getMin())/validator->getFidelity()));
+      else
+         retCtrl->setField("increment", String::ToString("%g", POINT_EPSILON));
+   }
+   return retCtrl;
+}
+
+void GuiInspectorTypeRangedF32::setValue(StringTableEntry newValue)
+{
+   GuiTextEditSliderCtrl* ctrl = dynamic_cast<GuiTextEditSliderCtrl*>(mEdit);
+   if (ctrl != NULL)
+      ctrl->setText(newValue);
+}
+
+//-----------------------------------------------------------------------------
+// GuiInspectorTypeRangedS32
+//-----------------------------------------------------------------------------
+IMPLEMENT_CONOBJECT(GuiInspectorTypeRangedS32);
+
+ConsoleDocClass(GuiInspectorTypeRangedS32,
+   "@brief Inspector field type for range-clamped S32\n\n"
+   "Editor use only.\n\n"
+   "@internal"
+);
+
+void GuiInspectorTypeRangedS32::consoleInit()
+{
+   Parent::consoleInit();
+
+   ConsoleBaseType::getType(TypeRangedS32)->setInspectorFieldType("GuiInspectorTypeRangedS32");
+}
+
+GuiControl* GuiInspectorTypeRangedS32::constructEditControl()
+{
+   GuiControl* retCtrl = new GuiTextEditSliderCtrl();
+
+   retCtrl->setDataField(StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile");
+
+   // Don't forget to register ourselves
+   _registerEditControl(retCtrl);
+
+   char szBuffer[512];
+   dSprintf(szBuffer, 512, "%d.apply(%d.getText());", getId(), retCtrl->getId());
+   retCtrl->setField("AltCommand", szBuffer);
+   IRangeValidator* validator = dynamic_cast<IRangeValidator*>(mField->validator);
+
+   retCtrl->setField("increment", "1");
+   retCtrl->setField("format", "%d");
+   retCtrl->setField("range", "-2147483648 2147483647");
+
+   if (validator)
+   {
+      retCtrl->setField("range", String::ToString("%d %d", validator->getMin(), validator->getMax()));
+      if (validator->getFidelity() > 1)
+         retCtrl->setField("increment", String::ToString("%d", (validator->getMax() - validator->getMin()) / validator->getFidelity()));
+   }
+   else
+   {
+      IRangeValidatorScaled* scaledValidator = dynamic_cast<IRangeValidatorScaled*>(mField->validator);
+      if (scaledValidator)
+      {
+         retCtrl->setField("range", String::ToString("%d %d", scaledValidator->getMin(), scaledValidator->getMax()));
+         if (validator->getFidelity() > 1)
+            retCtrl->setField("increment", String::ToString("%d", scaledValidator->getScaleFactor()));
+      }
+   }
+   return retCtrl;
+}
+
+void GuiInspectorTypeRangedS32::setValue(StringTableEntry newValue)
+{
+   GuiTextEditSliderCtrl* ctrl = dynamic_cast<GuiTextEditSliderCtrl*>(mEdit);
+   if (ctrl != NULL)
+      ctrl->setText(newValue);
+}
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // GuiInspectorTypeS32Mask
 // GuiInspectorTypeS32Mask
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 29 - 0
Engine/source/gui/editor/guiInspectorTypes.h

@@ -473,6 +473,35 @@ public:
    void setValue( StringTableEntry newValue ) override;
    void setValue( StringTableEntry newValue ) override;
 };
 };
 
 
+//------------------------------------------------------------------------------
+// TypeRangedF32 GuiInspectorField class
+//------------------------------------------------------------------------------
+class GuiInspectorTypeRangedF32 : public GuiInspectorField
+{
+private:
+   typedef GuiInspectorField Parent;
+public:
+   DECLARE_CONOBJECT(GuiInspectorTypeRangedF32);
+   static void consoleInit();
+
+   GuiControl* constructEditControl() override;
+   void setValue(StringTableEntry newValue) override;
+};
+
+//------------------------------------------------------------------------------
+// TypeRangedS32 GuiInspectorField class
+//------------------------------------------------------------------------------
+class GuiInspectorTypeRangedS32 : public GuiInspectorField
+{
+private:
+   typedef GuiInspectorField Parent;
+public:
+   DECLARE_CONOBJECT(GuiInspectorTypeRangedS32);
+   static void consoleInit();
+
+   GuiControl* constructEditControl() override;
+   void setValue(StringTableEntry newValue) override;
+};
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 // TypeBitMask32 GuiInspectorField class
 // TypeBitMask32 GuiInspectorField class

+ 1 - 0
Engine/source/gui/editor/inspector/dynamicField.cpp

@@ -86,6 +86,7 @@ void GuiInspectorDynamicField::setData( const char* data, bool callbacks )
 
 
          // give the target a chance to validate
          // give the target a chance to validate
          target->inspectPostApply();
          target->inspectPostApply();
+         Con::executef(mInspector, "onPostInspectorFieldModified", mInspector->getIdString(), target->getIdString());
       }
       }
    }
    }
    
    

+ 2 - 0
Engine/source/gui/editor/inspector/field.cpp

@@ -615,6 +615,8 @@ void GuiInspectorField::setData( const char* data, bool callbacks )
          
          
          // Give the target a chance to validate.
          // Give the target a chance to validate.
          target->inspectPostApply();
          target->inspectPostApply();
+         if (String::compare(oldValue.c_str(), newValue.c_str()) != 0)
+            Con::executef(mInspector, "onPostInspectorFieldModified", mInspector->getIdString(), target->getIdString());
       }
       }
       
       
       if( callbacks && numTargets > 1 )
       if( callbacks && numTargets > 1 )

+ 31 - 1
Engine/source/gui/editor/inspector/group.cpp

@@ -282,7 +282,7 @@ bool GuiInspectorGroup::inspectGroup()
             bGrabItems = false;
             bGrabItems = false;
          continue;
          continue;
       }
       }
-      
+
       // Skip field if it has the HideInInspectors flag set.
       // Skip field if it has the HideInInspectors flag set.
 
 
       if (field->flag.test(AbstractClassRep::FIELD_HideInInspectors))
       if (field->flag.test(AbstractClassRep::FIELD_HideInInspectors))
@@ -761,6 +761,26 @@ void GuiInspectorGroup::removeInspectorField(StringTableEntry name)
    }
    }
 }
 }
 
 
+void GuiInspectorGroup::hideInspectorField(StringTableEntry fieldName, bool setHidden)
+{
+   SimObject* inspectObj = mParent->getInspectObject();
+   if (inspectObj == nullptr)
+      return;
+
+   AbstractClassRep::Field* field = const_cast<AbstractClassRep::Field*>(inspectObj->getClassRep()->findField(fieldName));
+
+   if (field == NULL)
+   {
+      Con::errorf("fieldName not found: %s.%s", inspectObj->getName(), fieldName);
+      return;
+   }
+
+   if (setHidden)
+      field->flag.set(AbstractClassRep::FIELD_HideInInspectors);
+   else
+      field->flag.clear(AbstractClassRep::FIELD_HideInInspectors);
+}
+
 DefineEngineMethod(GuiInspectorGroup, createInspectorField, GuiInspectorField*, (), , "createInspectorField()")
 DefineEngineMethod(GuiInspectorGroup, createInspectorField, GuiInspectorField*, (), , "createInspectorField()")
 {
 {
    return object->createInspectorField();
    return object->createInspectorField();
@@ -798,6 +818,16 @@ DefineEngineMethod(GuiInspectorGroup, removeField, void, (const char* fieldName)
    object->removeInspectorField(StringTable->insert(fieldName));
    object->removeInspectorField(StringTable->insert(fieldName));
 }
 }
 
 
+DefineEngineMethod(GuiInspectorGroup, hideField, void, (const char* fieldName, bool setHidden), (true),
+   "Removes a Inspector field to this group of a given name.\n"
+   "@param fieldName The name of the field to be removed.")
+{
+   if (dStrEqual(fieldName, ""))
+      return;
+
+   object->hideInspectorField(StringTable->insert(fieldName), setHidden);
+}
+
 DefineEngineMethod(GuiInspectorGroup, setForcedArrayIndex, void, (S32 arrayIndex), (-1),
 DefineEngineMethod(GuiInspectorGroup, setForcedArrayIndex, void, (S32 arrayIndex), (-1),
    "Sets the ForcedArrayIndex for the group. Used to force presentation of arrayed fields to only show a specific field index."
    "Sets the ForcedArrayIndex for the group. Used to force presentation of arrayed fields to only show a specific field index."
    "@param arrayIndex The specific field index for arrayed fields to show. Use -1 or blank arg to go back to normal behavior.")
    "@param arrayIndex The specific field index for arrayed fields to show. Use -1 or blank arg to go back to normal behavior.")

+ 1 - 0
Engine/source/gui/editor/inspector/group.h

@@ -86,6 +86,7 @@ public:
    void addInspectorField(StringTableEntry name, StringTableEntry typeName, const char* description, const char* callbackName);
    void addInspectorField(StringTableEntry name, StringTableEntry typeName, const char* description, const char* callbackName);
    void addInspectorField(GuiInspectorField* field);
    void addInspectorField(GuiInspectorField* field);
    void removeInspectorField(StringTableEntry name);
    void removeInspectorField(StringTableEntry name);
+   void hideInspectorField(StringTableEntry fieldName, bool setHidden);
 
 
    void setForcedArrayIndex(const S32& arrayIndex = -1)
    void setForcedArrayIndex(const S32& arrayIndex = -1)
    {
    {