From af14de2bb773a2028380ef9ab2705d1e23cceb68 Mon Sep 17 00:00:00 2001 From: Areloch Date: Fri, 17 May 2019 01:48:45 -0500 Subject: [PATCH 1/2] Implements a Material Instance viewer to the material editor to see a feature-filtered dump of the generated shaders for a given material. --- Engine/source/materials/baseMatInstance.h | 3 +- Engine/source/materials/matInstance.cpp | 34 ++++ Engine/source/materials/matInstance.h | 3 +- .../source/materials/materialDefinition.cpp | 15 +- Engine/source/materials/materialManager.cpp | 41 +++++ Engine/source/materials/materialManager.h | 3 + Engine/source/materials/processedMaterial.h | 4 +- .../materials/processedShaderMaterial.cpp | 25 ++- .../materials/processedShaderMaterial.h | 2 +- .../gui/guiMaterialPropertiesWindow.ed.gui | 27 ++- .../gui/materialInstancesView.ed.gui | 170 ++++++++++++++++++ .../game/tools/materialEditor/main.cs | 4 + .../scripts/materialEditor.ed.cs | 26 +++ .../scripts/materialInstanceView.ed.cs | 27 +++ .../gui/guiMaterialPropertiesWindow.ed.gui | 27 ++- .../gui/materialInstancesView.ed.gui | 170 ++++++++++++++++++ .../Full/game/tools/materialEditor/main.cs | 4 + .../scripts/materialEditor.ed.cs | 26 +++ .../scripts/materialInstanceView.ed.cs | 27 +++ 19 files changed, 626 insertions(+), 12 deletions(-) create mode 100644 Templates/BaseGame/game/tools/materialEditor/gui/materialInstancesView.ed.gui create mode 100644 Templates/BaseGame/game/tools/materialEditor/scripts/materialInstanceView.ed.cs create mode 100644 Templates/Full/game/tools/materialEditor/gui/materialInstancesView.ed.gui create mode 100644 Templates/Full/game/tools/materialEditor/scripts/materialInstanceView.ed.cs diff --git a/Engine/source/materials/baseMatInstance.h b/Engine/source/materials/baseMatInstance.h index bca878dc2..3fcf09208 100644 --- a/Engine/source/materials/baseMatInstance.h +++ b/Engine/source/materials/baseMatInstance.h @@ -59,7 +59,7 @@ struct GFXStateBlockDesc; class GFXVertexFormat; class MatrixSet; class ProcessedMaterial; - +class GuiTreeViewCtrl; /// class BaseMatInstance @@ -216,6 +216,7 @@ public: virtual const GFXVertexFormat* getVertexFormat() const = 0; virtual void dumpShaderInfo() const = 0; + virtual void getShaderInfo(GuiTreeViewCtrl* tree, U32 item) const = 0; /// Fast test for use of normal maps in this material. bool hasNormalMap() const { return mHasNormalMaps; } diff --git a/Engine/source/materials/matInstance.cpp b/Engine/source/materials/matInstance.cpp index e242a2059..473e9ef52 100644 --- a/Engine/source/materials/matInstance.cpp +++ b/Engine/source/materials/matInstance.cpp @@ -37,6 +37,8 @@ #include "core/util/safeDelete.h" #include "ts/tsShape.h" +#include "gui/controls/guiTreeViewCtrl.h" + class MatInstParameters; class MatInstanceParameterHandle : public MaterialParameterHandle @@ -591,3 +593,35 @@ void MatInstance::dumpShaderInfo() const mProcessedMaterial->dumpMaterialInfo(); } + +void MatInstance::getShaderInfo(GuiTreeViewCtrl* tree, U32 item) const +{ + if (mMaterial == NULL) + { + Con::errorf("Trying to get Material information on an invalid MatInstance"); + return; + } + + if (mProcessedMaterial == NULL) + { + Con::printf(" [no processed material!]"); + return; + } + + const FeatureSet features = mProcessedMaterial->getFeatures(); + + String featureDesc = ""; + for (U32 i = 0; i < features.getCount(); i++) + { + const FeatureType& ft = features.getAt(i); + + featureDesc += ft.getName(); + + if(i+1 < features.getCount()) + featureDesc += ", "; + } + + U32 newItem = tree->insertItem(item, featureDesc); + + mProcessedMaterial->getMaterialInfo(tree, newItem); +} diff --git a/Engine/source/materials/matInstance.h b/Engine/source/materials/matInstance.h index 11178a42c..4a2a11d7c 100644 --- a/Engine/source/materials/matInstance.h +++ b/Engine/source/materials/matInstance.h @@ -44,7 +44,7 @@ class ShaderFeature; class MatInstanceParameterHandle; class MatInstParameters; class ProcessedMaterial; - +class GuiTreeViewCtrl; /// class MatInstance : public BaseMatInstance @@ -86,6 +86,7 @@ public: virtual const FeatureSet& getFeatures() const; virtual const FeatureSet& getRequestedFeatures() const { return mFeatureList; } virtual void dumpShaderInfo() const; + virtual void getShaderInfo(GuiTreeViewCtrl* tree, U32 item) const; ProcessedMaterial *getProcessedMaterial() const { return mProcessedMaterial; } diff --git a/Engine/source/materials/materialDefinition.cpp b/Engine/source/materials/materialDefinition.cpp index 9fd3f857a..9790db15e 100644 --- a/Engine/source/materials/materialDefinition.cpp +++ b/Engine/source/materials/materialDefinition.cpp @@ -36,7 +36,7 @@ #include "sfx/sfxTypes.h" #include "core/util/safeDelete.h" #include "T3D/accumulationVolume.h" - +#include "gui/controls/guiTreeViewCtrl.h" IMPLEMENT_CONOBJECT( Material ); @@ -647,6 +647,12 @@ DefineEngineMethod( Material, dumpInstances, void, (),, MATMGR->dumpMaterialInstances( object ); } +DefineEngineMethod(Material, getMaterialInstances, void, (GuiTreeViewCtrl* matTree), (nullAsType< GuiTreeViewCtrl*>()), + "Dumps a formatted list of the currently allocated material instances for this material to the console.") +{ + MATMGR->getMaterialInstances(object, matTree); +} + DefineEngineMethod( Material, getAnimFlags, const char*, (U32 id), , "" ) { char * animFlags = Con::getReturnBuffer(512); @@ -706,6 +712,13 @@ DefineEngineMethod( Material, setAutoGenerated, void, (bool isAutoGenerated), , object->setAutoGenerated(isAutoGenerated); } +DefineEngineMethod(Material, getAutogeneratedFile, const char*, (), , "Get filename of autogenerated shader file") +{ + SimObject *material = static_cast(object); + return material->getFilename(); +} + + // Accumulation bool Material::_setAccuEnabled( void *object, const char *index, const char *data ) { diff --git a/Engine/source/materials/materialManager.cpp b/Engine/source/materials/materialManager.cpp index 0f8519bb5..648694601 100644 --- a/Engine/source/materials/materialManager.cpp +++ b/Engine/source/materials/materialManager.cpp @@ -32,6 +32,7 @@ #include "console/consoleTypes.h" #include "console/engineAPI.h" +#include "gui/controls/guiTreeViewCtrl.h" MODULE_BEGIN( MaterialManager ) @@ -399,6 +400,36 @@ void MaterialManager::dumpMaterialInstances( BaseMaterialDefinition *target ) co Con::printf( "---------------------- Dump complete ----------------------"); } +void MaterialManager::getMaterialInstances(BaseMaterialDefinition* target, GuiTreeViewCtrl* materailInstanceTree) +{ + if (!mMatInstanceList.size()) + return; + + if (!target) + { + Con::errorf("Can't form a list without a specific MaterialDefinition"); + return; + } + + if (!materailInstanceTree) + { + Con::errorf("Requires a valid GuiTreeViewCtrl object to populate data into!"); + return; + } + + U32 matItem = materailInstanceTree->insertItem(0, target->getName()); + + for (U32 i = 0; i < mMatInstanceList.size(); i++) + { + BaseMatInstance* inst = mMatInstanceList[i]; + + if (target && inst->getMaterial() != target) + continue; + + inst->getShaderInfo(materailInstanceTree, matItem); + } +} + void MaterialManager::_track( MatInstance *matInstance ) { mMatInstanceList.push_back( matInstance ); @@ -488,6 +519,16 @@ DefineEngineFunction( dumpMaterialInstances, void, (), , MATMGR->dumpMaterialInstances(); } +DefineEngineFunction(getMaterialInstances, void, (BaseMaterialDefinition* target, GuiTreeViewCtrl* tree), (nullAsType(), nullAsType()), + "@brief Dumps a formatted list of currently allocated material instances to the console.\n\n" + "@ingroup Materials") +{ + if (target == nullptr || tree == nullptr) + return; + + MATMGR->getMaterialInstances(target, tree); +} + DefineEngineFunction( getMapEntry, const char*, (const char * texName), , "@hide") { diff --git a/Engine/source/materials/materialManager.h b/Engine/source/materials/materialManager.h index b038f33a6..809a69f20 100644 --- a/Engine/source/materials/materialManager.h +++ b/Engine/source/materials/materialManager.h @@ -37,6 +37,7 @@ class SimSet; class MatInstance; +class GuiTreeViewCtrl; class MaterialManager : public ManagedSingleton { @@ -97,6 +98,8 @@ public: void dumpMaterialInstances( BaseMaterialDefinition *target = NULL ) const; + void getMaterialInstances(BaseMaterialDefinition* target, GuiTreeViewCtrl* tree); + void updateTime(); F32 getTotalTime() const { return mAccumTime; } F32 getDeltaTime() const { return mDt; } diff --git a/Engine/source/materials/processedMaterial.h b/Engine/source/materials/processedMaterial.h index 3c3f97a88..619298dda 100644 --- a/Engine/source/materials/processedMaterial.h +++ b/Engine/source/materials/processedMaterial.h @@ -46,7 +46,7 @@ class SceneRenderState; class GFXVertexBufferHandleBase; class GFXPrimitiveBufferHandle; class MatrixSet; - +class GuiTreeViewCtrl; /// This contains the common data needed to render a pass. struct RenderPassData @@ -218,6 +218,8 @@ public: /// Dump shader info, or FF texture info? virtual void dumpMaterialInfo() { } + virtual void getMaterialInfo(GuiTreeViewCtrl* tree, U32 item) {} + /// Returns the source material. Material* getMaterial() const { return mMaterial; } diff --git a/Engine/source/materials/processedShaderMaterial.cpp b/Engine/source/materials/processedShaderMaterial.cpp index e433a354c..68491cf37 100644 --- a/Engine/source/materials/processedShaderMaterial.cpp +++ b/Engine/source/materials/processedShaderMaterial.cpp @@ -44,7 +44,7 @@ // We need to include customMaterialDefinition for ShaderConstHandles::init #include "materials/customMaterialDefinition.h" - +#include "gui/controls/guiTreeViewCtrl.h" #include "ts/tsShape.h" /// @@ -1421,3 +1421,26 @@ void ProcessedShaderMaterial::dumpMaterialInfo() Con::printf( " [%i] %s", i, shader->describeSelf().c_str() ); } } + +void ProcessedShaderMaterial::getMaterialInfo(GuiTreeViewCtrl* tree, U32 item) +{ + for (U32 i = 0; i < getNumPasses(); i++) + { + const ShaderRenderPassData* passData = _getRPD(i); + + if (passData == NULL) + continue; + + char passStr[64]; + dSprintf(passStr, 64, "Pass Number: %i", i); + + U32 passItem = tree->insertItem(item, passStr); + + const GFXShader * shader = passData->shader; + + if (shader == NULL) + tree->insertItem(passItem, "[NULL shader]"); + else + tree->insertItem(passItem, shader->describeSelf().c_str()); + } +} diff --git a/Engine/source/materials/processedShaderMaterial.h b/Engine/source/materials/processedShaderMaterial.h index ee0781b95..e2579423a 100644 --- a/Engine/source/materials/processedShaderMaterial.h +++ b/Engine/source/materials/processedShaderMaterial.h @@ -37,7 +37,6 @@ class ShaderMaterialParameterHandle; class ShaderFeatureConstHandles; class CustomMaterial; - class ShaderConstHandles { public: @@ -136,6 +135,7 @@ public: virtual void setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer); virtual bool stepInstance(); virtual void dumpMaterialInfo(); + virtual void getMaterialInfo(GuiTreeViewCtrl* tree, U32 item); virtual MaterialParameters* allocMaterialParameters(); virtual MaterialParameters* getDefaultMaterialParameters() { return mDefaultParameters; } virtual MaterialParameterHandle* getMaterialParameterHandle(const String& name); diff --git a/Templates/BaseGame/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui b/Templates/BaseGame/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui index 328d946b6..2a8697eae 100644 --- a/Templates/BaseGame/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui +++ b/Templates/BaseGame/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui @@ -3615,7 +3615,7 @@ isContainer = "0"; HorizSizing = "left"; VertSizing = "bottom"; - position = "86 1"; + position = "66 1"; Extent = "16 16"; MinExtent = "8 2"; canSave = "1"; @@ -3636,7 +3636,7 @@ Profile = "ToolsGuiDefaultProfile"; HorizSizing = "left"; VertSizing = "bottom"; - position = "106 1"; + position = "86 1"; Extent = "16 16"; MinExtent = "8 2"; canSave = "1"; @@ -3658,7 +3658,7 @@ Profile = "ToolsGuiDefaultProfile"; HorizSizing = "left"; VertSizing = "bottom"; - position = "123 1"; + position = "106 1"; Extent = "16 16"; MinExtent = "8 2"; canSave = "1"; @@ -3672,6 +3672,27 @@ useMouseEvents = "0"; bitmap = "tools/gui/images/save-icon"; }; + new GuiBitmapButtonCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "ToolsGuiDefaultProfile"; + HorizSizing = "left"; + VertSizing = "bottom"; + position = "126 1"; + Extent = "16 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.lookupMaterialInstances();"; + hovertime = "1000"; + groupNum = "-1"; + text =""; + tooltip = "Lookup Material Instances"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "tools/gui/images/visible"; + }; new GuiBitmapCtrl(){ position = "147 1"; Extent = "2 16"; diff --git a/Templates/BaseGame/game/tools/materialEditor/gui/materialInstancesView.ed.gui b/Templates/BaseGame/game/tools/materialEditor/gui/materialInstancesView.ed.gui new file mode 100644 index 000000000..ce5c683de --- /dev/null +++ b/Templates/BaseGame/game/tools/materialEditor/gui/materialInstancesView.ed.gui @@ -0,0 +1,170 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(MaterialInstanceViewCtrl) { + position = "0 0"; + extent = "1024 768"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + new GuiWindowCtrl(MaterialInstanceViewWindow) { + text = "Material Instances Viewer"; + resizeWidth = "1"; + resizeHeight = "1"; + canMove = "1"; + canClose = "1"; + canMinimize = "1"; + canMaximize = "1"; + canCollapse = "0"; + closeCommand = "Canvas.popDialog(MaterialInstanceViewCtrl);"; + edgeSnap = "1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "429 123"; + extent = "550 550"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiWindowProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextEditCtrl(MaterialInstanceFilter) { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "\c2Filter..."; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "11 21"; + extent = "516 18"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + class = "AssetBrowserSearchFilterText"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl(MaterialInstanceFilterBtn) { + bitmap = "tools/gui/images/delete"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "529 22"; + extent = "15 15"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Delete Asset"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiScrollCtrl() { + willFirstRespond = "1"; + hScrollBar = "dynamic"; + vScrollBar = "dynamic"; + lockHorizScroll = "0"; + lockVertScroll = "0"; + constantThumbHeight = "0"; + childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 38"; + extent = "550 510"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiScrollProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTreeViewCtrl(MaterialInstanceViewTree) { + tabSize = "16"; + textOffset = "2"; + fullRowSelect = "0"; + itemHeight = "21"; + destroyTreeOnSleep = "1"; + mouseDragging = "1"; + multipleSelections = "1"; + deleteObjectAllowed = "1"; + dragToItemAllowed = "1"; + clearAllOnSingleSelection = "1"; + showRoot = "1"; + useInspectorTooltips = "0"; + tooltipOnWidthOnly = "0"; + showObjectIds = "1"; + showClassNames = "1"; + showObjectNames = "1"; + showInternalNames = "1"; + showClassNameForUnnamedObjects = "0"; + compareToObjectID = "1"; + canRenameObjects = "1"; + renameInternal = "0"; + position = "1 1"; + extent = "550 510"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiTreeViewProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + }; +}; +//--- OBJECT WRITE END --- diff --git a/Templates/BaseGame/game/tools/materialEditor/main.cs b/Templates/BaseGame/game/tools/materialEditor/main.cs index 4751676fe..a3262c2f5 100644 --- a/Templates/BaseGame/game/tools/materialEditor/main.cs +++ b/Templates/BaseGame/game/tools/materialEditor/main.cs @@ -32,9 +32,13 @@ function initializeMaterialEditor() // Load Properties Window exec("~/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui"); + //Material Instance viewer + exec("~/materialEditor/gui/materialInstancesView.ed.gui"); + // Load Client Scripts. exec("./scripts/materialEditor.ed.cs"); exec("./scripts/materialEditorUndo.ed.cs"); + exec("./scripts/materialInstanceView.ed.cs"); //exec("./gui/profiles.ed.cs"); MaterialEditorPreviewWindow.setVisible( false ); diff --git a/Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.cs b/Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.cs index 30c5dac26..500a43240 100644 --- a/Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.cs +++ b/Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.cs @@ -2116,6 +2116,32 @@ function MaterialEditorGui::refreshMaterial(%this) MaterialEditorGui.setMaterialNotDirty(); } +//============================================================================== +// Looking up material instances/getting mat info +function MaterialEditorGui::lookupMaterialInstances( %this ) +{ + if( MaterialEditorGui.currentMaterial.getName() $= "" ) + { + MessageBoxOK("Cannot perform operation", "Unable to look up a material with a blank name" ); + return; + } + + MaterialInstanceViewTree.clear(); + MaterialInstanceViewTree.setFilterChildren(false); + MaterialInstanceViewTree.setItemFilterException(1, true); + + MaterialEditorGui.currentMaterial.getMaterialInstances(MaterialInstanceViewTree); + + if(MaterialInstanceFilter.Text !$= "\c2Filter...") + { + MaterialInstanceViewTree.setFilterText(MaterialInstanceFilter.Text); + } + + MaterialInstanceViewTree.buildVisibleTree(true); + + Canvas.pushDialog(MaterialInstanceViewCtrl); +} + //============================================================================== // Switching and Changing Materials diff --git a/Templates/BaseGame/game/tools/materialEditor/scripts/materialInstanceView.ed.cs b/Templates/BaseGame/game/tools/materialEditor/scripts/materialInstanceView.ed.cs new file mode 100644 index 000000000..e341374ca --- /dev/null +++ b/Templates/BaseGame/game/tools/materialEditor/scripts/materialInstanceView.ed.cs @@ -0,0 +1,27 @@ +function MaterialInstanceFilter::onGainFirstResponder( %this ) +{ + %this.selectAllText(); +} + +function MaterialInstanceFilter::onReturn( %this ) +{ + %text = %this.getText(); + if( %text $= "" ) + { + %this.reset(); + MaterialInstanceViewTree.clearFilterText(); + } + else + { + MaterialInstanceViewTree.setFilterText(%text); + } + + MaterialInstanceViewTree.buildVisibleTree(true); +} + +function MaterialInstanceFilterBtn::onClick(%this) +{ + MaterialInstanceFilter.reset(); + MaterialInstanceViewTree.clearFilterText(); + MaterialInstanceViewTree.buildVisibleTree(true); +} \ No newline at end of file diff --git a/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui b/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui index 328d946b6..2a8697eae 100644 --- a/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui +++ b/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui @@ -3615,7 +3615,7 @@ isContainer = "0"; HorizSizing = "left"; VertSizing = "bottom"; - position = "86 1"; + position = "66 1"; Extent = "16 16"; MinExtent = "8 2"; canSave = "1"; @@ -3636,7 +3636,7 @@ Profile = "ToolsGuiDefaultProfile"; HorizSizing = "left"; VertSizing = "bottom"; - position = "106 1"; + position = "86 1"; Extent = "16 16"; MinExtent = "8 2"; canSave = "1"; @@ -3658,7 +3658,7 @@ Profile = "ToolsGuiDefaultProfile"; HorizSizing = "left"; VertSizing = "bottom"; - position = "123 1"; + position = "106 1"; Extent = "16 16"; MinExtent = "8 2"; canSave = "1"; @@ -3672,6 +3672,27 @@ useMouseEvents = "0"; bitmap = "tools/gui/images/save-icon"; }; + new GuiBitmapButtonCtrl() { + canSaveDynamicFields = "0"; + Enabled = "1"; + isContainer = "0"; + Profile = "ToolsGuiDefaultProfile"; + HorizSizing = "left"; + VertSizing = "bottom"; + position = "126 1"; + Extent = "16 16"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + Command = "MaterialEditorGui.lookupMaterialInstances();"; + hovertime = "1000"; + groupNum = "-1"; + text =""; + tooltip = "Lookup Material Instances"; + buttonType = "PushButton"; + useMouseEvents = "0"; + bitmap = "tools/gui/images/visible"; + }; new GuiBitmapCtrl(){ position = "147 1"; Extent = "2 16"; diff --git a/Templates/Full/game/tools/materialEditor/gui/materialInstancesView.ed.gui b/Templates/Full/game/tools/materialEditor/gui/materialInstancesView.ed.gui new file mode 100644 index 000000000..ce5c683de --- /dev/null +++ b/Templates/Full/game/tools/materialEditor/gui/materialInstancesView.ed.gui @@ -0,0 +1,170 @@ +//--- OBJECT WRITE BEGIN --- +%guiContent = new GuiControl(MaterialInstanceViewCtrl) { + position = "0 0"; + extent = "1024 768"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "GuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + + new GuiWindowCtrl(MaterialInstanceViewWindow) { + text = "Material Instances Viewer"; + resizeWidth = "1"; + resizeHeight = "1"; + canMove = "1"; + canClose = "1"; + canMinimize = "1"; + canMaximize = "1"; + canCollapse = "0"; + closeCommand = "Canvas.popDialog(MaterialInstanceViewCtrl);"; + edgeSnap = "1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "429 123"; + extent = "550 550"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiWindowProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextEditCtrl(MaterialInstanceFilter) { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "\c2Filter..."; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "11 21"; + extent = "516 18"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + class = "AssetBrowserSearchFilterText"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl(MaterialInstanceFilterBtn) { + bitmap = "tools/gui/images/delete"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "529 22"; + extent = "15 15"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + tooltip = "Delete Asset"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiScrollCtrl() { + willFirstRespond = "1"; + hScrollBar = "dynamic"; + vScrollBar = "dynamic"; + lockHorizScroll = "0"; + lockVertScroll = "0"; + constantThumbHeight = "0"; + childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 38"; + extent = "550 510"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiScrollProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTreeViewCtrl(MaterialInstanceViewTree) { + tabSize = "16"; + textOffset = "2"; + fullRowSelect = "0"; + itemHeight = "21"; + destroyTreeOnSleep = "1"; + mouseDragging = "1"; + multipleSelections = "1"; + deleteObjectAllowed = "1"; + dragToItemAllowed = "1"; + clearAllOnSingleSelection = "1"; + showRoot = "1"; + useInspectorTooltips = "0"; + tooltipOnWidthOnly = "0"; + showObjectIds = "1"; + showClassNames = "1"; + showObjectNames = "1"; + showInternalNames = "1"; + showClassNameForUnnamedObjects = "0"; + compareToObjectID = "1"; + canRenameObjects = "1"; + renameInternal = "0"; + position = "1 1"; + extent = "550 510"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiTreeViewProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + }; +}; +//--- OBJECT WRITE END --- diff --git a/Templates/Full/game/tools/materialEditor/main.cs b/Templates/Full/game/tools/materialEditor/main.cs index 4751676fe..a3262c2f5 100644 --- a/Templates/Full/game/tools/materialEditor/main.cs +++ b/Templates/Full/game/tools/materialEditor/main.cs @@ -32,9 +32,13 @@ function initializeMaterialEditor() // Load Properties Window exec("~/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui"); + //Material Instance viewer + exec("~/materialEditor/gui/materialInstancesView.ed.gui"); + // Load Client Scripts. exec("./scripts/materialEditor.ed.cs"); exec("./scripts/materialEditorUndo.ed.cs"); + exec("./scripts/materialInstanceView.ed.cs"); //exec("./gui/profiles.ed.cs"); MaterialEditorPreviewWindow.setVisible( false ); diff --git a/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs b/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs index 5d4a9a7ba..f4282cd72 100644 --- a/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs +++ b/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs @@ -2116,6 +2116,32 @@ function MaterialEditorGui::refreshMaterial(%this) MaterialEditorGui.setMaterialNotDirty(); } +//============================================================================== +// Looking up material instances/getting mat info +function MaterialEditorGui::lookupMaterialInstances( %this ) +{ + if( MaterialEditorGui.currentMaterial.getName() $= "" ) + { + MessageBoxOK("Cannot perform operation", "Unable to look up a material with a blank name" ); + return; + } + + MaterialInstanceViewTree.clear(); + MaterialInstanceViewTree.setFilterChildren(false); + MaterialInstanceViewTree.setItemFilterException(1, true); + + MaterialEditorGui.currentMaterial.getMaterialInstances(MaterialInstanceViewTree); + + if(MaterialInstanceFilter.Text !$= "\c2Filter...") + { + MaterialInstanceViewTree.setFilterText(MaterialInstanceFilter.Text); + } + + MaterialInstanceViewTree.buildVisibleTree(true); + + Canvas.pushDialog(MaterialInstanceViewCtrl); +} + //============================================================================== // Switching and Changing Materials diff --git a/Templates/Full/game/tools/materialEditor/scripts/materialInstanceView.ed.cs b/Templates/Full/game/tools/materialEditor/scripts/materialInstanceView.ed.cs new file mode 100644 index 000000000..e341374ca --- /dev/null +++ b/Templates/Full/game/tools/materialEditor/scripts/materialInstanceView.ed.cs @@ -0,0 +1,27 @@ +function MaterialInstanceFilter::onGainFirstResponder( %this ) +{ + %this.selectAllText(); +} + +function MaterialInstanceFilter::onReturn( %this ) +{ + %text = %this.getText(); + if( %text $= "" ) + { + %this.reset(); + MaterialInstanceViewTree.clearFilterText(); + } + else + { + MaterialInstanceViewTree.setFilterText(%text); + } + + MaterialInstanceViewTree.buildVisibleTree(true); +} + +function MaterialInstanceFilterBtn::onClick(%this) +{ + MaterialInstanceFilter.reset(); + MaterialInstanceViewTree.clearFilterText(); + MaterialInstanceViewTree.buildVisibleTree(true); +} \ No newline at end of file From 8c05e33e7e630d7395222ea93c0fb9846c93063b Mon Sep 17 00:00:00 2001 From: Areloch Date: Sat, 18 May 2019 02:37:28 -0500 Subject: [PATCH 2/2] Forgot changes to the guiTreeViewCtrl to enable advanced filtering behavior. --- .../source/gui/controls/guiTreeViewCtrl.cpp | 47 +++++++++++++++++-- Engine/source/gui/controls/guiTreeViewCtrl.h | 10 +++- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/Engine/source/gui/controls/guiTreeViewCtrl.cpp b/Engine/source/gui/controls/guiTreeViewCtrl.cpp index f9ad7e411..62f3a86a7 100644 --- a/Engine/source/gui/controls/guiTreeViewCtrl.cpp +++ b/Engine/source/gui/controls/guiTreeViewCtrl.cpp @@ -832,6 +832,8 @@ GuiTreeViewCtrl::GuiTreeViewCtrl() mTexSelected = NULL; mRenderTooltipDelegate.bind( this, &GuiTreeViewCtrl::renderTooltip ); + + mDoFilterChildren = true; } //----------------------------------------------------------------------------- @@ -1122,7 +1124,7 @@ void GuiTreeViewCtrl::_expandObjectHierarchy( SimGroup* group ) //------------------------------------------------------------------------------ -void GuiTreeViewCtrl::_buildItem( Item* item, U32 tabLevel, bool bForceFullUpdate ) +void GuiTreeViewCtrl::_buildItem( Item* item, U32 tabLevel, bool bForceFullUpdate, bool skipFlter ) { if (!item || !mActive || !isVisible() || !mProfile ) return; @@ -1145,7 +1147,7 @@ void GuiTreeViewCtrl::_buildItem( Item* item, U32 tabLevel, bool bForceFullUpdat // If we have a filter pattern, sync the item's filtering status to it. - if( !getFilterText().isEmpty() ) + if( !getFilterText().isEmpty() && !skipFlter) { // Determine the filtering status by looking for the filter // text in the item's display text. @@ -1154,7 +1156,11 @@ void GuiTreeViewCtrl::_buildItem( Item* item, U32 tabLevel, bool bForceFullUpdat item->getDisplayText( sizeof( displayText ), displayText ); if( !dStristr( displayText, mFilterText ) ) { - item->mState.set( Item::Filtered ); + //Last check, see if we special-exception this item + if (!mItemFilterExceptionList.contains(item->mId)) + item->mState.set(Item::Filtered); + else + item->mState.clear(Item::Filtered); // If it's not a parent, we're done. Otherwise, there may be children // that are not filtered so we need to process them first. @@ -1163,7 +1169,9 @@ void GuiTreeViewCtrl::_buildItem( Item* item, U32 tabLevel, bool bForceFullUpdat return; } else - item->mState.clear( Item::Filtered ); + { + item->mState.clear(Item::Filtered); + } } else item->mState.clear( Item::Filtered ); @@ -1217,7 +1225,10 @@ void GuiTreeViewCtrl::_buildItem( Item* item, U32 tabLevel, bool bForceFullUpdat Item *pChildTemp = child; child = child->mNext; - _buildItem( pChildTemp, tabLevel + 1, bForceFullUpdate ); + if (!mItemFilterExceptionList.contains(item->mId) && !mDoFilterChildren && !item->isFiltered()) + _buildItem( pChildTemp, tabLevel + 1, bForceFullUpdate, true ); + else + _buildItem(pChildTemp, tabLevel + 1, bForceFullUpdate, false); } } } @@ -4775,6 +4786,18 @@ void GuiTreeViewCtrl::setFilterText( const String& text ) mFlags.set( RebuildVisible ); } +void GuiTreeViewCtrl::setItemFilterException(U32 item, bool isExempted) +{ + if (isExempted) + { + mItemFilterExceptionList.push_back(item); + } + else + { + mItemFilterExceptionList.remove(item); + } +} + //============================================================================= // Console Methods. //============================================================================= @@ -5574,6 +5597,20 @@ DefineEngineMethod( GuiTreeViewCtrl, setFilterText, void, ( const char* pattern object->setFilterText( pattern ); } +DefineEngineMethod(GuiTreeViewCtrl, setFilterChildren, void, (bool doFilterChildren), (true), + "Sets if the filter will also apply to any children of items that manage to pass being filtered.\n\n" + "@param doFilterChildren If true, items that pass the filter do not have their children filtered. If false, all items are filtered.\n\n") +{ + object->setFilterChildren(doFilterChildren); +} + +DefineEngineMethod(GuiTreeViewCtrl, setItemFilterException, void, (U32 item, bool isExempt), (0, true), + "Set a given item to be excluded from being filtered.\n\n" + "@param item Item ID of the item that is to be exempt from the filter.\n\n" + "@param isExempt If the item is exempt from the filter.\n\n") +{ + object->setItemFilterException(item, isExempt); +} //----------------------------------------------------------------------------- DefineEngineMethod( GuiTreeViewCtrl, clearFilterText, void, (),, diff --git a/Engine/source/gui/controls/guiTreeViewCtrl.h b/Engine/source/gui/controls/guiTreeViewCtrl.h index 17b9aed04..123118db7 100644 --- a/Engine/source/gui/controls/guiTreeViewCtrl.h +++ b/Engine/source/gui/controls/guiTreeViewCtrl.h @@ -356,6 +356,11 @@ class GuiTreeViewCtrl : public GuiArrayCtrl /// Current filter that determines which items in the tree are displayed and which are hidden. String mFilterText; + /// If true, all items are filtered. If false, then children of items that successfully pass filter are not filtered + bool mDoFilterChildren; + + Vector mItemFilterExceptionList; + /// If true, a trace of actions taken by the control is logged to the console. Can /// be turned on with the setDebug() script method. bool mDebug; @@ -431,7 +436,7 @@ class GuiTreeViewCtrl : public GuiArrayCtrl void _deleteItem(Item* item); - void _buildItem(Item* item, U32 tabLevel, bool bForceFullUpdate = false); + void _buildItem(Item* item, U32 tabLevel, bool bForceFullUpdate = false, bool skipFlter = false); Item* _findItemByAmbiguousId( S32 itemOrObjectId, bool buildVirtual = true ); @@ -569,6 +574,9 @@ class GuiTreeViewCtrl : public GuiArrayCtrl /// matches this pattern are displayed. void setFilterText( const String& text ); + void setFilterChildren(bool doFilter) { mDoFilterChildren = doFilter; } + void setItemFilterException(U32 item, bool isExempt); + /// Clear the current item filtering pattern. void clearFilterText() { setFilterText( String::EmptyString ); }