From 53188a12da7d3ce90de64a0d184b6a5f9df613d8 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Wed, 12 May 2021 17:06:57 -0700 Subject: [PATCH] Made StandardMultilayerPBR hide a layer's property groups when that layer is disabled. ATOM-14688 Disable Individual Layers - Added new SetMaterialPropertyGroupVisibility functions to the material functors. - Updated the MaterialFunctor::EditorContext to include parameters for handling material property group metadata. - Updated the material inspector(s) to apply the property group visiblity changes from the material functor, to hide or show the property groups. - Moved some code from MaterialPropertyDescriptor.h/cpp to a new MaterialDynamicMetadata.h/cpp, since these aren't really related to the MaterialPropertyDescriptor code. It's more for material functors to use. - Also fixed the casing for the "GetMaterialPropertyValue_Image" lua function, since I was already in this code (ATOM-14793 "Fix Inconsistent Casing For LuaMaterialFunctorRuntimeContext") Tested in MaterialEditor and in in the main Editor's MaterialComponent property override inspector. --- .../DetailMapsCommonFunctor.lua | 8 +- .../Materials/Types/Skin_WrinkleMaps.lua | 4 +- .../Types/StandardMultilayerPBR.materialtype | 6 ++ .../StandardMultilayerPBR_LayerEnable.lua | 49 +++++++++ ...StandardMultilayerPBR_ParallaxPerLayer.lua | 4 +- .../Types/StandardPBR_ClearCoatState.lua | 4 +- .../Types/StandardPBR_EmissiveState.lua | 4 +- .../Types/StandardPBR_HandleOpacityMode.lua | 2 +- .../Types/StandardPBR_ParallaxState.lua | 4 +- .../Materials/Types/StandardPBR_Roughness.lua | 4 +- .../Types/StandardPBR_SubsurfaceState.lua | 4 +- .../RPI.Reflect/Material/LuaMaterialFunctor.h | 2 + .../Material/MaterialDynamicMetadata.h | 100 ++++++++++++++++++ .../RPI.Reflect/Material/MaterialFunctor.h | 20 +++- .../Material/MaterialPropertyDescriptor.h | 47 -------- .../RPI.Public/Material/MaterialSystem.cpp | 1 + .../Material/LuaMaterialFunctor.cpp | 17 ++- .../Material/MaterialDynamicMetadata.cpp | 50 +++++++++ .../RPI.Reflect/Material/MaterialFunctor.cpp | 96 ++++++++++++----- .../Material/MaterialPropertyDescriptor.cpp | 14 --- .../Material/LuaMaterialFunctorTests.cpp | 76 ++++++++++++- .../MaterialPropertySerializerTests.cpp | 1 + .../RPI/Code/atom_rpi_reflect_files.cmake | 2 + .../DynamicProperty/DynamicProperty.h | 6 +- .../Inspector/InspectorRequestBus.h | 6 ++ .../Inspector/InspectorWidget.h | 3 + .../Code/Source/Inspector/InspectorWidget.cpp | 27 +++++ .../MaterialDocumentNotificationBus.h | 7 ++ .../Document/MaterialDocumentRequestBus.h | 5 + .../Code/Source/Document/MaterialDocument.cpp | 58 ++++++++-- .../Code/Source/Document/MaterialDocument.h | 21 +++- .../MaterialInspector/MaterialInspector.cpp | 16 ++- .../MaterialInspector/MaterialInspector.h | 1 + .../EditorMaterialComponentInspector.cpp | 25 +++-- 34 files changed, 553 insertions(+), 141 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_LayerEnable.lua create mode 100644 Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialDynamicMetadata.h create mode 100644 Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialDynamicMetadata.cpp diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialInputs/DetailMapsCommonFunctor.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialInputs/DetailMapsCommonFunctor.lua index 15e4b4f416..e1a3dd6f29 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialInputs/DetailMapsCommonFunctor.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialInputs/DetailMapsCommonFunctor.lua @@ -35,16 +35,16 @@ end function Process(context) local isFeatureEnabled = context:GetMaterialPropertyValue_bool("detailLayerGroup.enableDetailLayer") - local blendMaskTexture = context:GetMaterialPropertyValue_image("detailLayerGroup.blendDetailMask") + local blendMaskTexture = context:GetMaterialPropertyValue_Image("detailLayerGroup.blendDetailMask") local blendMaskTextureEnabled = context:GetMaterialPropertyValue_bool("detailLayerGroup.enableDetailMaskTexture") context:SetShaderOptionValue_bool("o_detail_blendMask_useTexture", isFeatureEnabled and blendMaskTextureEnabled and blendMaskTexture ~= nil) local baseColorDetailEnabled = context:GetMaterialPropertyValue_bool("detailLayerGroup.enableBaseColor") - local baseColorDetailTexture = context:GetMaterialPropertyValue_image("detailLayerGroup.baseColorDetailMap") + local baseColorDetailTexture = context:GetMaterialPropertyValue_Image("detailLayerGroup.baseColorDetailMap") context:SetShaderOptionValue_bool("o_detail_baseColor_useTexture", isFeatureEnabled and baseColorDetailEnabled and baseColorDetailTexture ~= nil) local normalDetailEnabled = context:GetMaterialPropertyValue_bool("detailLayerGroup.enableNormals") - local normalDetailTexture = context:GetMaterialPropertyValue_image("detailLayerGroup.normalDetailMap") + local normalDetailTexture = context:GetMaterialPropertyValue_Image("detailLayerGroup.normalDetailMap") context:SetShaderOptionValue_bool("o_detail_normal_useTexture", isFeatureEnabled and normalDetailEnabled and normalDetailTexture ~= nil) end @@ -78,7 +78,7 @@ function ProcessEditor(context) context:SetMaterialPropertyVisibility("detailUV.rotateDegrees", mainVisibility) context:SetMaterialPropertyVisibility("detailUV.scale", mainVisibility) - local blendMaskTexture = context:GetMaterialPropertyValue_image("detailLayerGroup.blendDetailMask") + local blendMaskTexture = context:GetMaterialPropertyValue_Image("detailLayerGroup.blendDetailMask") if(nil == blendMaskTexture) then context:SetMaterialPropertyVisibility("detailLayerGroup.enableDetailMaskTexture", MaterialPropertyVisibility_Hidden) context:SetMaterialPropertyVisibility("detailLayerGroup.blendDetailMaskUv", MaterialPropertyVisibility_Hidden) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_WrinkleMaps.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_WrinkleMaps.lua index d77918f521..9e1bc3763a 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_WrinkleMaps.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin_WrinkleMaps.lua @@ -65,8 +65,8 @@ function Process(context) for i=1,MAX_WRINKLE_LAYER_COUNT do if(i <= count) then - isBaseColorTextureMissing = isBaseColorEnabled and nil == context:GetMaterialPropertyValue_image("wrinkleLayers.baseColorMap" .. i) - isNormalTextureMissing = isNormalEnabled and nil == context:GetMaterialPropertyValue_image("wrinkleLayers.normalMap" .. i) + isBaseColorTextureMissing = isBaseColorEnabled and nil == context:GetMaterialPropertyValue_Image("wrinkleLayers.baseColorMap" .. i) + isNormalTextureMissing = isNormalEnabled and nil == context:GetMaterialPropertyValue_Image("wrinkleLayers.normalMap" .. i) context:SetShaderOptionValue_bool("o_wrinkleLayers_baseColor_useTexture" .. i, not isBaseColorTextureMissing) context:SetShaderOptionValue_bool("o_wrinkleLayers_normal_useTexture" .. i, not isNormalTextureMissing) else diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index b49c66346f..a2854e8902 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -2684,6 +2684,12 @@ "file": "StandardMultilayerPBR_ShaderEnable.lua" } }, + { + "type": "Lua", + "args": { + "file": "StandardMultilayerPBR_LayerEnable.lua" + } + }, { "type": "Lua", "args": { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_LayerEnable.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_LayerEnable.lua new file mode 100644 index 0000000000..f60aac6149 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_LayerEnable.lua @@ -0,0 +1,49 @@ +-------------------------------------------------------------------------------------- +-- +-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +-- its licensors. +-- +-- For complete copyright and license terms please see the LICENSE at the root of this +-- distribution (the "License"). All use of this software is governed by the License, +-- or, if provided, by the license below or the license accompanying this file. Do not +-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- +-- +---------------------------------------------------------------------------------------------------- + +-- This functor hides the properties for disabled material layers. + +function GetMaterialPropertyDependencies() + return { + "blend.enableLayer2", + "blend.enableLayer3" + } +end + +function SetLayerVisibility(context, layerNamePrefix, isVisible) + + local visibility = MaterialPropertyGroupVisibility_Enabled + if(not isVisible) then + visibility = MaterialPropertyGroupVisibility_Hidden + end + + context:SetMaterialPropertyGroupVisibility(layerNamePrefix .. "baseColor", visibility) + context:SetMaterialPropertyGroupVisibility(layerNamePrefix .. "metallic", visibility) + context:SetMaterialPropertyGroupVisibility(layerNamePrefix .. "roughness", visibility) + context:SetMaterialPropertyGroupVisibility(layerNamePrefix .. "specularF0", visibility) + context:SetMaterialPropertyGroupVisibility(layerNamePrefix .. "normal", visibility) + context:SetMaterialPropertyGroupVisibility(layerNamePrefix .. "clearCoat", visibility) + context:SetMaterialPropertyGroupVisibility(layerNamePrefix .. "occlusion", visibility) + context:SetMaterialPropertyGroupVisibility(layerNamePrefix .. "emissive", visibility) + context:SetMaterialPropertyGroupVisibility(layerNamePrefix .. "parallax", visibility) + context:SetMaterialPropertyGroupVisibility(layerNamePrefix .. "uv", visibility) +end + +function ProcessEditor(context) + local enableLayer2 = context:GetMaterialPropertyValue_bool("blend.enableLayer2") + local enableLayer3 = context:GetMaterialPropertyValue_bool("blend.enableLayer3") + + SetLayerVisibility(context, "layer2_", context:GetMaterialPropertyValue_bool("blend.enableLayer2")) + SetLayerVisibility(context, "layer3_", context:GetMaterialPropertyValue_bool("blend.enableLayer3")) +end diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua index 119dfed436..bd56292229 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua @@ -24,7 +24,7 @@ end function Process(context) local enable = context:GetMaterialPropertyValue_bool("parallax.enable") - local textureMap = context:GetMaterialPropertyValue_image("parallax.textureMap") + local textureMap = context:GetMaterialPropertyValue_Image("parallax.textureMap") context:SetShaderOptionValue_bool("o_useDepthMap", enable and textureMap ~= nil) end @@ -37,7 +37,7 @@ function ProcessEditor(context) context:SetMaterialPropertyVisibility("parallax.textureMap", MaterialPropertyVisibility_Hidden) end - local textureMap = context:GetMaterialPropertyValue_image("parallax.textureMap") + local textureMap = context:GetMaterialPropertyValue_Image("parallax.textureMap") local visibility = MaterialPropertyVisibility_Enabled if(not enable or textureMap == nil) then visibility = MaterialPropertyVisibility_Hidden diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ClearCoatState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ClearCoatState.lua index 8289291ef4..ffa00d7efd 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ClearCoatState.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ClearCoatState.lua @@ -34,7 +34,7 @@ function GetShaderOptionDependencies() end function UpdateUseTextureState(context, clearCoatEnabled, textureMapPropertyName, useTexturePropertyName, shaderOptionName) - local textureMap = context:GetMaterialPropertyValue_image(textureMapPropertyName) + local textureMap = context:GetMaterialPropertyValue_Image(textureMapPropertyName) local useTextureMap = context:GetMaterialPropertyValue_bool(useTexturePropertyName) context:SetShaderOptionValue_bool(shaderOptionName, clearCoatEnabled and useTextureMap and textureMap ~= nil) end @@ -50,7 +50,7 @@ end -- Note this logic matches that of the UseTextureFunctor class. function UpdateTextureDependentPropertyVisibility(context, textureMapPropertyName, useTexturePropertyName, uvPropertyName) - local textureMap = context:GetMaterialPropertyValue_image(textureMapPropertyName) + local textureMap = context:GetMaterialPropertyValue_Image(textureMapPropertyName) local useTexture = context:GetMaterialPropertyValue_bool(useTexturePropertyName) if(textureMap == nil) then diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_EmissiveState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_EmissiveState.lua index a8ac2e8a4a..7ee5876adb 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_EmissiveState.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_EmissiveState.lua @@ -22,7 +22,7 @@ end function Process(context) local enable = context:GetMaterialPropertyValue_bool("emissive.enable") - local textureMap = context:GetMaterialPropertyValue_image("emissive.textureMap") + local textureMap = context:GetMaterialPropertyValue_Image("emissive.textureMap") local useTextureMap = context:GetMaterialPropertyValue_bool("emissive.useTexture") context:SetShaderOptionValue_bool("o_emissiveEnabled", enable) @@ -47,7 +47,7 @@ function ProcessEditor(context) context:SetMaterialPropertyVisibility("emissive.textureMapUv", mainVisibility) if(enable) then - local textureMap = context:GetMaterialPropertyValue_image("emissive.textureMap") + local textureMap = context:GetMaterialPropertyValue_Image("emissive.textureMap") local useTextureMap = context:GetMaterialPropertyValue_bool("emissive.useTexture") if(textureMap == nil) then diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua index 6cc595d712..541b1ac1ce 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua @@ -90,7 +90,7 @@ function ProcessEditor(context) context:SetMaterialPropertyVisibility("opacity.textureMap", MaterialPropertyVisibility_Hidden) context:SetMaterialPropertyVisibility("opacity.textureMapUv", MaterialPropertyVisibility_Hidden) else - local textureMap = context:GetMaterialPropertyValue_image("opacity.textureMap") + local textureMap = context:GetMaterialPropertyValue_Image("opacity.textureMap") if(nil == textureMap) then context:SetMaterialPropertyVisibility("opacity.textureMapUv", MaterialPropertyVisibility_Disabled) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua index 0287e1105e..e6689da327 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua @@ -22,7 +22,7 @@ end function Process(context) local enable = context:GetMaterialPropertyValue_bool("parallax.enable") - local textureMap = context:GetMaterialPropertyValue_image("parallax.textureMap") + local textureMap = context:GetMaterialPropertyValue_Image("parallax.textureMap") context:SetShaderOptionValue_bool("o_parallax_feature_enabled", enable) context:SetShaderOptionValue_bool("o_useDepthMap", enable and textureMap ~= nil) end @@ -36,7 +36,7 @@ function ProcessEditor(context) context:SetMaterialPropertyVisibility("parallax.textureMap", MaterialPropertyVisibility_Hidden) end - local textureMap = context:GetMaterialPropertyValue_image("parallax.textureMap") + local textureMap = context:GetMaterialPropertyValue_Image("parallax.textureMap") local visibility = MaterialPropertyVisibility_Enabled if(not enable or textureMap == nil) then visibility = MaterialPropertyVisibility_Hidden diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Roughness.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Roughness.lua index 4887bc47e8..222e69cd3d 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Roughness.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Roughness.lua @@ -21,13 +21,13 @@ function GetShaderOptionDependencies() end function Process(context) - local textureMap = context:GetMaterialPropertyValue_image("roughness.textureMap") + local textureMap = context:GetMaterialPropertyValue_Image("roughness.textureMap") local useTexture = context:GetMaterialPropertyValue_bool("roughness.useTexture") context:SetShaderOptionValue_bool("o_roughness_useTexture", useTexture and textureMap ~= nil) end function ProcessEditor(context) - local textureMap = context:GetMaterialPropertyValue_image("roughness.textureMap") + local textureMap = context:GetMaterialPropertyValue_Image("roughness.textureMap") local useTexture = context:GetMaterialPropertyValue_bool("roughness.useTexture") if(nil == textureMap) then diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_SubsurfaceState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_SubsurfaceState.lua index fb07ac89a3..d8a69ba355 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_SubsurfaceState.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_SubsurfaceState.lua @@ -35,7 +35,7 @@ TransmissionMode_ThickObject = 1 TransmissionMode_ThinObject = 2 function UpdateUseTextureState(context, subsurfaceScatteringEnabled, textureMapPropertyName, useTexturePropertyName, shaderOptionName) - local textureMap = context:GetMaterialPropertyValue_image(textureMapPropertyName) + local textureMap = context:GetMaterialPropertyValue_Image(textureMapPropertyName) local useTextureMap = context:GetMaterialPropertyValue_bool(useTexturePropertyName) context:SetShaderOptionValue_bool(shaderOptionName, subsurfaceScatteringEnabled and useTextureMap and textureMap ~= nil) end @@ -53,7 +53,7 @@ function UpdateTextureDependentPropertyVisibility(context, featureEnabled, textu context:SetMaterialPropertyVisibility(useTexturePropertyName, MaterialPropertyVisibility_Hidden) context:SetMaterialPropertyVisibility(uvPropertyName, MaterialPropertyVisibility_Hidden) else - local textureMap = context:GetMaterialPropertyValue_image(textureMapPropertyName) + local textureMap = context:GetMaterialPropertyValue_Image(textureMapPropertyName) local useTextureMap = context:GetMaterialPropertyValue_bool(useTexturePropertyName) if(textureMap == nil) then diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h index 44de79ff22..396ba14810 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h @@ -329,6 +329,8 @@ namespace AZ bool SetMaterialPropertySoftMaxValue(const char* name, Type value); bool SetMaterialPropertyDescription(const char* name, const char* description); + + bool SetMaterialPropertyGroupVisibility(const char* name, MaterialPropertyGroupVisibility visibility); private: diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialDynamicMetadata.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialDynamicMetadata.h new file mode 100644 index 0000000000..b74e330665 --- /dev/null +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialDynamicMetadata.h @@ -0,0 +1,100 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#include +#include +#include + +namespace AZ +{ + namespace RPI + { + // Normally we wouldn't want editor-related code mixed in with runtime code, but + // since this data can be modified dynamically, keeping it in the runtime makes + // the overall material functor design simpler and more user-friendly. + + + //! Visibility for each material property. + //! If the data field is empty, use default as editable. + enum class MaterialPropertyVisibility : uint32_t + { + Enabled, //!< The property is visible and editable + Disabled, //!< The property is visible but non-editable + Hidden, //!< The property is invisible + + Default = Enabled + }; + + struct MaterialPropertyRange + { + MaterialPropertyRange() = default; + MaterialPropertyRange( + const MaterialPropertyValue& max, + const MaterialPropertyValue& min, + const MaterialPropertyValue& softMax, + const MaterialPropertyValue& softMin + ) + : m_max(max) + , m_min(min) + , m_softMax(softMax) + , m_softMin(softMin) + {} + + MaterialPropertyValue m_max; + MaterialPropertyValue m_min; + MaterialPropertyValue m_softMax; + MaterialPropertyValue m_softMin; + }; + + //! Used by material functors to dynamically control property metadata in tools. + //! For example, show/hide a property based on some other 'enable' flag property. + struct MaterialPropertyDynamicMetadata + { + AZ_TYPE_INFO(MaterialPropertyDynamicMetadata, "{A89F215F-3235-499F-896C-9E63ACC1D657}"); + + AZ::RPI::MaterialPropertyVisibility m_visibility; + AZStd::string m_description; + AZ::RPI::MaterialPropertyRange m_propertyRange; + }; + + //! Visibility for each material property group. + enum class MaterialPropertyGroupVisibility : uint32_t + { + // Note it's helpful to keep these values aligned with MaterialPropertyVisibility in part because in lua it would be easy to accidentally use + // MaterialPropertyVisibility instead of MaterialPropertyGroupVisibility resulting in sneaky bugs. Also, if the enums end up being the same in + // the future, we could just merge them into one. + + Enabled, //!< The property is visible and editable + //Disabled, //!< The property is visible but non-editable (reserved for possible future use, to match MaterialPropertyVisibility) + Hidden=2, //!< The property is invisible + + Default = Enabled + }; + + //! Used by material functors to dynamically control property group metadata in tools. + //! For example, show/hide an entire property group based on some 'enable' flag property. + struct MaterialPropertyGroupDynamicMetadata + { + AZ_TYPE_INFO(MaterialPropertyGroupDynamicMetadata, "{F94009F7-48A3-4CE0-AF64-D5A86890ACD4}"); + + AZ::RPI::MaterialPropertyGroupVisibility m_visibility; + }; + + void ReflectMaterialDynamicMetadata(ReflectContext* context); + + } // namespace RPI + + AZ_TYPE_INFO_SPECIALIZE(RPI::MaterialPropertyVisibility, "{318B43A2-79E3-4502-8FD0-5815209EA123}"); + AZ_TYPE_INFO_SPECIALIZE(RPI::MaterialPropertyGroupVisibility, "{B803958B-DE64-4FBF-AC00-CF781611BE37}"); +} // namespace AZ + diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialFunctor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialFunctor.h index d17c7634a2..6b9b34aa1b 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialFunctor.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialFunctor.h @@ -18,6 +18,7 @@ #include #include #include +#include namespace AZ { @@ -147,6 +148,8 @@ namespace AZ public: const MaterialPropertyDynamicMetadata* GetMaterialPropertyMetadata(const Name& propertyName) const; const MaterialPropertyDynamicMetadata* GetMaterialPropertyMetadata(const MaterialPropertyIndex& index) const; + + const MaterialPropertyGroupDynamicMetadata* GetMaterialPropertyGroupMetadata(const Name& propertyName) const; //! Get the property value. The type must be one of those in MaterialPropertyValue. //! Otherwise, a compile error will be reported. @@ -178,6 +181,8 @@ namespace AZ bool SetMaterialPropertySoftMaxValue(const Name& propertyName, const MaterialPropertyValue& max); bool SetMaterialPropertySoftMaxValue(const MaterialPropertyIndex& index, const MaterialPropertyValue& max); + + bool SetMaterialPropertyGroupVisibility(const Name& propertyGroupName, MaterialPropertyGroupVisibility visibility); // [GFX TODO][ATOM-4168] Replace the workaround for unlink-able RPI.Public classes in MaterialFunctor // const AZStd::vector&, AZStd::unordered_map&, RHI::ConstPtr @@ -185,18 +190,23 @@ namespace AZ EditorContext( const AZStd::vector& propertyValues, RHI::ConstPtr materialPropertiesLayout, - AZStd::unordered_map& metadata, - AZStd::unordered_set& outChangedProperties, + AZStd::unordered_map& propertyMetadata, + AZStd::unordered_map& propertyGroupMetadata, + AZStd::unordered_set& updatedPropertiesOut, + AZStd::unordered_set& updatedPropertyGroupsOut, const MaterialPropertyFlags* materialPropertyDependencies ); private: - AZStd::list_iterator> QueryMaterialMetadata(const Name& propertyName) const; + AZStd::list_iterator> QueryMaterialPropertyMetadata(const Name& propertyName) const; + AZStd::list_iterator> QueryMaterialPropertyGroupMetadata(const Name& propertyGroupName) const; const AZStd::vector& m_materialPropertyValues; RHI::ConstPtr m_materialPropertiesLayout; - AZStd::unordered_map& m_metadata; - AZStd::unordered_set& m_outChangedProperties; + AZStd::unordered_map& m_propertyMetadata; + AZStd::unordered_map& m_propertyGroupMetadata; + AZStd::unordered_set& m_updatedPropertiesOut; + AZStd::unordered_set& m_updatedPropertyGroupsOut; const MaterialPropertyFlags* m_materialPropertyDependencies = nullptr; }; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h index d73ce2334b..fab72d5f96 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h @@ -81,52 +81,6 @@ namespace AZ AZStd::string GetMaterialPropertyDataTypeString(AZ::TypeId typeId); - //! Visibility for each material property. - //! If the data field is empty, use default as editable. - enum class MaterialPropertyVisibility : uint32_t - { - Enabled, //< The property is visible and editable - Disabled, //< The property is visible but non-editable - Hidden, //< The property is invisible - - Default = Enabled - }; - - struct MaterialPropertyRange - { - MaterialPropertyRange() = default; - MaterialPropertyRange( - const MaterialPropertyValue& max, - const MaterialPropertyValue& min, - const MaterialPropertyValue& softMax, - const MaterialPropertyValue& softMin - ) - : m_max(max) - , m_min(min) - , m_softMax(softMax) - , m_softMin(softMin) - {} - - MaterialPropertyValue m_max; - MaterialPropertyValue m_min; - MaterialPropertyValue m_softMax; - MaterialPropertyValue m_softMin; - }; - - //! Used by material functors to dynamically control property metadata in tools. - //! For example, show/hide a property based on some other 'enable' flag property. - //! Normally we wouldn't want editor-related code mixed in with runtime code, but - //! since this data can be modified dynamically, keeping it in the runtime makes - //! the overall material functor design simpler and more user-friendly. - struct MaterialPropertyDynamicMetadata - { - AZ_TYPE_INFO(MaterialPropertyDynamicMetadata, "{A89F215F-3235-499F-896C-9E63ACC1D657}"); - - AZ::RPI::MaterialPropertyVisibility m_visibility; - AZStd::string m_description; - AZ::RPI::MaterialPropertyRange m_propertyRange; - }; - //! A material property is any data input to a material, like a bool, float, Vector, Image, Buffer, etc. //! This descriptor defines a single input property, including it's name ID, and how it maps //! to the shader system. @@ -171,7 +125,6 @@ namespace AZ } // namespace RPI AZ_TYPE_INFO_SPECIALIZE(RPI::MaterialPropertyOutputType, "{42A6E5E8-0FE6-4D7B-884A-1F478E4ADD97}"); - AZ_TYPE_INFO_SPECIALIZE(RPI::MaterialPropertyVisibility, "{318B43A2-79E3-4502-8FD0-5815209EA123}"); AZ_TYPE_INFO_SPECIALIZE(RPI::MaterialPropertyDataType, "{3D903D5C-C6AA-452E-A2F8-8948D30833FF}"); } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/MaterialSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/MaterialSystem.cpp index e7e04b271d..f1751a02e2 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/MaterialSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/MaterialSystem.cpp @@ -32,6 +32,7 @@ namespace AZ MaterialPropertiesLayout::Reflect(context); MaterialFunctor::Reflect(context); LuaMaterialFunctor::Reflect(context); + ReflectMaterialDynamicMetadata(context); } void MaterialSystem::GetAssetHandlers(AssetHandlerPtrList& assetHandlers) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp index 7ab3489666..7db5f12560 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp @@ -63,6 +63,7 @@ namespace AZ behaviorContext->Class(); MaterialPropertyDescriptor::Reflect(behaviorContext); + ReflectMaterialDynamicMetadata(behaviorContext); LuaMaterialFunctorRenderStates::Reflect(behaviorContext); LuaMaterialFunctorShaderItem::Reflect(behaviorContext); @@ -255,7 +256,7 @@ namespace AZ // Specialize for type Image* because that will be more intuitive within Lua. // The script can then check the result for nil without calling "get()". - // For example, "GetMaterialPropertyValue_image(name) == nil" rather than "GetMaterialPropertyValue_image(name):get() == nil" + // For example, "GetMaterialPropertyValue_Image(name) == nil" rather than "GetMaterialPropertyValue_Image(name):get() == nil" template<> Image* LuaMaterialFunctorCommonContext::GetMaterialPropertyValue(const char* name) const { @@ -278,7 +279,7 @@ namespace AZ ->Method("GetMaterialPropertyValue_Vector3", &LuaMaterialFunctorRuntimeContext::GetMaterialPropertyValue) ->Method("GetMaterialPropertyValue_Vector4", &LuaMaterialFunctorRuntimeContext::GetMaterialPropertyValue) ->Method("GetMaterialPropertyValue_Color", &LuaMaterialFunctorRuntimeContext::GetMaterialPropertyValue) - ->Method("GetMaterialPropertyValue_image", &LuaMaterialFunctorRuntimeContext::GetMaterialPropertyValue) + ->Method("GetMaterialPropertyValue_Image", &LuaMaterialFunctorRuntimeContext::GetMaterialPropertyValue) ->Method("SetShaderConstant_bool", &LuaMaterialFunctorRuntimeContext::SetShaderConstant) ->Method("SetShaderConstant_int", &LuaMaterialFunctorRuntimeContext::SetShaderConstant) ->Method("SetShaderConstant_uint", &LuaMaterialFunctorRuntimeContext::SetShaderConstant) @@ -436,7 +437,7 @@ namespace AZ ->Method("GetMaterialPropertyValue_Vector3", &LuaMaterialFunctorEditorContext::GetMaterialPropertyValue) ->Method("GetMaterialPropertyValue_Vector4", &LuaMaterialFunctorEditorContext::GetMaterialPropertyValue) ->Method("GetMaterialPropertyValue_Color", &LuaMaterialFunctorEditorContext::GetMaterialPropertyValue) - ->Method("GetMaterialPropertyValue_image", &LuaMaterialFunctorEditorContext::GetMaterialPropertyValue) + ->Method("GetMaterialPropertyValue_Image", &LuaMaterialFunctorEditorContext::GetMaterialPropertyValue) ->Method("SetMaterialPropertyVisibility", &LuaMaterialFunctorEditorContext::SetMaterialPropertyVisibility) ->Method("SetMaterialPropertyDescription", &LuaMaterialFunctorEditorContext::SetMaterialPropertyDescription) ->Method("SetMaterialPropertyMinValue_int", &LuaMaterialFunctorEditorContext::SetMaterialPropertyMinValue) @@ -451,6 +452,7 @@ namespace AZ ->Method("SetMaterialPropertySoftMaxValue_int", &LuaMaterialFunctorEditorContext::SetMaterialPropertySoftMaxValue) ->Method("SetMaterialPropertySoftMaxValue_uint", &LuaMaterialFunctorEditorContext::SetMaterialPropertySoftMaxValue) ->Method("SetMaterialPropertySoftMaxValue_float", &LuaMaterialFunctorEditorContext::SetMaterialPropertySoftMaxValue) + ->Method("SetMaterialPropertyGroupVisibility", &LuaMaterialFunctorEditorContext::SetMaterialPropertyGroupVisibility) ; } @@ -524,6 +526,15 @@ namespace AZ return m_editorContextImpl->SetMaterialPropertySoftMaxValue(index, value); } + + bool LuaMaterialFunctorEditorContext::SetMaterialPropertyGroupVisibility(const char* name, MaterialPropertyGroupVisibility visibility) + { + if (m_editorContextImpl) + { + return m_editorContextImpl->SetMaterialPropertyGroupVisibility(Name{m_propertyNamePrefix + name}, visibility); + } + return false; + } bool LuaMaterialFunctorEditorContext::SetMaterialPropertyVisibility(const char* name, MaterialPropertyVisibility visibility) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialDynamicMetadata.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialDynamicMetadata.cpp new file mode 100644 index 0000000000..5c8f4ccc02 --- /dev/null +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialDynamicMetadata.cpp @@ -0,0 +1,50 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +namespace AZ +{ + namespace RPI + { + void ReflectMaterialDynamicMetadata(ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Enum() + ->Value("Enabled", MaterialPropertyVisibility::Enabled) + ->Value("Disabled", MaterialPropertyVisibility::Disabled) + ->Value("Hidden", MaterialPropertyVisibility::Hidden) + ; + + serializeContext->Enum() + ->Value("Enabled", MaterialPropertyGroupVisibility::Enabled) + ->Value("Hidden", MaterialPropertyGroupVisibility::Hidden) + ; + } + + if (auto* behaviorContext = azrtti_cast(context)) + { + behaviorContext + ->Enum<(int)MaterialPropertyVisibility::Enabled>("MaterialPropertyVisibility_Enabled") + ->Enum<(int)MaterialPropertyVisibility::Disabled>("MaterialPropertyVisibility_Disabled") + ->Enum<(int)MaterialPropertyVisibility::Hidden>("MaterialPropertyVisibility_Hidden"); + + behaviorContext + ->Enum<(int)MaterialPropertyGroupVisibility::Enabled>("MaterialPropertyGroupVisibility_Enabled") + ->Enum<(int)MaterialPropertyGroupVisibility::Hidden>("MaterialPropertyGroupVisibility_Hidden"); + } + } + + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialFunctor.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialFunctor.cpp index 32772e9dd5..ab18a1fb66 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialFunctor.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialFunctor.cpp @@ -142,21 +142,25 @@ namespace AZ MaterialFunctor::EditorContext::EditorContext( const AZStd::vector& propertyValues, RHI::ConstPtr materialPropertiesLayout, - AZStd::unordered_map& metadata, - AZStd::unordered_set& outChangedProperties, + AZStd::unordered_map& propertyMetadata, + AZStd::unordered_map& propertyGroupMetadata, + AZStd::unordered_set& updatedPropertiesOut, + AZStd::unordered_set& updatedPropertyGroupsOut, const MaterialPropertyFlags* materialPropertyDependencies ) : m_materialPropertyValues(propertyValues) , m_materialPropertiesLayout(materialPropertiesLayout) - , m_metadata(metadata) - , m_outChangedProperties(outChangedProperties) + , m_propertyMetadata(propertyMetadata) + , m_propertyGroupMetadata(propertyGroupMetadata) + , m_updatedPropertiesOut(updatedPropertiesOut) + , m_updatedPropertyGroupsOut(updatedPropertyGroupsOut) , m_materialPropertyDependencies(materialPropertyDependencies) {} const MaterialPropertyDynamicMetadata* MaterialFunctor::EditorContext::GetMaterialPropertyMetadata(const Name& propertyName) const { - auto it = QueryMaterialMetadata(propertyName); - if (it == m_metadata.end()) + auto it = QueryMaterialPropertyMetadata(propertyName); + if (it == m_propertyMetadata.end()) { return nullptr; } @@ -168,11 +172,38 @@ namespace AZ const Name& name = m_materialPropertiesLayout->GetPropertyDescriptor(index)->GetName(); return GetMaterialPropertyMetadata(name); } + + const MaterialPropertyGroupDynamicMetadata* MaterialFunctor::EditorContext::GetMaterialPropertyGroupMetadata(const Name& propertyName) const + { + auto it = QueryMaterialPropertyGroupMetadata(propertyName); + if (it == m_propertyGroupMetadata.end()) + { + return nullptr; + } + return &(it->second); + } + + bool MaterialFunctor::EditorContext::SetMaterialPropertyGroupVisibility(const Name& propertyGroupName, MaterialPropertyGroupVisibility visibility) + { + auto it = QueryMaterialPropertyGroupMetadata(propertyGroupName); + if (it == m_propertyGroupMetadata.end()) + { + return false; + } + MaterialPropertyGroupVisibility originValue = it->second.m_visibility; + it->second.m_visibility = visibility; + if (originValue != visibility) + { + m_updatedPropertyGroupsOut.insert(propertyGroupName); + } + + return true; + } bool MaterialFunctor::EditorContext::SetMaterialPropertyVisibility(const Name& propertyName, MaterialPropertyVisibility visibility) { - auto it = QueryMaterialMetadata(propertyName); - if (it == m_metadata.end()) + auto it = QueryMaterialPropertyMetadata(propertyName); + if (it == m_propertyMetadata.end()) { return false; } @@ -180,7 +211,7 @@ namespace AZ it->second.m_visibility = visibility; if (originValue != visibility) { - m_outChangedProperties.insert(propertyName); + m_updatedPropertiesOut.insert(propertyName); } return true; @@ -194,8 +225,8 @@ namespace AZ bool MaterialFunctor::EditorContext::SetMaterialPropertyDescription(const Name& propertyName, AZStd::string description) { - auto it = QueryMaterialMetadata(propertyName); - if (it == m_metadata.end()) + auto it = QueryMaterialPropertyMetadata(propertyName); + if (it == m_propertyMetadata.end()) { return false; } @@ -204,7 +235,7 @@ namespace AZ it->second.m_description = description; if (origin != description) { - m_outChangedProperties.insert(propertyName); + m_updatedPropertiesOut.insert(propertyName); } return true; @@ -218,8 +249,8 @@ namespace AZ bool MaterialFunctor::EditorContext::SetMaterialPropertyMinValue(const Name& propertyName, const MaterialPropertyValue& min) { - auto it = QueryMaterialMetadata(propertyName); - if (it == m_metadata.end()) + auto it = QueryMaterialPropertyMetadata(propertyName); + if (it == m_propertyMetadata.end()) { return false; } @@ -229,7 +260,7 @@ namespace AZ if(origin != min) { - m_outChangedProperties.insert(propertyName); + m_updatedPropertiesOut.insert(propertyName); } return true; @@ -243,8 +274,8 @@ namespace AZ bool MaterialFunctor::EditorContext::SetMaterialPropertyMaxValue(const Name& propertyName, const MaterialPropertyValue& max) { - auto it = QueryMaterialMetadata(propertyName); - if (it == m_metadata.end()) + auto it = QueryMaterialPropertyMetadata(propertyName); + if (it == m_propertyMetadata.end()) { return false; } @@ -254,7 +285,7 @@ namespace AZ if (origin != max) { - m_outChangedProperties.insert(propertyName); + m_updatedPropertiesOut.insert(propertyName); } return true; @@ -268,8 +299,8 @@ namespace AZ bool MaterialFunctor::EditorContext::SetMaterialPropertySoftMinValue(const Name& propertyName, const MaterialPropertyValue& min) { - auto it = QueryMaterialMetadata(propertyName); - if (it == m_metadata.end()) + auto it = QueryMaterialPropertyMetadata(propertyName); + if (it == m_propertyMetadata.end()) { return false; } @@ -279,7 +310,7 @@ namespace AZ if (origin != min) { - m_outChangedProperties.insert(propertyName); + m_updatedPropertiesOut.insert(propertyName); } return true; @@ -293,8 +324,8 @@ namespace AZ bool MaterialFunctor::EditorContext::SetMaterialPropertySoftMaxValue(const Name& propertyName, const MaterialPropertyValue& max) { - auto it = QueryMaterialMetadata(propertyName); - if (it == m_metadata.end()) + auto it = QueryMaterialPropertyMetadata(propertyName); + if (it == m_propertyMetadata.end()) { return false; } @@ -304,7 +335,7 @@ namespace AZ if (origin != max) { - m_outChangedProperties.insert(propertyName); + m_updatedPropertiesOut.insert(propertyName); } return true; @@ -316,16 +347,27 @@ namespace AZ return SetMaterialPropertySoftMaxValue(name, max); } - AZStd::list_iterator> MaterialFunctor::EditorContext::QueryMaterialMetadata(const Name& propertyName) const + AZStd::list_iterator> MaterialFunctor::EditorContext::QueryMaterialPropertyMetadata(const Name& propertyName) const { - auto it = m_metadata.find(propertyName); - if (it == m_metadata.end()) + auto it = m_propertyMetadata.find(propertyName); + if (it == m_propertyMetadata.end()) { AZ_Error("MaterialFunctor", false, "Couldn't find metadata for material property: %s.", propertyName.GetCStr()); } return it; } + + AZStd::list_iterator> MaterialFunctor::EditorContext::QueryMaterialPropertyGroupMetadata(const Name& propertyGroupName) const + { + auto it = m_propertyGroupMetadata.find(propertyGroupName); + if (it == m_propertyGroupMetadata.end()) + { + AZ_Error("MaterialFunctor", false, "Couldn't find metadata for material property group: %s.", propertyGroupName.GetCStr()); + } + + return it; + } template const Type& MaterialFunctor::RuntimeContext::GetMaterialPropertyValue(const MaterialPropertyIndex& index) const diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyDescriptor.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyDescriptor.cpp index 367d95357b..72d658db63 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyDescriptor.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyDescriptor.cpp @@ -124,12 +124,6 @@ namespace AZ ->Value(ToString(MaterialPropertyOutputType::ShaderOption), MaterialPropertyOutputType::ShaderOption) ; - serializeContext->Enum() - ->Value("Enabled", MaterialPropertyVisibility::Enabled) - ->Value("Disabled", MaterialPropertyVisibility::Disabled) - ->Value("Hidden", MaterialPropertyVisibility::Hidden) - ; - serializeContext->Enum() ->Value(ToString(MaterialPropertyDataType::Invalid), MaterialPropertyDataType::Invalid) ->Value(ToString(MaterialPropertyDataType::Bool), MaterialPropertyDataType::Bool) @@ -153,14 +147,6 @@ namespace AZ ; } - if (auto* behaviorContext = azrtti_cast(context)) - { - behaviorContext - ->Enum<(int)MaterialPropertyVisibility::Enabled>("MaterialPropertyVisibility_Enabled") - ->Enum<(int)MaterialPropertyVisibility::Disabled>("MaterialPropertyVisibility_Disabled") - ->Enum<(int)MaterialPropertyVisibility::Hidden>("MaterialPropertyVisibility_Hidden"); - } - MaterialPropertyIndex::Reflect(context); } diff --git a/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp index 76fa6bfb0e..3dcbdfce07 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp @@ -748,12 +748,15 @@ namespace UnitTest MaterialPropertyDataType::UInt, "general.mode", MaterialPropertyDataType::Float, "general.value", functorScript); - + AZStd::unordered_set changedPropertyNames; - AZStd::unordered_map propertyDynamicMetadata; propertyDynamicMetadata[Name{"general.mode"}] = {}; propertyDynamicMetadata[Name{"general.value"}] = {}; + + AZStd::unordered_set changedPropertyGroupNames; + AZStd::unordered_map propertyGroupDynamicMetadata; + propertyGroupDynamicMetadata[Name{"general"}] = {}; Ptr functor = testData.GetMaterialTypeAsset()->GetMaterialFunctors()[0]; @@ -761,7 +764,9 @@ namespace UnitTest testData.GetMaterial()->GetPropertyValues(), testData.GetMaterial()->GetMaterialPropertiesLayout(), propertyDynamicMetadata, + propertyGroupDynamicMetadata, changedPropertyNames, + changedPropertyGroupNames, &functor->GetMaterialPropertyDependencies() ); @@ -814,10 +819,13 @@ namespace UnitTest functorScript); AZStd::unordered_set changedPropertyNames; - AZStd::unordered_map propertyDynamicMetadata; propertyDynamicMetadata[Name{"general.units"}] = {}; propertyDynamicMetadata[Name{"general.distance"}] = {}; + + AZStd::unordered_set changedPropertyGroupNames; + AZStd::unordered_map propertyGroupDynamicMetadata; + propertyGroupDynamicMetadata[Name{"general"}] = {}; Ptr functor = testData.GetMaterialTypeAsset()->GetMaterialFunctors()[0]; @@ -825,7 +833,9 @@ namespace UnitTest testData.GetMaterial()->GetPropertyValues(), testData.GetMaterial()->GetMaterialPropertiesLayout(), propertyDynamicMetadata, + propertyGroupDynamicMetadata, changedPropertyNames, + changedPropertyGroupNames, &functor->GetMaterialPropertyDependencies() ); @@ -845,6 +855,66 @@ namespace UnitTest EXPECT_EQ(-100.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_softMin.GetValue()); EXPECT_EQ(100.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_softMax.GetValue()); } + + TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_EditorContext_SetMaterialPropertyGroupVisibility) + { + using namespace AZ::RPI; + + const char* functorScript = + R"( + function GetMaterialPropertyDependencies() + return { "general.mode" } + end + + function ProcessEditor(context) + local mode = context:GetMaterialPropertyValue_uint("general.mode") + + if (mode == 1) then + context:SetMaterialPropertyGroupVisibility("otherGroup", MaterialPropertyGroupVisibility_Enabled) + else + context:SetMaterialPropertyGroupVisibility("otherGroup", MaterialPropertyGroupVisibility_Hidden) + end + end + )"; + + TestMaterialData testData; + testData.Setup( + MaterialPropertyDataType::UInt, "general.mode", + MaterialPropertyDataType::Float, "otherGroup.value", + functorScript); + + AZStd::unordered_set changedPropertyNames; + AZStd::unordered_map propertyDynamicMetadata; + propertyDynamicMetadata[Name{"general.mode"}] = {}; + propertyDynamicMetadata[Name{"otherGroup.value"}] = {}; + + AZStd::unordered_set changedPropertyGroupNames; + AZStd::unordered_map propertyGroupDynamicMetadata; + propertyGroupDynamicMetadata[Name{"general"}] = {}; + propertyGroupDynamicMetadata[Name{"otherGroup"}] = {}; + + Ptr functor = testData.GetMaterialTypeAsset()->GetMaterialFunctors()[0]; + + AZ::RPI::MaterialFunctor::EditorContext context = AZ::RPI::MaterialFunctor::EditorContext( + testData.GetMaterial()->GetPropertyValues(), + testData.GetMaterial()->GetMaterialPropertiesLayout(), + propertyDynamicMetadata, + propertyGroupDynamicMetadata, + changedPropertyNames, + changedPropertyGroupNames, + &functor->GetMaterialPropertyDependencies() + ); + + testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{0u}); + functor->Process(context); + EXPECT_EQ(MaterialPropertyGroupVisibility::Enabled, propertyGroupDynamicMetadata[Name{"general"}].m_visibility); + EXPECT_EQ(MaterialPropertyGroupVisibility::Hidden, propertyGroupDynamicMetadata[Name{"otherGroup"}].m_visibility); + + testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{1u}); + functor->Process(context); + EXPECT_EQ(MaterialPropertyGroupVisibility::Enabled, propertyGroupDynamicMetadata[Name{"general"}].m_visibility); + EXPECT_EQ(MaterialPropertyGroupVisibility::Enabled, propertyGroupDynamicMetadata[Name{"otherGroup"}].m_visibility); + } TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetRenderStates) { diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp index 5a81ebb74d..d32c285780 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp @@ -29,6 +29,7 @@ namespace JsonSerializationTests { AZ::RPI::MaterialTypeSourceData::Reflect(context.get()); AZ::RPI::MaterialPropertyDescriptor::Reflect(context.get()); + AZ::RPI::ReflectMaterialDynamicMetadata(context.get()); } void Reflect(AZStd::unique_ptr& context) diff --git a/Gems/Atom/RPI/Code/atom_rpi_reflect_files.cmake b/Gems/Atom/RPI/Code/atom_rpi_reflect_files.cmake index d1db00aa34..307f3a046b 100644 --- a/Gems/Atom/RPI/Code/atom_rpi_reflect_files.cmake +++ b/Gems/Atom/RPI/Code/atom_rpi_reflect_files.cmake @@ -55,6 +55,7 @@ set(FILES Include/Atom/RPI.Reflect/Material/MaterialAsset.h Include/Atom/RPI.Reflect/Material/MaterialAssetCreatorCommon.h Include/Atom/RPI.Reflect/Material/MaterialAssetCreator.h + Include/Atom/RPI.Reflect/Material/MaterialDynamicMetadata.h Include/Atom/RPI.Reflect/Material/MaterialPropertyDescriptor.h Include/Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h Include/Atom/RPI.Reflect/Material/MaterialPropertyValue.h @@ -135,6 +136,7 @@ set(FILES Source/RPI.Reflect/Material/MaterialAssetCreatorCommon.cpp Source/RPI.Reflect/Material/MaterialAssetCreator.cpp Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp + Source/RPI.Reflect/Material/MaterialDynamicMetadata.cpp Source/RPI.Reflect/Material/MaterialPropertyDescriptor.cpp Source/RPI.Reflect/Material/MaterialPropertiesLayout.cpp Source/RPI.Reflect/Material/MaterialTypeAsset.cpp diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h index b17a25a675..17ca1c8d04 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h @@ -38,8 +38,8 @@ namespace AtomToolsFramework Count }; - // Configures the initial state, data type, attributes, and values that describe - // the dynamic property and how it is presented + //! Configures the initial state, data type, attributes, and values that describe + //! the dynamic property and how it is presented struct DynamicPropertyConfig { AZ_TYPE_INFO(DynamicPropertyConfig, "{9CA40E92-7F03-42BE-B6AA-51F30EE5796C}"); @@ -98,7 +98,7 @@ namespace AtomToolsFramework //! Returns true if the property has a valid value. bool IsValid() const; - //! Returns the ID of the property. + //! Returns the ID of the property. const AZ::Name GetId() const; //! Returns the current property visibility. diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorRequestBus.h index 81b512faf2..0403c06f87 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorRequestBus.h @@ -44,6 +44,12 @@ namespace AtomToolsFramework const AZStd::string& groupDescription, QWidget* groupWidget) = 0; + //! Sets the visibility of a specific property group. This impacts both the header and the widget. + virtual void SetGroupVisible(const AZStd::string& groupNameId, bool visible) = 0; + + //! Returns the visibility of a specific property group. + virtual bool IsGroupVisible(const AZStd::string& groupNameId) const = 0; + //! Calls Refresh for a specific InspectorGroupWidget, allowing for non-destructive UI changes virtual void RefreshGroup(const AZStd::string& groupNameId) = 0; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorWidget.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorWidget.h index b0932b3b04..5559b51462 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorWidget.h @@ -57,6 +57,9 @@ namespace AtomToolsFramework const AZStd::string& groupDescription, QWidget* groupWidget) override; + void SetGroupVisible(const AZStd::string& groupNameId, bool visible) override; + bool IsGroupVisible(const AZStd::string& groupNameId) const override; + void RefreshGroup(const AZStd::string& groupNameId) override; void RebuildGroup(const AZStd::string& groupNameId) override; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp index ec5f9893bd..c1ccfb4616 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp @@ -69,6 +69,7 @@ namespace AtomToolsFramework InspectorGroupHeaderWidget* groupHeader = new InspectorGroupHeaderWidget(m_ui->m_propertyContent); groupHeader->setText(groupDisplayName.c_str()); groupHeader->setToolTip(groupDescription.c_str()); + groupHeader->setObjectName(groupNameId.c_str()); m_layout->addWidget(groupHeader); m_headers.push_back(groupHeader); @@ -81,6 +82,32 @@ namespace AtomToolsFramework OnHeaderClicked(event, groupHeader, groupWidget); }); } + + void InspectorWidget::SetGroupVisible(const AZStd::string& groupNameId, bool visible) + { + for (size_t i = 0; i < m_groups.size(); ++i) + { + if (m_groups[i]->objectName() == groupNameId.c_str()) + { + m_headers[i]->setVisible(visible); + m_groups[i]->setVisible(visible && m_headers[i]->IsExpanded()); + break; + } + } + } + + bool InspectorWidget::IsGroupVisible(const AZStd::string& groupNameId) const + { + for (auto& header : m_headers) + { + if (header->objectName() == groupNameId.c_str()) + { + return header->isVisible(); + } + } + + return false; + } void InspectorWidget::RefreshGroup(const AZStd::string& groupNameId) { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h index 3c3c77a628..80e8054ec5 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentNotificationBus.h @@ -18,6 +18,7 @@ #include #include +#include namespace MaterialEditor { @@ -77,6 +78,12 @@ namespace MaterialEditor //! @param documentId unique id of material document for which the notification is sent //! @param property object containing the property value and configuration that was modified virtual void OnDocumentPropertyConfigModified([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AtomToolsFramework::DynamicProperty& property) {} + + //! Signal that the property group visibility has been changed. + //! @param documentId unique id of material document for which the notification is sent + //! @param groupId id of the group that changed + //! @param visible whether the property group is visible + virtual void OnDocumentPropertyGroupVisibilityChanged([[maybe_unused]] const AZ::Uuid& documentId, [[maybe_unused]] const AZ::Name& groupId, [[maybe_unused]] bool visible) {} }; using MaterialDocumentNotificationBus = AZ::EBus; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h index dad21a6348..c71d500d8c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h @@ -19,6 +19,7 @@ #include #include +#include namespace AZ { @@ -67,6 +68,10 @@ namespace MaterialEditor //! Returns a property object //! If the document is not open or the id can't be found, an invalid property is returned. virtual const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const = 0; + + //! Returns whether a property group is visible + //! If the document is not open or the id can't be found, returns false. + virtual bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const = 0; //! Modify material property value virtual void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) = 0; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 288530a4e4..fec70763dd 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -117,6 +117,24 @@ namespace MaterialEditor const AtomToolsFramework::DynamicProperty& property = it->second; return property; } + + bool MaterialDocument::IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const + { + if (!IsOpen()) + { + AZ_Error("MaterialDocument", false, "Material document is not open."); + return false; + } + + const auto it = m_propertyGroupVisibility.find(propertyGroupFullName); + if (it == m_propertyGroupVisibility.end()) + { + AZ_Error("MaterialDocument", false, "Material document property group could not be found: '%s'.", propertyGroupFullName.GetCStr()); + return false; + } + + return it->second; + } void MaterialDocument::SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) { @@ -153,8 +171,12 @@ namespace MaterialEditor Recompile(); - AZStd::unordered_set changedPropertyNames = RunEditorMaterialFunctors(dirtyFlags); - for (const Name& changedPropertyName : changedPropertyNames) + EditorMaterialFunctorResult result = RunEditorMaterialFunctors(dirtyFlags); + for (const Name& changedPropertyGroupName : result.m_updatedPropertyGroups) + { + MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentPropertyGroupVisibilityChanged, m_id, changedPropertyGroupName, IsPropertyGroupVisible(changedPropertyGroupName)); + } + for (const Name& changedPropertyName : result.m_updatedProperties) { MaterialDocumentNotificationBus::Broadcast(&MaterialDocumentNotificationBus::Events::OnDocumentPropertyConfigModified, m_id, GetProperty(changedPropertyName)); } @@ -782,6 +804,12 @@ namespace MaterialEditor return true; }); + // Populate the property group visibility map + for (MaterialTypeSourceData::GroupDefinition& group : m_materialTypeSourceData.GetGroupDefinitionsInDisplayOrder()) + { + m_propertyGroupVisibility[AZ::Name{group.m_nameId}] = true; + } + // Adding properties for material type and parent as part of making dynamic // properties and the inspector more general purpose. // This allows the read only properties to appear in the inspector like any @@ -914,16 +942,26 @@ namespace MaterialEditor } } - AZStd::unordered_set MaterialDocument::RunEditorMaterialFunctors(AZ::RPI::MaterialPropertyFlags dirtyFlags) + MaterialDocument::EditorMaterialFunctorResult MaterialDocument::RunEditorMaterialFunctors(AZ::RPI::MaterialPropertyFlags dirtyFlags) { - AZStd::unordered_set changedPropertyNames; + EditorMaterialFunctorResult result; + AZStd::unordered_map propertyDynamicMetadata; + AZStd::unordered_map propertyGroupDynamicMetadata; for (auto& propertyPair : m_properties) { AtomToolsFramework::DynamicProperty& property = propertyPair.second; AtomToolsFramework::ConvertToPropertyMetaData(propertyDynamicMetadata[property.GetId()], property.GetConfig()); } + for (auto& groupPair : m_propertyGroupVisibility) + { + AZ::RPI::MaterialPropertyGroupDynamicMetadata& metadata = propertyGroupDynamicMetadata[AZ::Name{groupPair.first}]; + bool visible = groupPair.second; + metadata.m_visibility = visible ? + AZ::RPI::MaterialPropertyGroupVisibility::Enabled : AZ::RPI::MaterialPropertyGroupVisibility::Hidden; + } + for (AZ::RPI::Ptr& functor : m_editorFunctors) { const AZ::RPI::MaterialPropertyFlags& materialPropertyDependencies = functor->GetMaterialPropertyDependencies(); @@ -935,7 +973,9 @@ namespace MaterialEditor m_materialInstance->GetPropertyValues(), m_materialInstance->GetMaterialPropertiesLayout(), propertyDynamicMetadata, - changedPropertyNames, + propertyGroupDynamicMetadata, + result.m_updatedProperties, + result.m_updatedPropertyGroups, &materialPropertyDependencies ); functor->Process(context); @@ -950,7 +990,13 @@ namespace MaterialEditor property.SetConfig(propertyConfig); } - return changedPropertyNames; + for (auto& updatedPropertyGroup : result.m_updatedPropertyGroups) + { + bool visible = propertyGroupDynamicMetadata[updatedPropertyGroup].m_visibility == AZ::RPI::MaterialPropertyGroupVisibility::Enabled; + m_propertyGroupVisibility[updatedPropertyGroup] = visible; + } + + return result; } } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index 3959e45ad7..42f48c95cd 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -56,6 +56,7 @@ namespace MaterialEditor const AZ::RPI::MaterialTypeSourceData* GetMaterialTypeSourceData() const override; const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const override; const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const override; + bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override; bool Open(AZStd::string_view loadPath) override; bool Rebuild() override; @@ -79,11 +80,14 @@ namespace MaterialEditor // Predicate for evaluating properties using PropertyFilterFunction = AZStd::function; - // Map of documenmt's property + // Map of document's properties using PropertyMap = AZStd::unordered_map; // Map of raw property values for undo/redo comparison and storage using PropertyValueMap = AZStd::unordered_map; + + // Map of document's property group visibility flags + using PropertyGroupVisibilityMap = AZStd::unordered_map; // Function to be bound for undo and redo using UndoRedoFunction = AZStd::function; @@ -119,10 +123,16 @@ namespace MaterialEditor void RestorePropertyValues(const PropertyValueMap& propertyValues); + struct EditorMaterialFunctorResult + { + AZStd::unordered_set m_updatedProperties; + AZStd::unordered_set m_updatedPropertyGroups; + }; + // Run editor material functor to update editor metadata. // @param dirtyFlags indicates which properties have changed, and thus which MaterialFunctors need to be run. - // @return names for the set of properties that have been changed or need update. - AZStd::unordered_set RunEditorMaterialFunctors(AZ::RPI::MaterialPropertyFlags dirtyFlags); + // @return names for the set of properties and groups that have been changed or need update. + EditorMaterialFunctorResult RunEditorMaterialFunctors(AZ::RPI::MaterialPropertyFlags dirtyFlags); // Unique id of this material document AZ::Uuid m_id = AZ::Uuid::CreateRandom(); @@ -153,6 +163,9 @@ namespace MaterialEditor // Collection of all material's properties PropertyMap m_properties; + + // Collection of all material's property groups + PropertyGroupVisibilityMap m_propertyGroupVisibility; // Material functors that run in editor. See MaterialFunctor.h for details. AZStd::vector> m_editorFunctors; @@ -175,7 +188,7 @@ namespace MaterialEditor int m_undoHistoryIndex = 0; AZStd::any m_invalidValue; - + AtomToolsFramework::DynamicProperty m_invalidProperty; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp index b066c3c7dd..0fd3a8e2a8 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp @@ -185,7 +185,7 @@ namespace MaterialEditor } } - void MaterialInspector::OnDocumentPropertyConfigModified(const AZ::Uuid& documentId, const AtomToolsFramework::DynamicProperty& property) + void MaterialInspector::OnDocumentPropertyConfigModified(const AZ::Uuid&, const AtomToolsFramework::DynamicProperty& property) { for (auto& groupPair : m_groups) { @@ -197,18 +197,28 @@ namespace MaterialEditor if (reflectedProperty.GetVisibility() != property.GetVisibility()) { reflectedProperty.SetConfig(property.GetConfig()); - AtomToolsFramework::InspectorRequestBus::Event(documentId, &AtomToolsFramework::InspectorRequestBus::Events::RebuildGroup, groupPair.first); + RebuildGroup(groupPair.first); } else { reflectedProperty.SetConfig(property.GetConfig()); - AtomToolsFramework::InspectorRequestBus::Event(documentId, &AtomToolsFramework::InspectorRequestBus::Events::RefreshGroup, groupPair.first); + RefreshGroup(groupPair.first); } return; } } } } + + void MaterialInspector::OnDocumentPropertyGroupVisibilityChanged(const AZ::Uuid&, const AZ::Name& groupId, bool visible) + { + auto groupIter = m_groups.find(groupId.GetStringView()); + + if(groupIter != m_groups.end()) + { + SetGroupVisible(groupIter->first, visible); + } + } void MaterialInspector::BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode) { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h index efe979e5ea..65de41f240 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h @@ -50,6 +50,7 @@ namespace MaterialEditor void OnDocumentOpened(const AZ::Uuid& documentId) override; void OnDocumentPropertyValueModified(const AZ::Uuid& documentId, const AtomToolsFramework::DynamicProperty& property) override; void OnDocumentPropertyConfigModified(const AZ::Uuid& documentId, const AtomToolsFramework::DynamicProperty& property) override; + void OnDocumentPropertyGroupVisibilityChanged(const AZ::Uuid& documentId, const AZ::Name& groupId, bool visible) override; // AzToolsFramework::IPropertyEditorNotify overrides... void BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode) override; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp index 03533e142f..62f8a58fab 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp @@ -288,15 +288,17 @@ namespace AZ void MaterialPropertyInspector::RunEditorMaterialFunctors() { AZStd::unordered_set changedPropertyNames; + AZStd::unordered_set changedPropertyGroupNames; // Convert editor property configuration data into material property meta data so that it can be used to execute functors AZStd::unordered_map propertyDynamicMetadata; - for (auto& group : m_groups) + AZStd::unordered_map propertyGroupDynamicMetadata; + for (auto& groupPair : m_groups) { - for (auto& property : group.second.m_properties) - { - AtomToolsFramework::ConvertToPropertyMetaData(propertyDynamicMetadata[property.GetId()], property.GetConfig()); - } + AZ::RPI::MaterialPropertyGroupDynamicMetadata& metadata = propertyGroupDynamicMetadata[AZ::Name{groupPair.first}]; + + metadata.m_visibility = IsGroupVisible(groupPair.first) ? + AZ::RPI::MaterialPropertyGroupVisibility::Enabled : AZ::RPI::MaterialPropertyGroupVisibility::Hidden; } for (AZ::RPI::Ptr& functor : m_editorFunctors) @@ -310,7 +312,9 @@ namespace AZ m_materialInstance->GetPropertyValues(), m_materialInstance->GetMaterialPropertiesLayout(), propertyDynamicMetadata, + propertyGroupDynamicMetadata, changedPropertyNames, + changedPropertyGroupNames, &materialPropertyDependencies ); functor->Process(context); @@ -319,9 +323,16 @@ namespace AZ m_dirtyPropertyFlags.reset(); // Apply any changes to material property meta data back to the editor property configurations - for (auto& group : m_groups) + for (auto& groupPair : m_groups) { - for (auto& property : group.second.m_properties) + AZ::Name groupName{groupPair.first}; + + if (changedPropertyGroupNames.find(groupName) != changedPropertyGroupNames.end()) + { + SetGroupVisible(groupPair.first, propertyGroupDynamicMetadata[groupName].m_visibility == AZ::RPI::MaterialPropertyGroupVisibility::Enabled); + } + + for (auto& property : groupPair.second.m_properties) { AtomToolsFramework::DynamicPropertyConfig propertyConfig = property.GetConfig();