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.

This commit is contained in:
Areloch 2016-06-02 22:40:29 -05:00
parent 2464b620ba
commit 89672ea0ab
8 changed files with 369 additions and 9 deletions

View file

@ -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;

View file

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

View file

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

View file

@ -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)

View file

@ -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.

View file

@ -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, "")
{
}

View file

@ -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

View file

@ -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();