diff --git a/Engine/source/gui/controls/guiPopUpCtrlEx.cpp b/Engine/source/gui/controls/guiPopUpCtrlEx.cpp index ddfcb4d5b..45183285d 100644 --- a/Engine/source/gui/controls/guiPopUpCtrlEx.cpp +++ b/Engine/source/gui/controls/guiPopUpCtrlEx.cpp @@ -855,7 +855,7 @@ void GuiPopUpMenuCtrlEx::sortID() } //------------------------------------------------------------------------------ -void GuiPopUpMenuCtrlEx::addEntry(const char *buf, S32 id, U32 scheme) +void GuiPopUpMenuCtrlEx::addEntry(const char *buf, S32 id, U32 scheme, const bool& intented) { if( !buf ) { @@ -882,6 +882,7 @@ void GuiPopUpMenuCtrlEx::addEntry(const char *buf, S32 id, U32 scheme) dStrcpy( e.buf, buf, 256 ); e.id = id; e.scheme = scheme; + e.indented = intented; // see if there is a shortcut key char * cp = dStrchr( e.buf, '~' ); @@ -1326,8 +1327,8 @@ void GuiPopUpMenuCtrlEx::closePopUp() mSelIndex = ( mRevNum >= mSelIndex && mSelIndex != -1 ) ? mRevNum - mSelIndex : mSelIndex; if ( mSelIndex != -1 ) { - if ( mReplaceText ) - setText(mTl->mList[mSelIndex].text); + if (mReplaceText) + setText(mEntries[mSelIndex].buf); for(U32 i=0; i < mEntries.size(); i++) { @@ -1465,7 +1466,12 @@ void GuiPopUpMenuCtrlEx::onAction() } else { - mTl->addEntry(mEntries[j].id, mEntries[j].buf); + String entryText = mEntries[j].buf; + + if(mEntries[j].indented) + entryText = String(" ") + entryText; + + mTl->addEntry(mEntries[j].id, entryText.c_str()); } } diff --git a/Engine/source/gui/controls/guiPopUpCtrlEx.h b/Engine/source/gui/controls/guiPopUpCtrlEx.h index 503d91690..e1136626c 100644 --- a/Engine/source/gui/controls/guiPopUpCtrlEx.h +++ b/Engine/source/gui/controls/guiPopUpCtrlEx.h @@ -86,8 +86,9 @@ class GuiPopUpMenuCtrlEx : public GuiTextCtrl S32 id; U16 ascii; U16 scheme; - bool usesColorBox; // Added - ColorI colorbox; // Added + bool usesColorBox; // Added + ColorI colorbox; // Added + bool indented; // Added }; struct Scheme @@ -156,7 +157,11 @@ class GuiPopUpMenuCtrlEx : public GuiTextCtrl void setBitmap(const char *name); // Added void sort(); void sortID(); // Added - void addEntry(const char *buf, S32 id = -1, U32 scheme = 0); + void addEntry(const char *buf, S32 id = -1, U32 scheme = 0, const bool& indented = false); + void addCategory(const char *buf) + { + addEntry(buf, -2, 0); + } void addScheme(U32 id, ColorI fontColor, ColorI fontColorHL, ColorI fontColorSEL); void onRender(Point2I offset, const RectI &updateRect); void onAction(); @@ -184,6 +189,7 @@ class GuiPopUpMenuCtrlEx : public GuiTextCtrl S32 getNumEntries() { return( mEntries.size() ); } void replaceText(S32); + void setCanSearch(const bool& canSearch) { mTextSearchItems = canSearch; } void setSearchText(String searchTxt) { mSearchText = String::ToLower(searchTxt); onAction(); } DECLARE_CONOBJECT(GuiPopUpMenuCtrlEx); diff --git a/Engine/source/gui/editor/guiInspectorTypes.cpp b/Engine/source/gui/editor/guiInspectorTypes.cpp index 49d693523..61e884a0e 100644 --- a/Engine/source/gui/editor/guiInspectorTypes.cpp +++ b/Engine/source/gui/editor/guiInspectorTypes.cpp @@ -56,9 +56,9 @@ ConsoleDocClass( GuiInspectorTypeMenuBase, GuiControl* GuiInspectorTypeMenuBase::constructEditControl() { - GuiControl* retCtrl = new GuiPopUpMenuCtrl(); + GuiControl* retCtrl = new GuiPopUpMenuCtrlEx(); - GuiPopUpMenuCtrl *menu = dynamic_cast(retCtrl); + GuiPopUpMenuCtrlEx *menu = dynamic_cast(retCtrl); // Let's make it look pretty. retCtrl->setDataField( StringTable->insert("profile"), NULL, "ToolsGuiPopupMenuProfile" ); @@ -89,7 +89,7 @@ void GuiInspectorTypeMenuBase::setValue( StringTableEntry newValue ) ctrl->setText( newValue ); } -void GuiInspectorTypeMenuBase::_populateMenu( GuiPopUpMenuCtrl *menu ) +void GuiInspectorTypeMenuBase::_populateMenu( GuiPopUpMenuCtrlEx *menu ) { // do nothing, child classes override this. } @@ -105,7 +105,7 @@ ConsoleDocClass( GuiInspectorTypeEnum, "@internal" ); -void GuiInspectorTypeEnum::_populateMenu( GuiPopUpMenuCtrl *menu ) +void GuiInspectorTypeEnum::_populateMenu( GuiPopUpMenuCtrlEx *menu ) { const EngineEnumTable* table = mField->table; if( !table ) @@ -148,7 +148,7 @@ ConsoleDocClass( GuiInspectorTypeCubemapName, "@internal" ); -void GuiInspectorTypeCubemapName::_populateMenu( GuiPopUpMenuCtrl *menu ) +void GuiInspectorTypeCubemapName::_populateMenu(GuiPopUpMenuCtrlEx *menu ) { PROFILE_SCOPE( GuiInspectorTypeCubemapName_populateMenu ); @@ -356,7 +356,7 @@ ConsoleDocClass( GuiInspectorTypeGuiProfile, "@internal" ); -void GuiInspectorTypeGuiProfile::_populateMenu( GuiPopUpMenuCtrl *menu ) +void GuiInspectorTypeGuiProfile::_populateMenu(GuiPopUpMenuCtrlEx *menu ) { // Check whether we should show profiles from the editor category. @@ -399,7 +399,7 @@ ConsoleDocClass(GuiInspectorTypeActionMap, "@internal" ); -void GuiInspectorTypeActionMap::_populateMenu(GuiPopUpMenuCtrl* menu) +void GuiInspectorTypeActionMap::_populateMenu(GuiPopUpMenuCtrlEx* menu) { // Add the action maps to the menu. //First add a blank entry so you can clear the action map @@ -1671,7 +1671,7 @@ ConsoleDocClass( GuiInspectorTypeSFXParameterName, "@internal" ); -void GuiInspectorTypeSFXParameterName::_populateMenu( GuiPopUpMenuCtrl *menu ) +void GuiInspectorTypeSFXParameterName::_populateMenu(GuiPopUpMenuCtrlEx *menu ) { SimSet* set = Sim::getSFXParameterGroup(); for( SimSet::iterator iter = set->begin(); iter != set->end(); ++ iter ) @@ -1703,7 +1703,7 @@ ConsoleDocClass( GuiInspectorTypeSFXStateName, "@internal" ); -void GuiInspectorTypeSFXStateName::_populateMenu( GuiPopUpMenuCtrl *menu ) +void GuiInspectorTypeSFXStateName::_populateMenu(GuiPopUpMenuCtrlEx *menu ) { menu->addEntry( "", 0 ); @@ -1737,7 +1737,7 @@ ConsoleDocClass( GuiInspectorTypeSFXSourceName, "@internal" ); -void GuiInspectorTypeSFXSourceName::_populateMenu( GuiPopUpMenuCtrl *menu ) +void GuiInspectorTypeSFXSourceName::_populateMenu(GuiPopUpMenuCtrlEx *menu ) { menu->addEntry( "", 0 ); diff --git a/Engine/source/gui/editor/guiInspectorTypes.h b/Engine/source/gui/editor/guiInspectorTypes.h index d5cb90f93..2f9e26b31 100644 --- a/Engine/source/gui/editor/guiInspectorTypes.h +++ b/Engine/source/gui/editor/guiInspectorTypes.h @@ -45,6 +45,7 @@ #ifndef _GUITEXTEDITSLIDERCTRL_H_ #include "gui/controls/guiTextEditSliderCtrl.h" #endif +#include "gui/controls/guiPopUpCtrlEx.h" class GuiPopUpMenuCtrl; @@ -63,7 +64,7 @@ public: //----------------------------------------------------------------------------- virtual GuiControl* constructEditControl(); virtual void setValue( StringTableEntry newValue ); - virtual void _populateMenu( GuiPopUpMenuCtrl *menu ); + virtual void _populateMenu( GuiPopUpMenuCtrlEx *menu ); }; //----------------------------------------------------------------------------- @@ -77,7 +78,7 @@ public: DECLARE_CONOBJECT(GuiInspectorTypeEnum); static void consoleInit(); - virtual void _populateMenu( GuiPopUpMenuCtrl *menu ); + virtual void _populateMenu(GuiPopUpMenuCtrlEx *menu ); }; //----------------------------------------------------------------------------- @@ -91,7 +92,7 @@ public: DECLARE_CONOBJECT(GuiInspectorTypeCubemapName); static void consoleInit(); - virtual void _populateMenu( GuiPopUpMenuCtrl *menu ); + virtual void _populateMenu(GuiPopUpMenuCtrlEx *menu ); }; //-------------------------------------------------------------------------------- @@ -129,7 +130,7 @@ public: GuiInspectorTypeRegularMaterialName() {} DECLARE_CONOBJECT(GuiInspectorTypeRegularMaterialName); static void consoleInit(); - virtual void _populateMenu( GuiPopUpMenuCtrl *menu ); + virtual void _populateMenu(GuiPopUpMenuCtrlEx *menu ); }; //-------------------------------------------------------------------------------- @@ -183,7 +184,7 @@ public: DECLARE_CONOBJECT(GuiInspectorTypeGuiProfile); static void consoleInit(); - virtual void _populateMenu( GuiPopUpMenuCtrl *menu ); + virtual void _populateMenu(GuiPopUpMenuCtrlEx *menu ); }; //----------------------------------------------------------------------------- @@ -197,7 +198,7 @@ public: DECLARE_CONOBJECT(GuiInspectorTypeActionMap); static void consoleInit(); - virtual void _populateMenu(GuiPopUpMenuCtrl* menu); + virtual void _populateMenu(GuiPopUpMenuCtrlEx * menu); }; //----------------------------------------------------------------------------- @@ -561,7 +562,7 @@ public: DECLARE_CONOBJECT(GuiInspectorTypeSFXParameterName); static void consoleInit(); - virtual void _populateMenu( GuiPopUpMenuCtrl *menu ); + virtual void _populateMenu(GuiPopUpMenuCtrlEx *menu ); }; @@ -576,7 +577,7 @@ public: DECLARE_CONOBJECT(GuiInspectorTypeSFXStateName); static void consoleInit(); - virtual void _populateMenu( GuiPopUpMenuCtrl *menu ); + virtual void _populateMenu(GuiPopUpMenuCtrlEx *menu ); }; @@ -591,7 +592,7 @@ public: DECLARE_CONOBJECT(GuiInspectorTypeSFXSourceName); static void consoleInit(); - virtual void _populateMenu( GuiPopUpMenuCtrl *menu ); + virtual void _populateMenu(GuiPopUpMenuCtrlEx *menu ); }; //----------------------------------------------------------------------------- diff --git a/Engine/source/gui/editor/inspector/datablockField.cpp b/Engine/source/gui/editor/inspector/datablockField.cpp index cce8cb443..bd6962add 100644 --- a/Engine/source/gui/editor/inspector/datablockField.cpp +++ b/Engine/source/gui/editor/inspector/datablockField.cpp @@ -32,6 +32,7 @@ #include "sfx/sfxEnvironment.h" #include "sfx/sfxAmbience.h" #include "sfx/sfxTrack.h" +#include "T3D/gameBase/gameBase.h" //----------------------------------------------------------------------------- @@ -64,30 +65,158 @@ void GuiInspectorDatablockField::setClassName( StringTableEntry className ) } } -void GuiInspectorDatablockField::_populateMenu( GuiPopUpMenuCtrl* menu ) +void GuiInspectorDatablockField::_populateMenu( GuiPopUpMenuCtrlEx* menu ) { + menu->setCanSearch(true); menu->addScheme( 1, ColorI( 80, 0, 0, 255 ), ColorI( 80, 0, 0, 255 ), ColorI( 80, 0, 0, 255 ) ); // For client-only coloring. menu->addEntry( "", 0 ); // For unsetting. SimSet* set = _getDatablockSet(); U32 id = 1; - for( SimSet::iterator iter = set->begin(); iter != set->end(); ++ iter ) + //We can do some special filtering here if it's derived from GameBase a la categories + if(mDesiredClass->isSubclassOf(AbstractClassRep::findClassRep("GameBaseData"))) { - SimDataBlock* datablock = dynamic_cast< SimDataBlock* >( *iter ); + //First, do categories + Vector categories; + for (SimSet::iterator iter = set->begin(); iter != set->end(); ++iter) + { + SimDataBlock* datablock = dynamic_cast(*iter); + + // Skip non-datablocks if we somehow encounter them. + if (!datablock) + continue; + + if (datablock && (!mDesiredClass || datablock->getClassRep()->isClass(mDesiredClass))) + { + GameBaseData *data = dynamic_cast(datablock); + if(data) + { + String category = data->mCategory; + if(category.isNotEmpty() && (categories.empty() || categories.find_next(category) == -1)) + categories.push_back(category); + } + } + } + + if (categories.size() > 0) + { + categories.push_back("No Category"); + + //Now that we have our categories, lets populate our list + for (Vector::iterator catIter = categories.begin(); catIter != categories.end(); ++catIter) + { + String categoryName = String::ToLower(catIter->c_str()); + if (categoryName != String::EmptyString) + { + menu->addCategory(catIter->c_str()); + id++; + } + + for (SimSet::iterator iter = set->begin(); iter != set->end(); ++iter) + { + GameBaseData* datablock = dynamic_cast(*iter); + + // Skip non-datablocks if we somehow encounter them. + if (!datablock) + continue; + + String dbCategory = String(datablock->mCategory).isEmpty() ? String("no category") : String::ToLower(datablock->mCategory); + + if (datablock && (!mDesiredClass || datablock->getClassRep()->isClass(mDesiredClass)) && (dbCategory == categoryName)) + { + menu->addEntry(datablock->getName(), id++, datablock->isClientOnly() ? 1 : 0, true); + } + } + } + + return; + } + } + + for (SimSet::iterator iter = set->begin(); iter != set->end(); ++iter) + { + SimDataBlock* datablock = dynamic_cast(*iter); // Skip non-datablocks if we somehow encounter them. - if( !datablock ) + if (!datablock) continue; // Ok, now we have to figure inheritance info. - if( datablock && ( !mDesiredClass || datablock->getClassRep()->isClass( mDesiredClass ) ) ) - menu->addEntry( datablock->getName(), id ++, datablock->isClientOnly() ? 1 : 0 ); + if (datablock && (!mDesiredClass || datablock->getClassRep()->isClass(mDesiredClass))) + menu->addEntry(datablock->getName(), id++, datablock->isClientOnly() ? 1 : 0); } menu->sort(); } +GuiControl* GuiInspectorDatablockField::constructEditControl() +{ + // Create base filename edit controls + GuiControl* retCtrl = Parent::constructEditControl(); + if (retCtrl == NULL) + return retCtrl; + + char szBuffer[512]; + + // Create "Open in Editor" button + mEditButton = new GuiButtonCtrl(); + dSprintf(szBuffer, sizeof(szBuffer), "DatablockEditorPlugin.openDatablock(%d.getText());", retCtrl->getId()); + mEditButton->setField("Command", szBuffer); + mEditButton->setText("..."); + + mEditButton->setDataField(StringTable->insert("Profile"), NULL, "GuiInspectorButtonProfile"); + mEditButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile"); + mEditButton->setDataField(StringTable->insert("hovertime"), NULL, "1000"); + mEditButton->setDataField(StringTable->insert("tooltip"), NULL, "Edit this datablock"); + + mEditButton->registerObject(); + addObject(mEditButton); + + //Add add button + mAddButton = new GuiBitmapButtonCtrl(); + dSprintf(szBuffer, sizeof(szBuffer), "DatablockEditorPlugin.createNewDatablockOfType(%s, %d.getText());", mDesiredClass->getClassName(), retCtrl->getId()); + mAddButton->setField("Command", szBuffer); + + char addBtnBitmapName[512] = "ToolsModule:iconAdd_Image"; + mAddButton->setBitmap(StringTable->insert(addBtnBitmapName)); + + mAddButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile"); + mAddButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile"); + mAddButton->setDataField(StringTable->insert("hovertime"), NULL, "1000"); + mAddButton->setDataField(StringTable->insert("tooltip"), NULL, "Create new datablock"); + + mAddButton->registerObject(); + addObject(mAddButton); + + return retCtrl; +} + +bool GuiInspectorDatablockField::updateRects() +{ + S32 dividerPos, dividerMargin; + mInspector->getDivider(dividerPos, dividerMargin); + Point2I fieldExtent = getExtent(); + Point2I fieldPos = getPosition(); + + mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y); + mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y); + + bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent); + if (mEditButton != NULL) + { + mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4); + resized |= mEditButton->resize(mBrowseRect.point, mBrowseRect.extent); + } + + if (mAddButton != NULL) + { + RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4); + resized |= mAddButton->resize(shapeEdRect.point, shapeEdRect.extent); + } + + return resized; +} //----------------------------------------------------------------------------- // GuiInspectorTypeSFXDescriptionName diff --git a/Engine/source/gui/editor/inspector/datablockField.h b/Engine/source/gui/editor/inspector/datablockField.h index f08a51072..b12224766 100644 --- a/Engine/source/gui/editor/inspector/datablockField.h +++ b/Engine/source/gui/editor/inspector/datablockField.h @@ -23,6 +23,7 @@ #ifndef _GUI_INSPECTOR_DATABLOCKFIELD_H_ #define _GUI_INSPECTOR_DATABLOCKFIELD_H_ +#include "gui/controls/guiPopUpCtrlEx.h" #include "gui/editor/guiInspectorTypes.h" @@ -38,9 +39,14 @@ class GuiInspectorDatablockField : public GuiInspectorTypeMenuBase protected: AbstractClassRep *mDesiredClass; + SimObjectPtr mAddButton; + SimObjectPtr mEditButton; + RectI mBrowseRect; virtual SimSet* _getDatablockSet() const { return Sim::getDataBlockSet(); } - virtual void _populateMenu( GuiPopUpMenuCtrl* menu ); + virtual void _populateMenu( GuiPopUpMenuCtrlEx* menu ); + virtual GuiControl* constructEditControl(); + virtual bool updateRects(); public: diff --git a/Templates/BaseGame/game/tools/datablockEditor/datablockEditor.tscript b/Templates/BaseGame/game/tools/datablockEditor/datablockEditor.tscript index 2fa9cc30a..5f9d23d78 100644 --- a/Templates/BaseGame/game/tools/datablockEditor/datablockEditor.tscript +++ b/Templates/BaseGame/game/tools/datablockEditor/datablockEditor.tscript @@ -629,10 +629,21 @@ function DatablockEditorPlugin::deleteDatablock( %this ) } //--------------------------------------------------------------------------------------------- +function DatablockEditorPlugin::createNewDatablockOfType(%this, %class, %inheritFrom) +{ + $DATABLOCK_EDITOR_NEWDB_CLASS = %class; + $DATABLOCK_EDITOR_NEWDB_INHERITFROM = %inheritFrom; + + %this.pickDatablockPath(); +} function DatablockEditorPlugin::createDatablock(%this) { - %class = DatablockEditorTypeTree.getItemText(DatablockEditorTypeTree.getSelectedItem()); + if($DATABLOCK_EDITOR_NEWDB_CLASS $= "") + %class = DatablockEditorTypeTree.getItemText(DatablockEditorTypeTree.getSelectedItem()); + else + %class = $DATABLOCK_EDITOR_NEWDB_CLASS; + if( %class !$= "" ) { // Need to prompt for a name. @@ -659,6 +670,12 @@ function DatablockEditorPlugin::createDatablock(%this) %list.add( %datablock.getName(), %i + 1 ); } + if($DATABLOCK_EDITOR_NEWDB_INHERITFROM !$= "") + { + %inheritFromListId = %list.findText($DATABLOCK_EDITOR_NEWDB_INHERITFROM); + %list.setSelected(%inheritFromListId); + } + // Set up state of client-side checkbox. %clientSideCheckBox = DatablockEditorCreatePrompt-->ClientSideCheckBox; @@ -717,7 +734,11 @@ function DatablockEditorPlugin::createPromptNameCheck(%this, %path) function DatablockEditorPlugin::createDatablockFinish( %this, %name, %copySource ) { - %class = DatablockEditorTypeTree.getItemText(DatablockEditorTypeTree.getSelectedItem()); + if($DATABLOCK_EDITOR_NEWDB_CLASS $= "") + %class = DatablockEditorTypeTree.getItemText(DatablockEditorTypeTree.getSelectedItem()); + else + %class = $DATABLOCK_EDITOR_NEWDB_CLASS; + if( %class !$= "" ) { %action = %this.createUndo( ActionCreateDatablock, "Create New Datablock" ); @@ -742,6 +763,8 @@ function DatablockEditorPlugin::createDatablockFinish( %this, %name, %copySource %action.redo(); } + + $DATABLOCK_EDITOR_NEWDB_CLASS = ""; } //---------------------------------------------------------------------------------------------