From 2f40b843d4fac77b763a272fa4118583f53e33c1 Mon Sep 17 00:00:00 2001 From: Areloch Date: Sat, 18 Mar 2023 02:22:47 -0500 Subject: [PATCH] Adds expanded ability to create and insert specialized script-based inspector fields Adds logic during the editor script initialization to let game modules have embedded tools Changed setting to force prompt for target modules when creating things like datablocks to minimize confusion about where they save to --- Engine/source/gui/editor/guiInspector.cpp | 17 +++++ Engine/source/gui/editor/guiInspector.h | 2 + Engine/source/gui/editor/inspector/field.h | 7 +- Engine/source/gui/editor/inspector/group.cpp | 67 +++++++++++++++++++- Engine/source/gui/editor/inspector/group.h | 3 + Templates/BaseGame/game/tools/main.tscript | 38 ++++++++++- Templates/BaseGame/game/tools/settings.xml | 2 + 7 files changed, 131 insertions(+), 5 deletions(-) diff --git a/Engine/source/gui/editor/guiInspector.cpp b/Engine/source/gui/editor/guiInspector.cpp index 7b3708e0e..dcd3cbf00 100644 --- a/Engine/source/gui/editor/guiInspector.cpp +++ b/Engine/source/gui/editor/guiInspector.cpp @@ -805,6 +805,16 @@ S32 GuiInspector::createInspectorGroup(StringTableEntry groupName, S32 index) return newGroup->getId(); } +void GuiInspector::removeInspectorGroup(StringTableEntry groupName) +{ + GuiInspectorGroup* group = findExistentGroup(groupName); + if (group == nullptr) + return; + + mGroups.remove(group); + removeObject(group); +} + //============================================================================= // Console Methods. //============================================================================= @@ -962,3 +972,10 @@ DefineEngineMethod(GuiInspector, findExistentGroup, S32, (const char* groupName) GuiInspectorGroup* group = object->findExistentGroup(StringTable->insert(groupName)); return group ? group->getId() : 0; } + +DefineEngineMethod(GuiInspector, removeGroup, void, (const char* groupName), , + "Finds an existing GuiInspectorGroup if it exists removes it.\n" + "@param groupName Name of the new GuiInspectorGroup to find in this Inspector.") +{ + object->removeInspectorGroup(StringTable->insert(groupName)); +} diff --git a/Engine/source/gui/editor/guiInspector.h b/Engine/source/gui/editor/guiInspector.h index de8ed0378..d7492d513 100644 --- a/Engine/source/gui/editor/guiInspector.h +++ b/Engine/source/gui/editor/guiInspector.h @@ -167,6 +167,8 @@ public: S32 createInspectorGroup(StringTableEntry groupName, S32 index); + void removeInspectorGroup(StringTableEntry groupName); + protected: typedef Vector< SimObjectPtr< SimObject > > TargetVector; diff --git a/Engine/source/gui/editor/inspector/field.h b/Engine/source/gui/editor/inspector/field.h index 676269f75..9b6e6d372 100644 --- a/Engine/source/gui/editor/inspector/field.h +++ b/Engine/source/gui/editor/inspector/field.h @@ -210,8 +210,11 @@ class GuiInspectorField : public GuiControl void setTargetObject(SimObject* obj) { mTargetObject = obj; } SimObject* getTargetObject() { return mTargetObject; } void setSpecialEditField(bool isSpecialEditField) { mSpecialEditField = isSpecialEditField; } - void setSpecialEditVariableName(String varName) { mVariableName = StringTable->insert(varName); } - void setSpecialEditCallbackName(String callName) { mCallbackName = StringTable->insert(callName); } + + void setSpecialEditVariableName(StringTableEntry varName) { mVariableName = varName; } + StringTableEntry getSpecialEditVariableName() { return mVariableName; } + + void setSpecialEditCallbackName(StringTableEntry callName) { mCallbackName = callName; } DECLARE_CONOBJECT( GuiInspectorField ); DECLARE_CATEGORY( "Gui Editor" ); diff --git a/Engine/source/gui/editor/inspector/group.cpp b/Engine/source/gui/editor/inspector/group.cpp index 75d0460a1..4f2de4bff 100644 --- a/Engine/source/gui/editor/inspector/group.cpp +++ b/Engine/source/gui/editor/inspector/group.cpp @@ -568,6 +568,22 @@ AbstractClassRep* GuiInspectorGroup::findCommonAncestorClass() return classRep; } +GuiInspectorField* GuiInspectorGroup::createInspectorField() +{ + GuiInspectorField* newField = new GuiInspectorField(); + + newField->init(mParent, this); + + newField->setSpecialEditField(true); + + if (newField->registerObject()) + { + return newField; + } + + return NULL; +} + void GuiInspectorGroup::addInspectorField(StringTableEntry name, StringTableEntry typeName, const char* description, const char* callbackName) { S32 fieldType = -1; @@ -626,7 +642,7 @@ void GuiInspectorGroup::addInspectorField(StringTableEntry name, StringTableEntr //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); + Con::executef(this, "onConstructField", name, name, typeName, description, StringTable->EmptyString(), StringTable->EmptyString(), callbackName, mParent->getInspectObject(0)->getId()); } } else @@ -639,7 +655,7 @@ void GuiInspectorGroup::addInspectorField(StringTableEntry name, StringTableEntr StringTableEntry fieldName = StringTable->insert(name); fieldGui->setSpecialEditVariableName(fieldName); - fieldGui->setSpecialEditCallbackName(callbackName); + fieldGui->setSpecialEditCallbackName(StringTable->insert(callbackName)); fieldGui->setInspectorField(NULL, fieldName); fieldGui->setDocs(description); @@ -657,6 +673,35 @@ void GuiInspectorGroup::addInspectorField(StringTableEntry name, StringTableEntr } } +void GuiInspectorGroup::addInspectorField(GuiInspectorField* field) +{ + mStack->addObject(field); + mChildren.push_back(field); + mStack->updatePanes(); +} + +void GuiInspectorGroup::removeInspectorField(StringTableEntry name) +{ + for (U32 i = 0; i < mStack->size(); i++) + { + GuiInspectorField* field = dynamic_cast(mStack->getObject(i)); + + if (field == nullptr) + continue; + + if (field->getFieldName() == name || field->getSpecialEditVariableName() == name) + { + mStack->removeObject(field); + return; + } + } +} + +DefineEngineMethod(GuiInspectorGroup, createInspectorField, GuiInspectorField*, (), , "createInspectorField()") +{ + return object->createInspectorField(); +} + 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" @@ -670,3 +715,21 @@ DefineEngineMethod(GuiInspectorGroup, addField, void, (const char* fieldName, co object->addInspectorField(StringTable->insert(fieldName), StringTable->insert(fieldTypeName), description, callbackName); } + + +DefineEngineMethod(GuiInspectorGroup, addInspectorField, void, (GuiInspectorField* field), (nullAsType()), "addInspectorField( GuiInspectorFieldObject )") +{ + if(field) + object->addInspectorField(field); +} + +DefineEngineMethod(GuiInspectorGroup, removeField, void, (const char* fieldName), + (""), + "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->removeInspectorField(StringTable->insert(fieldName)); +} diff --git a/Engine/source/gui/editor/inspector/group.h b/Engine/source/gui/editor/inspector/group.h index eb38ec36f..7cef6f71b 100644 --- a/Engine/source/gui/editor/inspector/group.h +++ b/Engine/source/gui/editor/inspector/group.h @@ -76,7 +76,10 @@ public: U32 getNumFields() const { return mChildren.size(); } + GuiInspectorField* createInspectorField(); void addInspectorField(StringTableEntry name, StringTableEntry typeName, const char* description, const char* callbackName); + void addInspectorField(GuiInspectorField* field); + void removeInspectorField(StringTableEntry name); protected: // overridable method that creates our inner controls. diff --git a/Templates/BaseGame/game/tools/main.tscript b/Templates/BaseGame/game/tools/main.tscript index b44a27f99..df21eca44 100644 --- a/Templates/BaseGame/game/tools/main.tscript +++ b/Templates/BaseGame/game/tools/main.tscript @@ -126,13 +126,49 @@ function onStart() } %folder = findNextFile( %pattern ); } + + //Next, scrape through modules and scan for tools subfolders there + %pattern = "data/*/editor." @ $TorqueScriptFileExtension; + %folder = findFirstFile( %pattern ); + if ( %folder $= "") + { + // if we have absolutely no matches for main.tscript, we look for main.tscript.dso + %pattern = "data/*/editor." @ $TorqueScriptFileExtension @ ".dso"; + %folder = findFirstFile( %pattern ); + } + while ( %folder !$= "" ) + { + if( filePath( %folder ) !$= "tools" ) // Skip the actual 'tools' folder...we want the children + { + %folder = filePath( %folder ); + %editor = fileName( %folder ); + if ( IsDirectory( %folder ) ) + { + // Yes, this sucks and should be done better + if ( strstr( $Tools::loadFirst, %editor ) == -1 ) + { + $editors[$editors[count]] = %editor; + $editorsPath[$editors[count]] = %folder; + $editors[count]++; + } + } + } + %folder = findNextFile( %pattern ); + } // initialize every editor new SimSet( EditorPluginSet ); %count = $editors[count]; for ( %i = 0; %i < %count; %i++ ) { - exec( "./" @ $editors[%i] @ "/main." @ $TorqueScriptFileExtension ); + %editorFilename = "./" @ $editors[%i] @ "/main." @ $TorqueScriptFileExtension; + if(isFile(%editorFilename)) + exec( "./" @ $editors[%i] @ "/main." @ $TorqueScriptFileExtension ); + else + { + if($editorsPath[%i] !$= "") + exec( $editorsPath[%i] @ "/editor." @ $TorqueScriptFileExtension ); + } %initializeFunction = "initialize" @ $editors[%i]; if( isFunction( %initializeFunction ) ) diff --git a/Templates/BaseGame/game/tools/settings.xml b/Templates/BaseGame/game/tools/settings.xml index dc0c31602..abb4d07a5 100644 --- a/Templates/BaseGame/game/tools/settings.xml +++ b/Templates/BaseGame/game/tools/settings.xml @@ -49,6 +49,8 @@ + 1 ExampleModule