浏览代码

Hooks the component fields back into the inspector so they are registered as proper fields of their types, as opposed to the regular string-only dynamic fields.

Areloch 9 年之前
父节点
当前提交
89672ea0ab

+ 9 - 7
Engine/source/T3D/components/component.cpp

@@ -410,20 +410,22 @@ void Component::addComponentField(const char *fieldName, const char *desc, const
    S32 fieldTypeMask = -1;
    StringTableEntry fieldType = StringTable->insert(type);
 
-   if (fieldType == StringTable->insert("TypeS32"))
+   if (fieldType == StringTable->insert("int"))
       fieldTypeMask = TypeS32;
-   else if (fieldType == StringTable->insert("TypeF32"))
+   else if (fieldType == StringTable->insert("float"))
       fieldTypeMask = TypeF32;
-   else if (fieldType == StringTable->insert("TypePoint3F"))
+   else if (fieldType == StringTable->insert("vector"))
       fieldTypeMask = TypePoint3F;
-   else if (fieldType == StringTable->insert("TypeMaterialName"))
+   else if (fieldType == StringTable->insert("material"))
       fieldTypeMask = TypeMaterialName;
-   else if (fieldType == StringTable->insert("TypeImageFilename"))
+   else if (fieldType == StringTable->insert("image"))
       fieldTypeMask = TypeImageFilename;
-   else if (fieldType == StringTable->insert("TypeShapeFilename"))
+   else if (fieldType == StringTable->insert("shape"))
       fieldTypeMask = TypeShapeFilename;
-   else if (fieldType == StringTable->insert("TypeBool"))
+   else if (fieldType == StringTable->insert("bool"))
       fieldTypeMask = TypeBool;
+   else if (fieldType == StringTable->insert("object"))
+      fieldTypeMask = TypeSimObjectPtr;
    else
       fieldTypeMask = TypeString;
 

+ 2 - 0
Engine/source/T3D/components/render/meshComponent.cpp

@@ -115,6 +115,8 @@ void MeshComponent::onRemove()
 {
    Parent::onRemove();
 
+   mMeshAsset.clear();
+
    SAFE_DELETE(mShapeInstance);
 }
 

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

@@ -230,7 +230,7 @@ bool Entity::onAdd()
 
 void Entity::onRemove()
 {
-   clearComponents(false);
+   clearComponents(true);
 
    removeFromScene();
 

+ 1 - 1
Engine/source/gui/controls/guiTreeViewCtrl.cpp

@@ -3798,7 +3798,7 @@ void GuiTreeViewCtrl::onMouseDown(const GuiEvent & event)
       if (item->isInspectorData())
       {
          Entity* e = dynamic_cast<Entity*>(item->getObject());
-         if (item->mScriptInfo.mText != StringTable->insert("Components"))
+         //if (item->mScriptInfo.mText != StringTable->insert("Components"))
          {
             Entity* e = dynamic_cast<Entity*>(item->getObject());
             if (e)

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

@@ -32,6 +32,7 @@
 #ifdef TORQUE_EXPERIMENTAL_EC
 #include "gui/editor/inspector/entityGroup.h"
 #include "gui/editor/inspector/mountingGroup.h"
+#include "gui/editor/inspector/componentGroup.h"
 #endif
 
 IMPLEMENT_CONOBJECT(GuiInspector);
@@ -609,6 +610,17 @@ void GuiInspector::refresh()
          addObject(mounting);
       }
    }
+
+   if (mTargets.first()->getClassRep()->isSubclassOf("Component"))
+   {
+      //Build the component field groups as the component describes it
+      Component* comp = dynamic_cast<Component*>(mTargets.first().getPointer());
+
+      GuiInspectorComponentGroup *compGroup = new GuiInspectorComponentGroup("Component Fields", this);
+      compGroup->registerObject();
+      mGroups.push_back(compGroup);
+      addObject(compGroup);
+   }
 #endif
 
    // Create the inspector groups for static fields.

+ 260 - 0
Engine/source/gui/editor/inspector/componentGroup.cpp

@@ -0,0 +1,260 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "gui/buttons/guiIconButtonCtrl.h"
+#include "gui/editor/guiInspector.h"
+#include "gui/editor/inspector/componentGroup.h"
+#include "core/strings/stringUnit.h"
+#include "T3D/components/component.h"
+#include "gui/editor/inspector/field.h"
+
+#include "console/engineAPI.h"
+
+IMPLEMENT_CONOBJECT(GuiInspectorComponentGroup);
+
+ConsoleDocClass(GuiInspectorComponentGroup,
+   "@brief Used to inspect an object's FieldDictionary (dynamic fields) instead "
+   "of regular persistent fields.\n\n"
+   "Editor use only.\n\n"
+   "@internal"
+   );
+
+GuiInspectorComponentGroup::GuiInspectorComponentGroup(StringTableEntry groupName, SimObjectPtr<GuiInspector> parent)
+: GuiInspectorGroup(groupName, parent) 
+{ 
+   /*mNeedScroll=false;*/
+};
+
+bool GuiInspectorComponentGroup::onAdd()
+{
+   if (!Parent::onAdd())
+      return false;
+
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// GuiInspectorComponentGroup - add custom controls
+//-----------------------------------------------------------------------------
+bool GuiInspectorComponentGroup::createContent()
+{
+   if(!Parent::createContent())
+      return false;
+
+   Con::evaluatef("%d.stack = %d;", this->getId(), mStack->getId());
+
+   Con::executef(this, "createContent");
+
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// GuiInspectorComponentGroup - inspectGroup override
+//-----------------------------------------------------------------------------
+bool GuiInspectorComponentGroup::inspectGroup()
+{
+   // We can't inspect a group without a target!
+   if (!mParent || !mParent->getNumInspectObjects())
+      return false;
+
+   // to prevent crazy resizing, we'll just freeze our stack for a sec..
+   mStack->freeze(true);
+
+   mStack->clear();
+
+   bool bNoGroup = false;
+
+   // Un-grouped fields are all sorted into the 'general' group
+   if (dStricmp(mCaption, "General") == 0)
+      bNoGroup = true;
+
+   // Just delete all fields and recreate them (like the dynamicGroup)
+   // because that makes creating controls for array fields a lot easier
+   clearFields();
+
+   bool bNewItems = false;
+   bool bMakingArray = false;
+   GuiStackControl *pArrayStack = NULL;
+   GuiRolloutCtrl *pArrayRollout = NULL;
+   bool bGrabItems = false;
+
+   Component* comp = dynamic_cast<Component*>(getInspector()->getInspectObject(0));
+
+   //if this isn't a component, what are we even doing here?
+   if (!comp)
+      return false;
+
+   for (U32 i = 0; i < comp->getComponentFieldCount(); i++)
+   {
+      ComponentField* field = comp->getComponentField(i);
+
+      bNewItems = true;
+
+      GuiInspectorField *fieldGui = constructField(field->mFieldType);
+      if (fieldGui == NULL)
+         fieldGui = new GuiInspectorField();
+
+      fieldGui->init(mParent, this);
+
+      AbstractClassRep::Field *refField;
+      //check statics
+      refField = const_cast<AbstractClassRep::Field *>(comp->findField(field->mFieldName));
+      if (!refField)
+      {
+         //check dynamics
+         SimFieldDictionary* fieldDictionary = comp->getFieldDictionary();
+         SimFieldDictionaryIterator itr(fieldDictionary);
+
+         while (*itr)
+         {
+            SimFieldDictionary::Entry* entry = *itr;
+            if (entry->slotName == field->mFieldName)
+            {
+               AbstractClassRep::Field f;
+               f.pFieldname = StringTable->insert(field->mFieldName);
+
+               if (field->mFieldDescription)
+                  f.pFieldDocs = field->mFieldDescription;
+
+               f.type = field->mFieldType;
+               f.offset = -1;
+               f.elementCount = 1;
+               f.validator = NULL;
+               f.flag = 0; //change to be the component type
+
+               f.setDataFn = &defaultProtectedSetFn;
+               f.getDataFn = &defaultProtectedGetFn;
+               f.writeDataFn = &defaultProtectedWriteFn;
+
+               if (!dStrcmp(field->mGroup, ""))
+                  f.pGroupname = "Component";
+               else
+                  f.pGroupname = field->mGroup;
+
+               ConsoleBaseType* conType = ConsoleBaseType::getType(field->mFieldType);
+               AssertFatal(conType, "ConsoleObject::addField - invalid console type");
+               f.table = conType->getEnumTable();
+
+               tempFields.push_back(f);
+
+               refField = &f;
+
+               break;
+            }
+            ++itr;
+         }
+      }
+
+      if (!refField)
+         continue;
+
+      fieldGui->setInspectorField(&tempFields[tempFields.size() - 1]);
+
+      if (fieldGui->registerObject())
+      {
+#ifdef DEBUG_SPEW
+         Platform::outputDebugString("[GuiInspectorGroup] Adding field '%s'",
+            field->pFieldname);
+#endif
+
+         mChildren.push_back(fieldGui);
+         mStack->addObject(fieldGui);
+      }
+      else
+      {
+         SAFE_DELETE(fieldGui);
+      }
+   }
+
+   mStack->freeze(false);
+   mStack->updatePanes();
+
+   // If we've no new items, there's no need to resize anything!
+   if (bNewItems == false && !mChildren.empty())
+      return true;
+
+   sizeToContents();
+
+   setUpdate();
+
+   return true;
+}
+
+void GuiInspectorComponentGroup::updateAllFields()
+{
+   // We overload this to just reinspect the group.
+   inspectGroup();
+}
+
+void GuiInspectorComponentGroup::onMouseMove(const GuiEvent &event)
+{
+   //mParent->mOverDivider = false;
+}
+ConsoleMethod(GuiInspectorComponentGroup, inspectGroup, bool, 2, 2, "Refreshes the dynamic fields in the inspector.")
+{
+   return object->inspectGroup();
+}
+
+void GuiInspectorComponentGroup::clearFields()
+{
+}
+
+SimFieldDictionary::Entry* GuiInspectorComponentGroup::findDynamicFieldInDictionary(StringTableEntry fieldName)
+{
+   SimFieldDictionary * fieldDictionary = mParent->getInspectObject()->getFieldDictionary();
+
+   for (SimFieldDictionaryIterator ditr(fieldDictionary); *ditr; ++ditr)
+   {
+      SimFieldDictionary::Entry * entry = (*ditr);
+
+      if (entry->slotName == fieldName)
+         return entry;
+   }
+
+   return NULL;
+}
+
+void GuiInspectorComponentGroup::addDynamicField()
+{
+}
+
+AbstractClassRep::Field* GuiInspectorComponentGroup::findObjectBehaviorField(Component* target, String fieldName)
+{
+   AbstractClassRep::FieldList& fieldList = target->getClassRep()->mFieldList;
+   for (AbstractClassRep::FieldList::iterator itr = fieldList.begin();
+      itr != fieldList.end(); ++itr)
+   {
+      AbstractClassRep::Field* field = &(*itr);
+      String fldNm(field->pFieldname);
+      if (fldNm == fieldName)
+         return field;
+   }
+   return NULL;
+}
+ConsoleMethod(GuiInspectorComponentGroup, addDynamicField, void, 2, 2, "obj.addDynamicField();")
+{
+   object->addDynamicField();
+}
+
+ConsoleMethod(GuiInspectorComponentGroup, removeDynamicField, void, 3, 3, "")
+{
+}

+ 70 - 0
Engine/source/gui/editor/inspector/componentGroup.h

@@ -0,0 +1,70 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef GUI_INSPECTOR_COMPONENT_GROUP_H
+#define GUI_INSPECTOR_COMPONENT_GROUP_H
+
+#include "gui/editor/inspector/group.h"
+#include "console/simFieldDictionary.h"
+#include "T3D/components/component.h"
+#include "gui/controls/guiPopUpCtrlEx.h"
+
+class GuiInspectorComponentGroup : public GuiInspectorGroup
+{
+private:
+   typedef GuiInspectorGroup Parent;
+   GuiControl* mAddCtrl;
+
+   Vector<AbstractClassRep::Field> tempFields;
+
+public:
+   DECLARE_CONOBJECT(GuiInspectorComponentGroup);
+   GuiInspectorComponentGroup() { /*mNeedScroll=false;*/ };
+   GuiInspectorComponentGroup(StringTableEntry groupName, SimObjectPtr<GuiInspector> parent);
+
+   //-----------------------------------------------------------------------------
+   // inspectGroup is overridden in GuiInspectorComponentGroup to inspect an 
+   // objects FieldDictionary (dynamic fields) instead of regular persistent
+   // fields.
+   virtual bool onAdd();
+   bool inspectGroup();
+   virtual void updateAllFields();
+
+   void onMouseMove(const GuiEvent &event);
+
+   // For scriptable dynamic field additions
+   void addDynamicField();
+
+   // Clear our fields (delete them)
+   void clearFields();
+
+   // Find an already existent field by name in the dictionary
+   virtual SimFieldDictionary::Entry* findDynamicFieldInDictionary(StringTableEntry fieldName);
+
+   AbstractClassRep::Field* findObjectBehaviorField(Component* target, String fieldName);
+protected:
+   // create our inner controls when we add
+   virtual bool createContent();
+
+};
+
+#endif

+ 14 - 0
Engine/source/gui/editor/inspector/dynamicGroup.cpp

@@ -26,6 +26,10 @@
 #include "gui/editor/inspector/dynamicField.h"
 #include "console/engineAPI.h"
 
+#ifdef TORQUE_EXPERIMENTAL_EC
+#include "T3D/components/component.h"
+#endif
+
 IMPLEMENT_CONOBJECT(GuiInspectorDynamicGroup);
 
 ConsoleDocClass( GuiInspectorDynamicGroup,
@@ -122,6 +126,16 @@ bool GuiInspectorDynamicGroup::inspectGroup()
       SimFieldDictionary * fieldDictionary = target->getFieldDictionary();
       for(SimFieldDictionaryIterator ditr(fieldDictionary); *ditr; ++ditr)
       {
+#ifdef TORQUE_EXPERIMENTAL_EC
+         if (target->getClassRep()->isSubclassOf("Component"))
+         {
+            Component* compTarget = dynamic_cast<Component*>(target);
+
+            ComponentField* compField = compTarget->getComponentField((*ditr)->slotName);
+            if (compField)
+               continue;
+         }
+#endif
          if( i == 0 )
          {
             flist.increment();