소스 검색

Merge pull request #982 from Areloch/OnInspectEditorLogic

Adds logic and handling for Inspected SimObjects to be able to injectnew InspectorGroups and InspectorFields when being inspected for editing.
Brian Roberts 2 년 전
부모
커밋
59ed9ee7b6

+ 7 - 0
Engine/source/console/simObject.cpp

@@ -40,6 +40,7 @@
 #include "core/stream/fileStream.h"
 #include "core/fileObject.h"
 #include "persistence/taml/tamlCustom.h"
+#include "gui/editor/guiInspector.h"
 
 #include "sim/netObject.h"
 #include "cinterface/cinterface.h"
@@ -2334,7 +2335,13 @@ String SimObject::_getLogMessage(const char* fmt, va_list args) const
 // MARK: ---- API ----
 
 //-----------------------------------------------------------------------------
+void SimObject::onInspect(GuiInspector* inspector)
+{
+   if (isMethod("onInspect"))
+      Con::executef(this, "onInspect", inspector);
+}
 
+//-----------------------------------------------------------------------------
 DefineEngineMethod( SimObject, dumpGroupHierarchy, void, (),,
    "Dump the hierarchy of this object up to RootGroup to the console." )
 {

+ 1 - 1
Engine/source/console/simObject.h

@@ -653,7 +653,7 @@ class SimObject: public ConsoleObject, public TamlCallbacks
       virtual void onEditorDisable(){};
 
       /// Called when the object is inspected via a GuiInspector control
-      virtual void onInspect(GuiInspector*) {};
+      virtual void onInspect(GuiInspector*);
 
       /// @}
 

+ 44 - 0
Engine/source/gui/editor/guiInspector.cpp

@@ -779,6 +779,32 @@ void GuiInspector::sendInspectPostApply()
       getInspectObject( i )->inspectPostApply();
 }
 
+S32 GuiInspector::createInspectorGroup(StringTableEntry groupName, S32 index)
+{
+   GuiInspectorGroup* newGroup = nullptr;
+   newGroup = findExistentGroup(groupName);
+   if (newGroup)
+      return newGroup->getId();  //if we already have a group under this name, just return it
+
+   newGroup = new GuiInspectorGroup(groupName, this);
+   newGroup->registerObject();
+
+   if (index == -1)
+   {
+      //if index is -1, we just throw the group onto the stack at the end
+      mGroups.push_back(newGroup);
+   }
+   else
+   {
+      //if we have an explicit index, insert it specifically
+      mGroups.insert(index, newGroup);
+   }
+
+   addObject(newGroup);
+
+   return newGroup->getId();
+}
+
 //=============================================================================
 //    Console Methods.
 //=============================================================================
@@ -918,3 +944,21 @@ DefineEngineMethod( GuiInspector, findByObject, S32, (SimObject* obj), ,
 
    return inspector->getId();
 }
+
+DefineEngineMethod(GuiInspector, createGroup, S32, (const char* groupName, S32 index), (-1),
+   "Creates a new GuiInspectorGroup for this inspector and returns it's Id. If one already exists, then the Id of the existing one is returned.\n"
+   "@param groupName Name of the new GuiInspectorGroup to add to this Inspector."
+   "@param index(Optional) The index where to add the new group to in this Inspector's group stack."
+   "@return id of the named GuiInspectorGroup")
+{
+   return object->createInspectorGroup(StringTable->insert(groupName), index);
+}
+
+DefineEngineMethod(GuiInspector, findExistentGroup, S32, (const char* groupName), ,
+   "Finds an existing GuiInspectorGroup if it exists and returns it's Id.\n"
+   "@param groupName Name of the new GuiInspectorGroup to find in this Inspector."
+   "@return id of the named GuiInspectorGroup")
+{
+   GuiInspectorGroup* group = object->findExistentGroup(StringTable->insert(groupName));
+   return group ? group->getId() : 0;
+}

+ 2 - 0
Engine/source/gui/editor/guiInspector.h

@@ -165,6 +165,8 @@ public:
 
    void refresh();
 
+   S32 createInspectorGroup(StringTableEntry groupName, S32 index);
+
 protected:
       
    typedef Vector< SimObjectPtr< SimObject > > TargetVector;

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

@@ -25,7 +25,10 @@
 #include "gui/editor/inspector/dynamicField.h"
 #include "gui/editor/inspector/datablockField.h"
 #include "gui/buttons/guiIconButtonCtrl.h"
-
+#include "T3D/assets/MaterialAsset.h"
+#include "T3D/assets/ShapeAsset.h"
+#include "T3D/assets/ImageAsset.h"
+#include "T3D/assets/SoundAsset.h"
 
 IMPLEMENT_CONOBJECT(GuiInspectorGroup);
 
@@ -564,3 +567,97 @@ AbstractClassRep* GuiInspectorGroup::findCommonAncestorClass()
       
    return classRep;
 }
+
+void GuiInspectorGroup::addInspectorField(StringTableEntry name, StringTableEntry typeName, const char* description, const char* callbackName)
+{
+   S32 fieldType = -1;
+
+   if (typeName == StringTable->insert("int"))
+      fieldType = TypeS32;
+   else if (typeName == StringTable->insert("float"))
+      fieldType = TypeF32;
+   else if (typeName == StringTable->insert("vector"))
+      fieldType = TypePoint3F;
+   else if (typeName == StringTable->insert("vector2"))
+      fieldType = TypePoint2F;
+   else if (typeName == StringTable->insert("material"))
+      fieldType = TypeMaterialAssetId;
+   else if (typeName == StringTable->insert("image"))
+      fieldType = TypeImageAssetId;
+   else if (typeName == StringTable->insert("shape"))
+      fieldType = TypeShapeAssetId;
+   else if (typeName == StringTable->insert("sound"))
+      fieldType = TypeSoundAssetId;
+   else if (typeName == StringTable->insert("bool"))
+      fieldType = TypeBool;
+   else if (typeName == StringTable->insert("object"))
+      fieldType = TypeSimObjectPtr;
+   else if (typeName == StringTable->insert("string"))
+      fieldType = TypeString;
+   else if (typeName == StringTable->insert("colorI"))
+      fieldType = TypeColorI;
+   else if (typeName == StringTable->insert("colorF"))
+      fieldType = TypeColorF;
+   else if (typeName == StringTable->insert("ease"))
+      fieldType = TypeEaseF;
+   else if (typeName == StringTable->insert("command"))
+      fieldType = TypeCommand;
+   else if (typeName == StringTable->insert("filename"))
+      fieldType = TypeStringFilename;
+   else
+      fieldType = -1;
+
+   GuiInspectorField* fieldGui = constructField(fieldType);
+   if (fieldGui == nullptr)
+   {
+      //call down into script and see if there's special handling for that type of field
+      //this allows us to have completely special-case field types implemented entirely in script
+      if (isMethod("onConstructField"))
+      {
+         //ensure our stack variable is bound if we need it
+         Con::evaluatef("%d.stack = %d;", this->getId(), mStack->getId());
+
+         Con::executef(this, "onConstructField", name, name, typeName, description, StringTable->EmptyString(), StringTable->EmptyString(), callbackName);
+      }
+   }
+   else
+   {
+      fieldGui->init(mParent, this);
+
+      fieldGui->setSpecialEditField(true);
+      fieldGui->setTargetObject(mParent->getInspectObject(0));
+
+      StringTableEntry fieldName = StringTable->insert(name);
+
+      fieldGui->setSpecialEditVariableName(fieldName);
+      fieldGui->setSpecialEditCallbackName(callbackName);
+
+      fieldGui->setInspectorField(NULL, fieldName);
+      fieldGui->setDocs(description);
+
+      if (fieldGui->registerObject())
+      {
+         fieldGui->setValue(mParent->getInspectObject(0)->getDataField(fieldName, NULL));
+
+         mStack->addObject(fieldGui);
+      }
+      else
+      {
+         SAFE_DELETE(fieldGui);
+      }
+   }
+}
+
+DefineEngineMethod(GuiInspectorGroup, addField, void, (const char* fieldName, const char* fieldTypeName, const char* description, const char* callbackName),
+   ("", "", "", ""),
+   "Adds a new Inspector field to this group.\n"
+   "@param fieldName The name of the field to add. The field will associate to a variable of the same name on the inspected object for editing purposes."
+   "@param fieldTypeName The name of the type of field it is. If it's an understood existing type, it will create it as normal. If it's an unknown type, it will attempt to call into script to create it."
+   "@param description (Optional) Description of the field."
+   "@param callbackName (Optional) Sets a special callback function to be called when this field is edited.")
+{
+   if (dStrEqual(fieldName, "") || dStrEqual(fieldTypeName, ""))
+      return;
+
+   object->addInspectorField(StringTable->insert(fieldName), StringTable->insert(fieldTypeName), description, callbackName);
+}

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

@@ -76,6 +76,8 @@ public:
    
    U32 getNumFields() const { return mChildren.size(); }
 
+   void addInspectorField(StringTableEntry name, StringTableEntry typeName, const char* description, const char* callbackName);
+
 protected:
    // overridable method that creates our inner controls.
    virtual bool createContent();