Updated the naming convention for material property "names" vs "IDs".

Merge pull request #4207 from aws-lumberyard-dev/Atom/santorac/RemixableMaterialTypes

A "property name" is the name of the just the property without regard to the group that it's in. A "group name" is the name of the group. And a "property ID" is the full unique name of a property in the form "groupName.propertyName". This is important preparation for upcoming changes where property sets can contain other property sets, and property IDs can be arbitrarily long like "layer1.baseColor.factor" for example.

The naming changes include variables, some code comments, and the .materialtype file format. All material types have been updated to use "name" instead of "id". If any users have made custom material types, they will need to search and replace "id" with "name" (there probably aren't many of these in the wild, and fixing any that do exist will be a very simple change, not worth the cruft of keeping backward compatibility code around IMO).

Testing:
Opened up materials in the material editor.
Ran AtomSampleViewer in dx12 and vulkan with no new failures.
RPI unit tests.

Signed-off-by: santorac 55155825+santorac@users.noreply.github.com
This commit is contained in:
santorac
2021-09-30 10:59:17 -07:00
committed by GitHub
46 changed files with 1996 additions and 1449 deletions
@@ -5,7 +5,7 @@
"properties": {
"general": [
{
"id": "texcoord",
"name": "texcoord",
"displayName": "Texture Coordinate Stream",
"description": "Which UV channel to use when sampling textures.",
"type": "Int",
@@ -14,75 +14,75 @@
"max": 8
},
{
"id": "enableShadows",
"name": "enableShadows",
"displayName": "Enable Shadows",
"description": "Whether to use the shadow maps.",
"type": "Bool",
"defaultValue": false,
"connection": {
"type": "ShaderOption",
"id": "o_enableShadows"
"name": "o_enableShadows"
}
},
{
"id": "enableDirectionalLights",
"name": "enableDirectionalLights",
"displayName": "Enable Directional Lights",
"description": "Whether to use directional lights.",
"type": "Bool",
"defaultValue": false,
"connection": {
"type": "ShaderOption",
"id": "o_enableDirectionalLights"
"name": "o_enableDirectionalLights"
}
},
{
"id": "enablePunctualLights",
"name": "enablePunctualLights",
"displayName": "Enable Punctual Lights",
"description": "Whether to use punctual lights.",
"type": "Bool",
"defaultValue": false,
"connection": {
"type": "ShaderOption",
"id": "o_enablePunctualLights"
"name": "o_enablePunctualLights"
}
},
{
"id": "enableAreaLights",
"name": "enableAreaLights",
"displayName": "Enable Area Lights",
"description": "Whether to use area lights.",
"type": "Bool",
"defaultValue": false,
"connection": {
"type": "ShaderOption",
"id": "o_enableAreaLights"
"name": "o_enableAreaLights"
}
},
{
"id": "enableIBL",
"name": "enableIBL",
"displayName": "Enable IBL",
"description": "Whether to use Image Based Lighting (IBL).",
"type": "Bool",
"defaultValue": true,
"connection": {
"type": "ShaderOption",
"id": "o_enableIBL"
"name": "o_enableIBL"
}
}
],
"baseColor": [
{
"id": "color",
"name": "color",
"displayName": "Color",
"description": "Color is displayed as sRGB but the values are stored as linear color.",
"type": "Color",
"defaultValue": [ 1.0, 1.0, 1.0 ],
"connection": {
"type": "ShaderInput",
"id": "m_baseColor"
"name": "m_baseColor"
}
},
{
"id": "factor",
"name": "factor",
"displayName": "Factor",
"description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.",
"type": "Float",
@@ -91,31 +91,31 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_baseColorFactor"
"name": "m_baseColorFactor"
}
},
{
"id": "useTexture",
"name": "useTexture",
"displayName": "Use Texture",
"description": "Whether to use the texture map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMap",
"name": "textureMap",
"displayName": "Texture Map",
"description": "Base color texture map",
"type": "Image",
"defaultValue": "Textures/Default/default_basecolor.tif",
"connection": {
"type": "ShaderInput",
"id": "m_baseColorMap"
"name": "m_baseColorMap"
}
}
],
"metallic": [
{
"id": "factor",
"name": "factor",
"displayName": "Factor",
"description": "This value is linear, black is non-metal and white means raw metal.",
"type": "Float",
@@ -124,30 +124,30 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_metallicFactor"
"name": "m_metallicFactor"
}
},
{
"id": "useTexture",
"name": "useTexture",
"displayName": "Use Texture",
"description": "Whether to use the texture map, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMap",
"name": "textureMap",
"displayName": "Texture Map",
"description": "",
"type": "Image",
"connection": {
"type": "ShaderInput",
"id": "m_metallicMap"
"name": "m_metallicMap"
}
}
],
"roughness": [
{
"id": "factor",
"name": "factor",
"displayName": "Factor",
"description": "Strength factor for scaling the values",
"type": "Float",
@@ -156,31 +156,31 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_roughnessFactor"
"name": "m_roughnessFactor"
}
},
{
"id": "useTexture",
"name": "useTexture",
"displayName": "Use Texture",
"description": "Whether to use the texture map, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMap",
"name": "textureMap",
"displayName": "Texture Map",
"description": "Texture map for defining surface roughness.",
"type": "Image",
"defaultValue": "Textures/Default/default_roughness.tif",
"connection": {
"type": "ShaderInput",
"id": "m_roughnessMap"
"name": "m_roughnessMap"
}
}
],
"specularF0": [
{
"id": "factor",
"name": "factor",
"displayName": "Factor",
"description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.",
"type": "Float",
@@ -189,51 +189,51 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_specularF0Factor"
"name": "m_specularF0Factor"
}
},
{
"id": "useTexture",
"name": "useTexture",
"displayName": "Use Texture",
"description": "Whether to use the texture map, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMap",
"name": "textureMap",
"displayName": "Texture Map",
"description": "Texture map for defining surface reflectance.",
"type": "Image",
"connection": {
"type": "ShaderInput",
"id": "m_specularF0Map"
"name": "m_specularF0Map"
}
},
{
"id": "applySpecularAA",
"name": "applySpecularAA",
"displayName": "Apply Specular AA",
"description": "Whether to apply specular anti-aliasing in the shader.",
"type": "Bool",
"defaultValue": true,
"connection": {
"type": "ShaderOption",
"id": "o_applySpecularAA"
"name": "o_applySpecularAA"
}
},
{
"id": "enableMultiScatterCompensation",
"name": "enableMultiScatterCompensation",
"displayName": "Multiscattering Compensation",
"description": "Whether to enable multiple scattering compensation.",
"type": "Bool",
"connection": {
"type": "ShaderOption",
"id": "o_specularF0_enableMultiScatterCompensation"
"name": "o_specularF0_enableMultiScatterCompensation"
}
}
],
"normal": [
{
"id": "factor",
"name": "factor",
"displayName": "Factor",
"description": "Strength factor for scaling the values",
"type": "Float",
@@ -243,85 +243,85 @@
"max": 2.0,
"connection": {
"type": "ShaderInput",
"id": "m_normalFactor"
"name": "m_normalFactor"
}
},
{
"id": "useTexture",
"name": "useTexture",
"displayName": "Use Texture",
"description": "Whether to use the texture map, or just rely on vertex normals.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMap",
"name": "textureMap",
"displayName": "Texture Map",
"description": "Texture map for defining surface normal direction.",
"type": "Image",
"defaultValue": "Textures/Default/default_normal.tif",
"connection": {
"type": "ShaderInput",
"id": "m_normalMap"
"name": "m_normalMap"
}
},
{
"id": "flipX",
"name": "flipX",
"displayName": "Flip X Channel",
"description": "Flip tangent direction for this normal map.",
"type": "Bool",
"defaultValue": false,
"connection": {
"type": "ShaderInput",
"id": "m_flipNormalX"
"name": "m_flipNormalX"
}
},
{
"id": "flipY",
"name": "flipY",
"displayName": "Flip Y Channel",
"description": "Flip bitangent direction for this normal map.",
"type": "Bool",
"defaultValue": false,
"connection": {
"type": "ShaderInput",
"id": "m_flipNormalY"
"name": "m_flipNormalY"
}
}
],
"opacity": [
{
"id": "mode",
"name": "mode",
"displayName": "Opacity Mode",
"description": "Opacity mode for this texture. 0: Opaque, 1: Cutout, 2:Blended",
"type": "Uint",
"defaultValue": 0,
"connection": {
"type": "ShaderOption",
"id": "o_opacity_mode"
"name": "o_opacity_mode"
}
},
{
"id": "alphaSource",
"name": "alphaSource",
"displayName": "Alpha Source",
"description": "Source texture of alpha value. 0:Packed, 1:Split, 2:None",
"type": "Uint",
"defaultValue": 0,
"connection": {
"type": "ShaderOption",
"id": "o_opacity_source"
"name": "o_opacity_source"
}
},
{
"id": "textureMap",
"name": "textureMap",
"displayName": "Texture Map",
"description": "Texture map for defining surface opacity.",
"type": "Image",
"connection": {
"type": "ShaderInput",
"id": "m_opacityMap"
"name": "m_opacityMap"
}
},
{
"id": "factor",
"name": "factor",
"displayName": "Factor",
"description": "Factor for cutout threshold and blending",
"type": "Float",
@@ -330,11 +330,11 @@
"defaultValue": 0.5,
"connection": {
"type": "ShaderInput",
"id": "m_opacityFactor"
"name": "m_opacityFactor"
}
},
{
"id": "doubleSided",
"name": "doubleSided",
"displayName": "Double-sided",
"description": "Whether to render back-faces or just front-faces.",
"type": "Bool"
@@ -342,14 +342,14 @@
],
"uv": [
{
"id": "center",
"name": "center",
"displayName": "Center",
"description": "Center point for scaling and rotation transformations.",
"type": "vector2",
"defaultValue": [0.0, 0.0]
},
{
"id": "tileU",
"name": "tileU",
"displayName": "Tile U",
"description": "Scales texture coordinates in V.",
"type": "float",
@@ -357,7 +357,7 @@
"step": 0.1
},
{
"id": "tileV",
"name": "tileV",
"displayName": "Tile V",
"description": "Scales texture coordinates in V.",
"type": "float",
@@ -365,7 +365,7 @@
"step": 0.1
},
{
"id": "offsetU",
"name": "offsetU",
"displayName": "Offset U",
"description": "Offsets texture coordinates in the U direction.",
"type": "float",
@@ -374,7 +374,7 @@
"max": 1.0
},
{
"id": "offsetV",
"name": "offsetV",
"displayName": "Offset V",
"description": "Offsets texture coordinates in the V direction.",
"type": "float",
@@ -383,7 +383,7 @@
"max": 1.0
},
{
"id": "rotateDegrees",
"name": "rotateDegrees",
"displayName": "Rotate",
"description": "Rotates the texture coordinates (degrees).",
"type": "float",
@@ -393,7 +393,7 @@
"step": 1.0
},
{
"id": "scale",
"name": "scale",
"displayName": "Scale",
"description": "Scales texture coordinates in both U and V.",
"type": "float",
@@ -403,29 +403,29 @@
],
"emissive": [
{
"id": "enable",
"name": "enable",
"displayName": "Enable",
"description": "Enable the emissive group",
"type":"Bool",
"defaultValue": false,
"connection": {
"type": "ShaderOption",
"id": "o_emissiveEnabled"
"name": "o_emissiveEnabled"
}
},
{
"id": "color",
"name": "color",
"displayName": "Color",
"description": "Color is displayed as sRGB but the values are stored as linear color.",
"type": "Color",
"defaultValue": [ 1.0, 1.0, 1.0 ],
"connection": {
"type": "ShaderInput",
"id": "m_emissiveColor"
"name": "m_emissiveColor"
}
},
{
"id": "intensity",
"name": "intensity",
"displayName": "Intensity",
"description": "The amount of energy emitted, in EV100 unit",
"type": "Float",
@@ -434,33 +434,33 @@
"max": 5
},
{
"id": "useTexture",
"name": "useTexture",
"displayName": "Use Texture",
"description": "Whether to use the texture map.",
"type": "Bool",
"defaultValue": false
},
{
"id": "textureMap",
"name": "textureMap",
"displayName": "Texture Map",
"description": "Texture map for defining emissive area.",
"type": "Image",
"connection": {
"type": "ShaderInput",
"id": "m_emissiveMap"
"name": "m_emissiveMap"
}
}
],
"parallax": [
{
"id": "enable",
"name": "enable",
"displayName": "Enable",
"description": "Whether to enable the parallax feature.",
"type": "Bool",
"defaultValue": false
},
{
"id": "factor",
"name": "factor",
"displayName": "Factor",
"description": "Strength factor for scaling the depth values",
"type": "Float",
@@ -469,39 +469,39 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_heightmapScale"
"name": "m_heightmapScale"
}
},
{
"id": "textureMap",
"name": "textureMap",
"displayName": "Texture Map",
"description": "Depthmap to create parallax effect.",
"type": "Image",
"connection": {
"type": "ShaderInput",
"id": "m_heightmap"
"name": "m_heightmap"
}
},
{
"id": "algorithm",
"name": "algorithm",
"displayName": "Algorithm",
"description": "Select the algorithm to use for parallax mapping. 0: Basic, 1:Steep, 2:POM, 3:Relief, 4:Contact refinement",
"type": "Uint",
"defaultValue": 0,
"connection":{
"type": "ShaderOption",
"id": "o_parallax_algorithm"
"name": "o_parallax_algorithm"
}
},
{
"id": "quality",
"name": "quality",
"displayName": "Quality",
"description": "Quality of parallax mapping. 0:Low, 1:Medium, 2:High, 3:Ultra",
"type": "Uint",
"defaultValue": 0,
"connection":{
"type": "ShaderOption",
"id": "o_parallax_quality"
"name": "o_parallax_quality"
}
}
]
@@ -5,7 +5,7 @@
"properties": {
"settings": [
{
"id": "opacity",
"name": "opacity",
"displayName": "Opacity",
"description": "Opacity of the shadow effect.",
"type": "Float",
@@ -14,17 +14,17 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_opacity"
"name": "m_opacity"
}
},
{
"id": "shadeAll",
"name": "shadeAll",
"displayName": "Shade All",
"description": "Shades the entire geometry with the shadow color, not just what's in shadow. For debugging.",
"type": "Bool",
"connection": {
"type": "ShaderOption",
"id": "o_shadeAll"
"name": "o_shadeAll"
}
}
]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,38 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
namespace AZ
{
class ReflectContext;
namespace RPI
{
//! The property connection itself is rather simple, but we need this custom serializer to provide backward compatibility
//! for when the "id" key was changed to "name". If the JSON serialization system is ever updated to provide built-in
//! support for versioning, then we can probably remove this class.
class JsonMaterialPropertyConnectionSerializer
: public BaseJsonSerializer
{
public:
AZ_RTTI(JsonMaterialPropertyConnectionSerializer, "{2B7F00CF-51F7-4409-9C0E-914E59696FB9}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue,
const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
} // namespace RPI
} // namespace AZ
@@ -0,0 +1,38 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
namespace AZ
{
class ReflectContext;
namespace RPI
{
//! The property group itself is rather simple, but we need this custom serializer to provide backward compatibility
//! for when the "id" key was changed to "name". If the JSON serialization system is ever updated to provide built-in
//! support for versioning, then we can probably remove this class.
class JsonMaterialPropertyGroupSerializer
: public BaseJsonSerializer
{
public:
AZ_RTTI(JsonMaterialPropertyGroupSerializer, "{74C56BBC-2084-46AF-9393-04C2FBDF6B20}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue,
const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
} // namespace RPI
} // namespace AZ
@@ -40,12 +40,12 @@ namespace AZ
AZ_TYPE_INFO(AZ::RPI::MaterialTypeSourceData::PropertyConnection, "{C2F37C26-D7EF-4142-A650-EF50BB18610F}");
PropertyConnection() = default;
PropertyConnection(MaterialPropertyOutputType type, AZStd::string_view nameId, int32_t shaderIndex = -1);
PropertyConnection(MaterialPropertyOutputType type, AZStd::string_view fieldName, int32_t shaderIndex = -1);
MaterialPropertyOutputType m_type = MaterialPropertyOutputType::Invalid;
//! The name of a specific shader setting. This will either be a ShaderResourceGroup input or a ShaderOption, depending on m_type
AZStd::string m_nameId;
AZStd::string m_fieldName;
//! For m_type==ShaderOption, this is either the index of a specific shader in m_shaderCollection, or -1 which means every shader in m_shaderCollection.
//! For m_type==ShaderInput, this field is not used.
@@ -58,8 +58,8 @@ namespace AZ
{
AZ_TYPE_INFO(AZ::RPI::MaterialTypeSourceData::GroupDefinition, "{B2D0FC5C-72A3-435E-A194-1BFDABAC253D}");
//! The unique name of the property group. A property's full ID will be groupNameId.propertyNameId.
AZStd::string m_nameId;
//! The unique name of the property group. The full property ID will be groupName.propertyName
AZStd::string m_name;
// Editor metadata ...
AZStd::string m_displayName;
@@ -74,7 +74,7 @@ namespace AZ
static const float DefaultMax;
static const float DefaultStep;
AZStd::string m_nameId; //!< The name of the property within the property group. The full ID will be groupNameId.propertyNameId.
AZStd::string m_name; //!< The name of the property within the property group. The full property ID will be groupName.propertyName.
MaterialPropertyVisibility m_visibility = MaterialPropertyVisibility::Default;
@@ -130,7 +130,7 @@ namespace AZ
AZStd::vector<GroupDefinition> m_groups;
//! Collection of all available user-facing properties
AZStd::map<AZStd::string /*group name ID*/, PropertyList> m_properties;
AZStd::map<AZStd::string /*group name*/, PropertyList> m_properties;
};
AZStd::string m_description;
@@ -151,9 +151,9 @@ namespace AZ
//! Copy over UV custom names to the properties enum values.
void ResolveUvEnums();
const GroupDefinition* FindGroup(AZStd::string_view groupNameId) const;
const GroupDefinition* FindGroup(AZStd::string_view groupName) const;
const PropertyDefinition* FindProperty(AZStd::string_view groupNameId, AZStd::string_view propertyNameId) const;
const PropertyDefinition* FindProperty(AZStd::string_view groupName, AZStd::string_view propertyName) const;
//! Construct a complete list of group definitions, including implicit groups, arranged in the same order as the source data
//! Groups with the same name will be consolidated into a single entry
@@ -15,6 +15,13 @@
namespace AZ
{
class JsonDeserializerContext;
namespace JsonSerializationResult
{
union ResultCode;
}
namespace RPI
{
class MaterialTypeSourceData;
@@ -35,6 +42,17 @@ namespace AZ
//! @param filePath a relative path if document is provided, an absolute path if document is not provided.
//! @param document the loaded json document.
AZ::Outcome<MaterialTypeSourceData> LoadMaterialTypeSourceData(const AZStd::string& filePath, const rapidjson::Value* document = nullptr);
//! Utility function for custom JSON serializers to report results as "Skipped" when encountering keys that aren't recognized
//! as part of the custom format.
//! @param acceptedFieldNames an array of names that are recognized by the custom format
//! @param acceptedFieldNameCount the number of elements in @acceptedFieldNames
//! @param object the JSON object being loaded
//! @param context the common JsonDeserializerContext that is central to the serialization process
//! @param result the ResultCode that well be updated with the Outcomes "Skipped" if an unrecognized field is encountered
void CheckForUnrecognizedJsonFields(
const AZStd::string_view* acceptedFieldNames, uint32_t acceptedFieldNameCount,
const rapidjson::Value& object, JsonDeserializerContext& context, JsonSerializationResult::ResultCode& result);
}
}
}
@@ -70,8 +70,8 @@ namespace AZ
virtual ~Material();
//! Finds the material property index from the material property name
MaterialPropertyIndex FindPropertyIndex(const Name& name) const;
//! Finds the material property index from the material property ID
MaterialPropertyIndex FindPropertyIndex(const Name& propertyId) const;
//! Sets the value of a material property. The template data type must match the property's data type.
//! @return true if property value was changed
@@ -35,7 +35,7 @@ namespace AZ
AZ_DISABLE_COPY_MOVE(MaterialPropertiesLayout);
size_t GetPropertyCount() const;
MaterialPropertyIndex FindPropertyIndex(const Name& propertyName) const;
MaterialPropertyIndex FindPropertyIndex(const Name& propertyId) const;
const MaterialPropertyDescriptor* GetPropertyDescriptor(MaterialPropertyIndex index) const;
private:
@@ -47,7 +47,7 @@ namespace AZ
{
AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor;
materialBuilderDescriptor.m_name = JobKey;
materialBuilderDescriptor.m_version = 108; // Set materialtype dependency to OrderOnce
materialBuilderDescriptor.m_version = 109; // Changed "id" to "name" in serialization
materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.material", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.materialtype", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
materialBuilderDescriptor.m_busId = azrtti_typeid<MaterialBuilder>();
@@ -0,0 +1,126 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/RPI.Edit/Material/MaterialPropertyConnectionSerializer.h>
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/StackedString.h>
namespace AZ
{
namespace RPI
{
namespace JsonMaterialPropertyConnectionSerializerInternal
{
namespace Field
{
static constexpr const char type[] = "type";
static constexpr const char name[] = "name";
static constexpr const char id[] = "id"; // For backward compatibility
static constexpr const char shaderIndex[] = "shaderIndex";
}
static const AZStd::string_view AcceptedFields[] =
{
Field::type,
Field::name,
Field::id,
Field::shaderIndex
};
}
AZ_CLASS_ALLOCATOR_IMPL(JsonMaterialPropertyConnectionSerializer, SystemAllocator, 0);
JsonSerializationResult::Result JsonMaterialPropertyConnectionSerializer::Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertyConnectionSerializerInternal;
AZ_Assert(azrtti_typeid<MaterialTypeSourceData::PropertyConnection>() == outputValueTypeId,
"Unable to deserialize material property connection to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
MaterialTypeSourceData::PropertyConnection* propertyConnection = reinterpret_cast<MaterialTypeSourceData::PropertyConnection*>(outputValue);
AZ_Assert(propertyConnection, "Output value for JsonMaterialPropertyConnectionSerializer can't be null.");
JSR::ResultCode result(JSR::Tasks::ReadField);
if (!inputValue.IsObject())
{
return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Unsupported, "Property connection must be a JSON object.");
}
MaterialUtils::CheckForUnrecognizedJsonFields(AcceptedFields, AZ_ARRAY_SIZE(AcceptedFields), inputValue, context, result);
result.Combine(ContinueLoadingFromJsonObjectField(&propertyConnection->m_type, azrtti_typeid<MaterialPropertyOutputType>(), inputValue, Field::type, context));
JsonSerializationResult::ResultCode nameResult = ContinueLoadingFromJsonObjectField(&propertyConnection->m_fieldName, azrtti_typeid<AZStd::string>(), inputValue, Field::name, context);
if (nameResult.GetOutcome() == JsonSerializationResult::Outcomes::DefaultsUsed)
{
// This "id" key is for backward compatibility.
result.Combine(ContinueLoadingFromJsonObjectField(&propertyConnection->m_fieldName, azrtti_typeid<AZStd::string>(), inputValue, Field::id, context));
}
else
{
result.Combine(nameResult);
}
result.Combine(ContinueLoadingFromJsonObjectField(&propertyConnection->m_shaderIndex, azrtti_typeid<int32_t>(), inputValue, Field::shaderIndex, context));
if (result.GetProcessing() == JsonSerializationResult::Processing::Completed)
{
return context.Report(result, "Successfully loaded property connection.");
}
else
{
return context.Report(result, "Partially loaded property connection.");
}
}
JsonSerializationResult::Result JsonMaterialPropertyConnectionSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
[[maybe_unused]] const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertyConnectionSerializerInternal;
AZ_Assert(azrtti_typeid<MaterialTypeSourceData::PropertyConnection>() == valueTypeId,
"Unable to serialize material property connection to json because the provided type is %s",
valueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(valueTypeId);
const MaterialTypeSourceData::PropertyConnection* propertyConnection = reinterpret_cast<const MaterialTypeSourceData::PropertyConnection*>(inputValue);
AZ_Assert(propertyConnection, "Input value for JsonMaterialPropertyConnectionSerializer can't be null.");
JSR::ResultCode result(JSR::Tasks::WriteValue);
outputValue.SetObject();
MaterialTypeSourceData::PropertyConnection defaultConnection;
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::type, &propertyConnection->m_type, &defaultConnection.m_type, azrtti_typeid<MaterialPropertyOutputType>(), context));
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::name, &propertyConnection->m_fieldName, &defaultConnection.m_fieldName, azrtti_typeid<AZStd::string>(), context));
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::shaderIndex, &propertyConnection->m_shaderIndex, &defaultConnection.m_shaderIndex, azrtti_typeid<int32_t>(), context));
if (result.GetProcessing() == JsonSerializationResult::Processing::Completed)
{
return context.Report(result, "Successfully stored property connection.");
}
else
{
return context.Report(result, "Partially stored property connection.");
}
}
} // namespace RPI
} // namespace AZ
@@ -0,0 +1,125 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/RPI.Edit/Material/MaterialPropertyGroupSerializer.h>
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/StackedString.h>
namespace AZ
{
namespace RPI
{
namespace JsonMaterialPropertyGroupSerializerInternal
{
namespace Field
{
static constexpr const char name[] = "name";
static constexpr const char id[] = "id"; // For backward compatibility
static constexpr const char displayName[] = "displayName";
static constexpr const char description[] = "description";
}
static const AZStd::string_view AcceptedFields[] =
{
Field::name,
Field::id,
Field::displayName,
Field::description
};
}
AZ_CLASS_ALLOCATOR_IMPL(JsonMaterialPropertyGroupSerializer, SystemAllocator, 0);
JsonSerializationResult::Result JsonMaterialPropertyGroupSerializer::Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertyGroupSerializerInternal;
AZ_Assert(azrtti_typeid<MaterialTypeSourceData::GroupDefinition>() == outputValueTypeId,
"Unable to deserialize material property group to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
MaterialTypeSourceData::GroupDefinition* propertyGroup = reinterpret_cast<MaterialTypeSourceData::GroupDefinition*>(outputValue);
AZ_Assert(propertyGroup, "Output value for JsonMaterialPropertyGroupSerializer can't be null.");
JSR::ResultCode result(JSR::Tasks::ReadField);
if (!inputValue.IsObject())
{
return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Unsupported, "Property group must be a JSON object.");
}
MaterialUtils::CheckForUnrecognizedJsonFields(AcceptedFields, AZ_ARRAY_SIZE(AcceptedFields), inputValue, context, result);
JsonSerializationResult::ResultCode nameResult = ContinueLoadingFromJsonObjectField(&propertyGroup->m_name, azrtti_typeid<AZStd::string>(), inputValue, Field::name, context);
if (nameResult.GetOutcome() == JsonSerializationResult::Outcomes::DefaultsUsed)
{
// This "id" key is for backward compatibility.
result.Combine(ContinueLoadingFromJsonObjectField(&propertyGroup->m_name, azrtti_typeid<AZStd::string>(), inputValue, Field::id, context));
}
else
{
result.Combine(nameResult);
}
result.Combine(ContinueLoadingFromJsonObjectField(&propertyGroup->m_displayName, azrtti_typeid<AZStd::string>(), inputValue, Field::displayName, context));
result.Combine(ContinueLoadingFromJsonObjectField(&propertyGroup->m_description, azrtti_typeid<AZStd::string>(), inputValue, Field::description, context));
if (result.GetProcessing() == JsonSerializationResult::Processing::Completed)
{
return context.Report(result, "Successfully loaded property group.");
}
else
{
return context.Report(result, "Partially loaded property group.");
}
}
JsonSerializationResult::Result JsonMaterialPropertyGroupSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
[[maybe_unused]] const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertyGroupSerializerInternal;
AZ_Assert(azrtti_typeid<MaterialTypeSourceData::GroupDefinition>() == valueTypeId,
"Unable to serialize material property group to json because the provided type is %s",
valueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(valueTypeId);
const MaterialTypeSourceData::GroupDefinition* propertyGroup = reinterpret_cast<const MaterialTypeSourceData::GroupDefinition*>(inputValue);
AZ_Assert(propertyGroup, "Input value for JsonMaterialPropertyGroupSerializer can't be null.");
JSR::ResultCode result(JSR::Tasks::WriteValue);
outputValue.SetObject();
AZStd::string defaultEmpty;
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::name, &propertyGroup->m_name, &defaultEmpty, azrtti_typeid<AZStd::string>(), context));
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::displayName, &propertyGroup->m_displayName, &defaultEmpty, azrtti_typeid<AZStd::string>(), context));
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::description, &propertyGroup->m_description, &defaultEmpty, azrtti_typeid<AZStd::string>(), context));
if (result.GetProcessing() == JsonSerializationResult::Processing::Completed)
{
return context.Report(result, "Successfully stored property group.");
}
else
{
return context.Report(result, "Partially stored property group.");
}
}
} // namespace RPI
} // namespace AZ
@@ -8,6 +8,7 @@
#include <Atom/RPI.Edit/Material/MaterialPropertySerializer.h>
#include <Atom/RPI.Edit/Material/MaterialPropertyId.h>
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
@@ -23,11 +24,12 @@ namespace AZ
{
namespace RPI
{
namespace // Avoid conflicts in uber builds
namespace JsonMaterialPropertySerializerInternal
{
namespace Field
{
static constexpr const char id[] = "id";
static constexpr const char name[] = "name";
static constexpr const char id[] = "id"; // For backward compatibility
static constexpr const char displayName[] = "displayName";
static constexpr const char description[] = "description";
static constexpr const char type[] = "type";
@@ -46,6 +48,7 @@ namespace AZ
static const AZStd::string_view AcceptedFields[] =
{
Field::name,
Field::id,
Field::displayName,
Field::description,
@@ -103,6 +106,7 @@ namespace AZ
JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
JSR::ResultCode result(JSR::Tasks::ReadField);
@@ -160,6 +164,7 @@ namespace AZ
JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
JSR::ResultCode result(JSR::Tasks::ReadField);
@@ -181,6 +186,7 @@ namespace AZ
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
AZ_Assert(azrtti_typeid<MaterialTypeSourceData::PropertyDefinition>() == outputValueTypeId,
"Unable to deserialize material property to json because the provided type is %s",
@@ -197,28 +203,19 @@ namespace AZ
return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Unsupported, "Property definition must be a JSON object.");
}
// First check for unexpected fields
for (auto iter = inputValue.MemberBegin(); iter != inputValue.MemberEnd(); ++iter)
MaterialUtils::CheckForUnrecognizedJsonFields(AcceptedFields, AZ_ARRAY_SIZE(AcceptedFields), inputValue, context, result);
JsonSerializationResult::ResultCode nameResult = ContinueLoadingFromJsonObjectField(&property->m_name, azrtti_typeid<AZStd::string>(), inputValue, Field::name, context);
if (nameResult.GetOutcome() == JsonSerializationResult::Outcomes::DefaultsUsed)
{
bool matched = false;
for (int i = 0; i < AZ_ARRAY_SIZE(AcceptedFields); ++i)
{
if (iter->name.GetString() == AcceptedFields[i])
{
matched = true;
break;
}
}
if (!matched)
{
ScopedContextPath subPath{context, iter->name.GetString()};
result.Combine(context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Skipped, "Skipping unrecognized field"));
}
// This "id" key is for backward compatibility.
result.Combine(ContinueLoadingFromJsonObjectField(&property->m_name, azrtti_typeid<AZStd::string>(), inputValue, Field::id, context));
}
else
{
result.Combine(nameResult);
}
result.Combine(ContinueLoadingFromJsonObjectField(&property->m_nameId, azrtti_typeid<AZStd::string>(), inputValue, Field::id, context));
result.Combine(ContinueLoadingFromJsonObjectField(&property->m_displayName, azrtti_typeid<AZStd::string>(), inputValue, Field::displayName, context));
result.Combine(ContinueLoadingFromJsonObjectField(&property->m_description, azrtti_typeid<AZStd::string>(), inputValue, Field::description, context));
result.Combine(ContinueLoadingFromJsonObjectField(&property->m_dataType, azrtti_typeid<MaterialPropertyDataType>(), inputValue, Field::type, context));
@@ -302,6 +299,8 @@ namespace AZ
JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
JSR::ResultCode result(JSR::Tasks::WriteValue);
if (property->m_value.Is<T>())
@@ -345,6 +344,8 @@ namespace AZ
JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
JsonSerializationResult::ResultCode result(JSR::Tasks::WriteValue);
if (property->m_value.Is<T>())
@@ -360,6 +361,7 @@ namespace AZ
[[maybe_unused]] const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
AZ_Assert(azrtti_typeid<MaterialTypeSourceData::PropertyDefinition>() == valueTypeId,
"Unable to serialize material property to json because the provided type is %s",
@@ -374,7 +376,7 @@ namespace AZ
outputValue.SetObject();
const AZStd::string emptyString;
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::id, &property->m_nameId, &emptyString, azrtti_typeid<AZStd::string>(), context));
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::name, &property->m_name, &emptyString, azrtti_typeid<AZStd::string>(), context));
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::displayName, &property->m_displayName, &emptyString, azrtti_typeid<AZStd::string>(), context));
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::description, &property->m_description, &emptyString, azrtti_typeid<AZStd::string>(), context));
@@ -452,6 +454,8 @@ namespace AZ
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
JSR::ResultCode result(JSR::Tasks::ReadField);
if (inputValue.HasMember(Field::vectorLabels))
@@ -467,6 +471,8 @@ namespace AZ
{
AZStd::string emptyString;
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
JsonSerializationResult::ResultCode result(JSR::Tasks::WriteValue);
if (!property->m_vectorLabels.empty())
@@ -62,18 +62,18 @@ namespace AZ
return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Catastrophic, "Material type reference not found.");
}
// Construct the full property name (groupId.propertyId) by parsing it from the JSON path string.
size_t startPropertyNameId = context.GetPath().Get().rfind('/');
size_t startGroupNameId = context.GetPath().Get().rfind('/', startPropertyNameId-1);
AZStd::string_view groupNameId = context.GetPath().Get().substr(startGroupNameId + 1, startPropertyNameId - startGroupNameId - 1);
AZStd::string_view propertyNameId = context.GetPath().Get().substr(startPropertyNameId + 1);
// Construct the full property name (groupName.propertyName) by parsing it from the JSON path string.
size_t startPropertyName = context.GetPath().Get().rfind('/');
size_t startGroupName = context.GetPath().Get().rfind('/', startPropertyName-1);
AZStd::string_view groupName = context.GetPath().Get().substr(startGroupName + 1, startPropertyName - startGroupName - 1);
AZStd::string_view propertyName = context.GetPath().Get().substr(startPropertyName + 1);
JSR::ResultCode result(JSR::Tasks::ReadField);
auto propertyDefinition = materialType->FindProperty(groupNameId, propertyNameId);
auto propertyDefinition = materialType->FindProperty(groupName, propertyName);
if (!propertyDefinition)
{
AZStd::string message = AZStd::string::format("Property '%.*s.%.*s' not found in material type.", AZ_STRING_ARG(groupNameId), AZ_STRING_ARG(propertyNameId));
AZStd::string message = AZStd::string::format("Property '%.*s.%.*s' not found in material type.", AZ_STRING_ARG(groupName), AZ_STRING_ARG(propertyName));
return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Unsupported, message);
}
else
@@ -9,6 +9,8 @@
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialPropertySerializer.h>
#include <Atom/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.h>
#include <Atom/RPI.Edit/Material/MaterialPropertyConnectionSerializer.h>
#include <Atom/RPI.Edit/Material/MaterialPropertyGroupSerializer.h>
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
@@ -46,29 +48,17 @@ namespace AZ
if (JsonRegistrationContext* jsonContext = azrtti_cast<JsonRegistrationContext*>(context))
{
jsonContext->Serializer<JsonMaterialPropertySerializer>()->HandlesType<MaterialTypeSourceData::PropertyDefinition>();
jsonContext->Serializer<JsonMaterialPropertyConnectionSerializer>()->HandlesType<MaterialTypeSourceData::PropertyConnection>();
jsonContext->Serializer<JsonMaterialPropertyGroupSerializer>()->HandlesType<MaterialTypeSourceData::GroupDefinition>();
}
else if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
{
serializeContext->Class<PropertyConnection>()
->Version(1)
->Field("type", &PropertyConnection::m_type)
->Field("id", &PropertyConnection::m_nameId)
->Field("shaderIndex", &PropertyConnection::m_shaderIndex)
;
serializeContext->Class<PropertyConnection>()->Version(3);
serializeContext->Class<GroupDefinition>()->Version(4);
serializeContext->Class<PropertyDefinition>()->Version(1);
serializeContext->RegisterGenericType<PropertyConnectionList>();
serializeContext->Class<GroupDefinition>()
->Version(1)
->Field("id", &GroupDefinition::m_nameId)
->Field("displayName", &GroupDefinition::m_displayName)
->Field("description", &GroupDefinition::m_description)
;
serializeContext->Class<PropertyDefinition>()
->Version(1)
;
serializeContext->Class<ShaderVariantReferenceData>()
->Version(2)
->Field("file", &ShaderVariantReferenceData::m_shaderFilePath)
@@ -96,9 +86,9 @@ namespace AZ
}
}
MaterialTypeSourceData::PropertyConnection::PropertyConnection(MaterialPropertyOutputType type, AZStd::string_view nameId, int32_t shaderIndex)
MaterialTypeSourceData::PropertyConnection::PropertyConnection(MaterialPropertyOutputType type, AZStd::string_view fieldName, int32_t shaderIndex)
: m_type(type)
, m_nameId(nameId)
, m_fieldName(fieldName)
, m_shaderIndex(shaderIndex)
{
}
@@ -107,11 +97,11 @@ namespace AZ
const float MaterialTypeSourceData::PropertyDefinition::DefaultMax = std::numeric_limits<float>::max();
const float MaterialTypeSourceData::PropertyDefinition::DefaultStep = 0.1f;
const MaterialTypeSourceData::GroupDefinition* MaterialTypeSourceData::FindGroup(AZStd::string_view groupNameId) const
const MaterialTypeSourceData::GroupDefinition* MaterialTypeSourceData::FindGroup(AZStd::string_view groupName) const
{
for (const GroupDefinition& group : m_propertyLayout.m_groups)
{
if (group.m_nameId == groupNameId)
if (group.m_name == groupName)
{
return &group;
}
@@ -120,9 +110,9 @@ namespace AZ
return nullptr;
}
const MaterialTypeSourceData::PropertyDefinition* MaterialTypeSourceData::FindProperty(AZStd::string_view groupNameId, AZStd::string_view propertyNameId) const
const MaterialTypeSourceData::PropertyDefinition* MaterialTypeSourceData::FindProperty(AZStd::string_view groupName, AZStd::string_view propertyName) const
{
auto groupIter = m_propertyLayout.m_properties.find(groupNameId);
auto groupIter = m_propertyLayout.m_properties.find(groupName);
if (groupIter == m_propertyLayout.m_properties.end())
{
return nullptr;
@@ -130,7 +120,7 @@ namespace AZ
for (const PropertyDefinition& property : groupIter->second)
{
if (property.m_nameId == propertyNameId)
if (property.m_name == propertyName)
{
return &property;
}
@@ -169,24 +159,24 @@ namespace AZ
AZStd::unordered_set<AZStd::string> foundGroups;
for (const auto& groupDefinition : m_propertyLayout.m_groups)
{
if (foundGroups.insert(groupDefinition.m_nameId).second)
if (foundGroups.insert(groupDefinition.m_name).second)
{
groupDefinitions.push_back(groupDefinition);
}
else
{
AZ_Warning("Material source data", false, "Duplicate group '%s' found.", groupDefinition.m_nameId.c_str());
AZ_Warning("Material source data", false, "Duplicate group '%s' found.", groupDefinition.m_name.c_str());
}
}
// Some groups are defined implicitly, in the "properties" section where a group name is used but not explicitly defined in the "groups" section.
for (const auto& propertyListPair : m_propertyLayout.m_properties)
{
const AZStd::string& groupNameId = propertyListPair.first;
if (foundGroups.insert(groupNameId).second)
const AZStd::string& groupName = propertyListPair.first;
if (foundGroups.insert(groupName).second)
{
MaterialTypeSourceData::GroupDefinition groupDefinition;
groupDefinition.m_nameId = groupNameId;
groupDefinition.m_name = groupName;
groupDefinitions.push_back(groupDefinition);
}
}
@@ -203,12 +193,12 @@ namespace AZ
for (const auto& propertyListPair : m_propertyLayout.m_properties)
{
const AZStd::string& groupNameId = propertyListPair.first;
const AZStd::string& groupName = propertyListPair.first;
const auto& propertyList = propertyListPair.second;
for (const auto& propertyDefinition : propertyList)
{
const AZStd::string& propertyNameId = propertyDefinition.m_nameId;
if (!callback(groupNameId, propertyNameId, propertyDefinition))
const AZStd::string& propertyName = propertyDefinition.m_name;
if (!callback(groupName, propertyName, propertyDefinition))
{
return;
}
@@ -225,15 +215,15 @@ namespace AZ
for (const auto& groupDefinition : GetGroupDefinitionsInDisplayOrder())
{
const AZStd::string& groupNameId = groupDefinition.m_nameId;
const auto propertyListItr = m_propertyLayout.m_properties.find(groupNameId);
const AZStd::string& groupName = groupDefinition.m_name;
const auto propertyListItr = m_propertyLayout.m_properties.find(groupName);
if (propertyListItr != m_propertyLayout.m_properties.end())
{
const auto& propertyList = propertyListItr->second;
for (const auto& propertyDefinition : propertyList)
{
const AZStd::string& propertyNameId = propertyDefinition.m_nameId;
if (!callback(groupNameId, propertyNameId, propertyDefinition))
const AZStd::string& propertyName = propertyDefinition.m_name;
if (!callback(groupName, propertyName, propertyDefinition))
{
return;
}
@@ -249,7 +239,7 @@ namespace AZ
const uint32_t index = propertyValue.GetValue<uint32_t>();
if (index >= propertyDefinition.m_enumValues.size())
{
AZ_Error("Material source data", false, "Invalid value for material enum property: '%s'.", propertyDefinition.m_nameId.c_str());
AZ_Error("Material source data", false, "Invalid value for material enum property: '%s'.", propertyDefinition.m_name.c_str());
return false;
}
@@ -272,7 +262,7 @@ namespace AZ
imageAsset.GetId(), imageAsset.GetType(), platformName, imageAssetInfo, rootFilePath);
if (!result)
{
AZ_Error("Material source data", false, "Image asset could not be found for property: '%s'.", propertyDefinition.m_nameId.c_str());
AZ_Error("Material source data", false, "Image asset could not be found for property: '%s'.", propertyDefinition.m_name.c_str());
return false;
}
}
@@ -340,13 +330,13 @@ namespace AZ
for (auto& groupIter : m_propertyLayout.m_properties)
{
const AZStd::string& groupNameId = groupIter.first;
const AZStd::string& groupName = groupIter.first;
for (const PropertyDefinition& property : groupIter.second)
{
// Register the property...
MaterialPropertyId propertyId{ groupNameId, property.m_nameId };
MaterialPropertyId propertyId{ groupName, property.m_name };
if (!propertyId.IsValid())
{
@@ -366,16 +356,16 @@ namespace AZ
switch (output.m_type)
{
case MaterialPropertyOutputType::ShaderInput:
materialTypeAssetCreator.ConnectMaterialPropertyToShaderInput(Name{ output.m_nameId.data() });
materialTypeAssetCreator.ConnectMaterialPropertyToShaderInput(Name{ output.m_fieldName.data() });
break;
case MaterialPropertyOutputType::ShaderOption:
if (output.m_shaderIndex >= 0)
{
materialTypeAssetCreator.ConnectMaterialPropertyToShaderOption(Name{ output.m_nameId.data() }, output.m_shaderIndex);
materialTypeAssetCreator.ConnectMaterialPropertyToShaderOption(Name{ output.m_fieldName.data() }, output.m_shaderIndex);
}
else
{
materialTypeAssetCreator.ConnectMaterialPropertyToShaderOptions(Name{ output.m_nameId.data() });
materialTypeAssetCreator.ConnectMaterialPropertyToShaderOptions(Name{ output.m_fieldName.data() });
}
break;
case MaterialPropertyOutputType::Invalid:
@@ -17,6 +17,8 @@
#include <Atom/RPI.Edit/Common/JsonFileLoadContext.h>
#include <Atom/RPI.Edit/Common/JsonUtils.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
#include <AzCore/std/string/string.h>
@@ -99,6 +101,29 @@ namespace AZ
return AZ::Success(AZStd::move(materialType));
}
}
void CheckForUnrecognizedJsonFields(const AZStd::string_view* acceptedFieldNames, uint32_t acceptedFieldNameCount, const rapidjson::Value& object, JsonDeserializerContext& context, JsonSerializationResult::ResultCode &result)
{
for (auto iter = object.MemberBegin(); iter != object.MemberEnd(); ++iter)
{
bool matched = false;
for (uint32_t i = 0; i < acceptedFieldNameCount; ++i)
{
if (iter->name.GetString() == acceptedFieldNames[i])
{
matched = true;
break;
}
}
if (!matched)
{
ScopedContextPath subPath{context, iter->name.GetString()};
result.Combine(context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Skipped, "Skipping unrecognized field"));
}
}
}
}
}
}
@@ -386,9 +386,9 @@ namespace AZ
return m_currentChangeId;
}
MaterialPropertyIndex Material::FindPropertyIndex(const Name& name) const
MaterialPropertyIndex Material::FindPropertyIndex(const Name& propertyId) const
{
return m_layout->FindPropertyIndex(name);
return m_layout->FindPropertyIndex(propertyId);
}
template<typename Type>
@@ -34,9 +34,9 @@ namespace AZ
return m_materialPropertyDescriptors.size();
}
MaterialPropertyIndex MaterialPropertiesLayout::FindPropertyIndex(const Name& propertyName) const
MaterialPropertyIndex MaterialPropertiesLayout::FindPropertyIndex(const Name& propertyId) const
{
return m_materialPropertyIndexes.Find(propertyName);
return m_materialPropertyIndexes.Find(propertyId);
}
const MaterialPropertyDescriptor* MaterialPropertiesLayout::GetPropertyDescriptor(MaterialPropertyIndex index) const
@@ -46,7 +46,7 @@ namespace JsonSerializationTests
AZStd::shared_ptr<AZ::RPI::MaterialTypeSourceData::PropertyDefinition> CreatePartialDefaultInstance() override
{
auto result = AZStd::make_shared<AZ::RPI::MaterialTypeSourceData::PropertyDefinition>();
result->m_nameId = "testProperty";
result->m_name = "testProperty";
result->m_dataType = AZ::RPI::MaterialPropertyDataType::Float;
result->m_step = 1.0f;
result->m_value = 0.0f;
@@ -57,7 +57,7 @@ namespace JsonSerializationTests
{
return R"(
{
"id": "testProperty",
"name": "testProperty",
"type": "Float",
"step": 1.0
})";
@@ -66,7 +66,7 @@ namespace JsonSerializationTests
AZStd::shared_ptr<AZ::RPI::MaterialTypeSourceData::PropertyDefinition> CreateFullySetInstance() override
{
auto result = AZStd::make_shared<AZ::RPI::MaterialTypeSourceData::PropertyDefinition>();
result->m_nameId = "testProperty";
result->m_name = "testProperty";
result->m_description = "description";
result->m_displayName = "display_name";
result->m_dataType = AZ::RPI::MaterialPropertyDataType::Float;
@@ -87,7 +87,7 @@ namespace JsonSerializationTests
{
return R"(
{
"id": "testProperty",
"name": "testProperty",
"displayName": "display_name",
"description": "description",
"type": "Float",
@@ -101,7 +101,7 @@ namespace JsonSerializationTests
"connection":
{
"type": "ShaderOption",
"id": "o_foo",
"name": "o_foo",
"shaderIndex": 2
},
"enumIsUv": true
@@ -135,7 +135,7 @@ namespace JsonSerializationTests
const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& lhs,
const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& rhs) override
{
if (lhs.m_nameId != rhs.m_nameId) { return false; }
if (lhs.m_name != rhs.m_name) { return false; }
if (lhs.m_description != rhs.m_description) { return false; }
if (lhs.m_displayName != rhs.m_displayName) { return false; }
if (lhs.m_dataType != rhs.m_dataType) { return false; }
@@ -153,7 +153,7 @@ namespace JsonSerializationTests
auto& leftConnection = lhs.m_outputConnections[i];
auto& rightConnection = rhs.m_outputConnections[i];
if (leftConnection.m_type != rightConnection.m_type) { return false; }
if (leftConnection.m_nameId != rightConnection.m_nameId) { return false; }
if (leftConnection.m_fieldName != rightConnection.m_fieldName) { return false; }
if (leftConnection.m_shaderIndex != rightConnection.m_shaderIndex) { return false; }
}
return true;
@@ -202,7 +202,7 @@ namespace UnitTest
{
const AZStd::string inputJson = R"(
{
"id": "testProperty",
"name": "testProperty",
"displayName": "Test Property",
"description": "This is a property description",
"type": "Float"
@@ -216,12 +216,12 @@ namespace UnitTest
EXPECT_EQ(AZ::JsonSerializationResult::Processing::Completed, loadResult.m_jsonResultCode.GetProcessing());
EXPECT_EQ(AZ::JsonSerializationResult::Outcomes::PartialDefaults, loadResult.m_jsonResultCode.GetOutcome());
EXPECT_EQ("testProperty", propertyData.m_nameId);
EXPECT_EQ("testProperty", propertyData.m_name);
EXPECT_EQ("Test Property", propertyData.m_displayName);
EXPECT_EQ("This is a property description", propertyData.m_description);
EXPECT_EQ(MaterialPropertyDataType::Float, propertyData.m_dataType);
EXPECT_TRUE(loadResult.ContainsMessage("/id", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/name", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/displayName", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/description", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/type", "Success"));
@@ -237,7 +237,7 @@ namespace UnitTest
// Note we are keeping id and type because they are required fields
const AZStd::string inputJson = R"(
{
"id": "testProperty",
"name": "testProperty",
"type": "Float"
}
)";
@@ -252,7 +252,7 @@ namespace UnitTest
EXPECT_TRUE(propertyData.m_displayName.empty());
EXPECT_TRUE(propertyData.m_description.empty());
EXPECT_TRUE(loadResult.ContainsMessage("/id", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/name", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/type", "Success"));
EXPECT_FALSE(loadResult.ContainsOutcome(JsonSerializationResult::Outcomes::Skipped));
@@ -280,7 +280,7 @@ namespace UnitTest
{
const AZStd::string inputJson = R"(
{
"id": "testProperty",
"name": "testProperty",
"type": "foo"
}
)";
@@ -294,7 +294,7 @@ namespace UnitTest
EXPECT_EQ(AZ::RPI::MaterialPropertyDataType::Invalid, propertyData.m_dataType);
EXPECT_TRUE(loadResult.ContainsMessage("/id", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/name", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/type", "Enum value could not read"));
}
@@ -303,7 +303,7 @@ namespace UnitTest
const AZStd::string inputJson = R"(
[
{
"id": "testProperty1",
"name": "testProperty1",
"type": "Float",
"defaultValue": 0.5,
"min": 0.1,
@@ -313,7 +313,7 @@ namespace UnitTest
"step": 0.05
},
{
"id": "testProperty2",
"name": "testProperty2",
"type": "Int",
"defaultValue": -1,
"min": -5,
@@ -323,7 +323,7 @@ namespace UnitTest
"step": 1
},
{
"id": "testProperty3",
"name": "testProperty3",
"type": "UInt",
"defaultValue": 4294901761,
"min": 4294901760,
@@ -368,7 +368,7 @@ namespace UnitTest
for (int i = 0; i < propertyData.size(); ++i)
{
AZStd::string prefix = AZStd::string::format("/%d", i);
EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/id", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/name", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/type", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/defaultValue", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/min", "Success"));
@@ -388,19 +388,19 @@ namespace UnitTest
const AZStd::string inputJson = R"(
[
{
"id": "testProperty1",
"name": "testProperty1",
"displayName": "Test Property 1",
"description": "Test",
"type": "Float"
},
{
"id": "testProperty2",
"name": "testProperty2",
"displayName": "Test Property 2",
"description": "Test",
"type": "Int"
},
{
"id": "testProperty3",
"name": "testProperty3",
"displayName": "Test Property 3",
"description": "Test",
"type": "UInt"
@@ -443,13 +443,13 @@ namespace UnitTest
const AZStd::string inputJson = R"(
[
{
"id": "testProperty1",
"name": "testProperty1",
"type": "Vector2",
"vectorLabels": ["U", "V"],
"defaultValue": [0.6, 0.5]
},
{
"id": "testProperty2",
"name": "testProperty2",
"type": "Vector4",
"vectorLabels": ["A", "B", "C", "D"],
"defaultValue": [0.3, 0.4, 0.5, 0.6]
@@ -485,21 +485,21 @@ namespace UnitTest
const AZStd::string inputJson = R"(
[
{
"id": "visibilityIsDefault",
"name": "visibilityIsDefault",
"type": "Float"
},
{
"id": "visibilityIsEditable",
"name": "visibilityIsEditable",
"type": "Float",
"visibility": "Enabled"
},
{
"id": "visibilityIsDisabled",
"name": "visibilityIsDisabled",
"type": "Float",
"visibility": "Disabled"
},
{
"id": "visibilityIsHidden",
"name": "visibilityIsHidden",
"type": "Float",
"visibility": "Hidden"
}
@@ -509,20 +509,20 @@ namespace UnitTest
const AZStd::string expectedOutputJson = R"(
[
{
"id": "visibilityIsDefault",
"name": "visibilityIsDefault",
"type": "Float"
},
{
"id": "visibilityIsEditable",
"name": "visibilityIsEditable",
"type": "Float"
},
{
"id": "visibilityIsDisabled",
"name": "visibilityIsDisabled",
"type": "Float",
"visibility": "Disabled"
},
{
"id": "visibilityIsHidden",
"name": "visibilityIsHidden",
"type": "Float",
"visibility": "Hidden"
}
@@ -552,7 +552,7 @@ namespace UnitTest
const AZStd::string inputJson = R"(
[
{
"id": "testProperty1",
"name": "testProperty1",
"type": "Float",
"defaultValue": true,
"min": -1,
@@ -560,7 +560,7 @@ namespace UnitTest
"step": "1"
},
{
"id": "testProperty2",
"name": "testProperty2",
"type": "Int",
"defaultValue": true,
"min": -1.5,
@@ -568,7 +568,7 @@ namespace UnitTest
"step": "1"
},
{
"id": "testProperty3",
"name": "testProperty3",
"type": "UInt",
"defaultValue": "4294963200",
"min": true,
@@ -610,32 +610,32 @@ namespace UnitTest
const AZStd::string inputJson = R"(
[
{
"id": "testProperty1",
"name": "testProperty1",
"type": "Bool",
"defaultValue": true
},
{
"id": "testProperty2",
"name": "testProperty2",
"type": "Vector2",
"defaultValue": [0.1, 0.2]
},
{
"id": "testProperty3",
"name": "testProperty3",
"type": "Vector3",
"defaultValue": [0.3, 0.4, 0.5]
},
{
"id": "testProperty4",
"name": "testProperty4",
"type": "Vector4",
"defaultValue": [0.6, 0.5, 0.8, 0.4]
},
{
"id": "testProperty5",
"name": "testProperty5",
"type": "Color",
"defaultValue": [0.1, 0.2, 0.3]
},
{
"id": "testProperty6",
"name": "testProperty6",
"type": "Image",
"defaultValue": "Default.png"
}
@@ -669,7 +669,7 @@ namespace UnitTest
for (int i = 0; i < propertyData.size(); ++i)
{
AZStd::string prefix = AZStd::string::format("/%d", i);
EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/id", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/name", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/type", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage(prefix + "/defaultValue", "Success"));
}
@@ -684,27 +684,27 @@ namespace UnitTest
const AZStd::string inputJson = R"(
[
{
"id": "testProperty1",
"name": "testProperty1",
"type": "Bool"
},
{
"id": "testProperty2",
"name": "testProperty2",
"type": "Vector2"
},
{
"id": "testProperty3",
"name": "testProperty3",
"type": "Vector3"
},
{
"id": "testProperty4",
"name": "testProperty4",
"type": "Vector4"
},
{
"id": "testProperty5",
"name": "testProperty5",
"type": "Color"
},
{
"id": "testProperty6",
"name": "testProperty6",
"type": "Image"
}
]
@@ -745,27 +745,27 @@ namespace UnitTest
const AZStd::string inputJson = R"(
[
{
"id": "testProperty1",
"name": "testProperty1",
"type": "Bool",
"defaultValue": 1
},
{
"id": "testProperty2",
"name": "testProperty2",
"type": "Vector2",
"defaultValue": { "x": 0.4, "y": 0.1 }
},
{
"id": "testProperty3",
"name": "testProperty3",
"type": "Vector3",
"defaultValue": { "x": 0.4, "y": 0.1, "z": 0.5 }
},
{
"id": "testProperty4",
"name": "testProperty4",
"type": "Vector4",
"defaultValue": { "x": 0.4, "y": 0.1, "z": 0.5, "w": 0.6 }
},
{
"id": "testProperty5",
"name": "testProperty5",
"type": "Color",
"defaultValue": { "hex": "FF00FF" }
}
@@ -798,6 +798,41 @@ namespace UnitTest
TEST_F(MaterialPropertySerializerTests, LoadAndStoreJson_OneConnection)
{
const AZStd::string inputJson = R"(
{
"name": "testProperty",
"type": "Float",
"connection": {
"type": "ShaderOption",
"name": "o_foo",
"shaderIndex": 2
}
}
)";
MaterialTypeSourceData::PropertyDefinition propertyData;
JsonTestResult loadResult = LoadTestDataFromJson(propertyData, inputJson);
EXPECT_EQ(AZ::JsonSerializationResult::Tasks::ReadField, loadResult.m_jsonResultCode.GetTask());
EXPECT_EQ(AZ::JsonSerializationResult::Processing::Completed, loadResult.m_jsonResultCode.GetProcessing());
EXPECT_EQ(1, propertyData.m_outputConnections.size());
EXPECT_EQ(MaterialPropertyOutputType::ShaderOption, propertyData.m_outputConnections[0].m_type);
EXPECT_EQ("o_foo", propertyData.m_outputConnections[0].m_fieldName);
EXPECT_EQ(2, propertyData.m_outputConnections[0].m_shaderIndex);
EXPECT_TRUE(loadResult.ContainsMessage("/connection/type", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/connection/name", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/connection/shaderIndex", "Success"));
EXPECT_FALSE(loadResult.ContainsOutcome(JsonSerializationResult::Outcomes::Skipped));
TestStoreToJson(propertyData, inputJson);
}
TEST_F(MaterialPropertySerializerTests, LoadUsingOldFormat)
{
// Tests backward compatibility for when "id" was the key instead of "name", for both the property and its connections.
const AZStd::string inputJson = R"(
{
"id": "testProperty",
@@ -815,35 +850,35 @@ namespace UnitTest
EXPECT_EQ(AZ::JsonSerializationResult::Tasks::ReadField, loadResult.m_jsonResultCode.GetTask());
EXPECT_EQ(AZ::JsonSerializationResult::Processing::Completed, loadResult.m_jsonResultCode.GetProcessing());
EXPECT_EQ("testProperty", propertyData.m_name);
EXPECT_EQ(1, propertyData.m_outputConnections.size());
EXPECT_EQ(MaterialPropertyOutputType::ShaderOption, propertyData.m_outputConnections[0].m_type);
EXPECT_EQ("o_foo", propertyData.m_outputConnections[0].m_nameId);
EXPECT_EQ("o_foo", propertyData.m_outputConnections[0].m_fieldName);
EXPECT_EQ(2, propertyData.m_outputConnections[0].m_shaderIndex);
EXPECT_TRUE(loadResult.ContainsMessage("/connection/type", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/connection/id", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/connection/shaderIndex", "Success"));
EXPECT_FALSE(loadResult.ContainsOutcome(JsonSerializationResult::Outcomes::Skipped));
TestStoreToJson(propertyData, inputJson);
}
TEST_F(MaterialPropertySerializerTests, LoadAndStoreJson_MultipleConnections)
{
const AZStd::string inputJson = R"(
{
"id": "testProperty",
"name": "testProperty",
"type": "Float",
"connection": [
{
"type": "ShaderInput",
"id": "o_foo",
"name": "o_foo",
"shaderIndex": 2
},
{
"type": "ShaderOption",
"id": "o_bar",
"name": "o_bar",
"shaderIndex": 1
}
]
@@ -858,18 +893,18 @@ namespace UnitTest
EXPECT_EQ(2, propertyData.m_outputConnections.size());
EXPECT_EQ(MaterialPropertyOutputType::ShaderInput, propertyData.m_outputConnections[0].m_type);
EXPECT_EQ("o_foo", propertyData.m_outputConnections[0].m_nameId);
EXPECT_EQ("o_foo", propertyData.m_outputConnections[0].m_fieldName);
EXPECT_EQ(2, propertyData.m_outputConnections[0].m_shaderIndex);
EXPECT_EQ(MaterialPropertyOutputType::ShaderOption, propertyData.m_outputConnections[1].m_type);
EXPECT_EQ("o_bar", propertyData.m_outputConnections[1].m_nameId);
EXPECT_EQ("o_bar", propertyData.m_outputConnections[1].m_fieldName);
EXPECT_EQ(1, propertyData.m_outputConnections[1].m_shaderIndex);
EXPECT_TRUE(loadResult.ContainsMessage("/connection/0/type", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/connection/0/id", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/connection/0/name", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/connection/0/shaderIndex", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/connection/1/type", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/connection/1/id", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/connection/1/name", "Success"));
EXPECT_TRUE(loadResult.ContainsMessage("/connection/1/shaderIndex", "Success"));
EXPECT_FALSE(loadResult.ContainsOutcome(JsonSerializationResult::Outcomes::Skipped));
@@ -881,12 +916,12 @@ namespace UnitTest
// "conection" is misspelled
const AZStd::string inputJson = R"(
{
"id": "testProperty",
"name": "testProperty",
"type": "Float",
"conection": [
{
"type": "ShaderInput",
"id": "o_foo",
"name": "o_foo",
"shaderIndex": 2
}
]
@@ -899,7 +934,7 @@ namespace UnitTest
EXPECT_EQ(AZ::JsonSerializationResult::Tasks::ReadField, loadResult.m_jsonResultCode.GetTask());
EXPECT_EQ(AZ::JsonSerializationResult::Processing::Completed, loadResult.m_jsonResultCode.GetProcessing());
EXPECT_EQ(propertyData.m_nameId, "testProperty");
EXPECT_EQ(propertyData.m_name, "testProperty");
EXPECT_EQ(propertyData.m_dataType, MaterialPropertyDataType::Float);
EXPECT_EQ(propertyData.m_outputConnections.size(), 0);
@@ -911,13 +946,13 @@ namespace UnitTest
// "shadrIndex" is misspelled
const AZStd::string inputJson = R"(
{
"id": "testProperty",
"name": "testProperty",
"type": "Float",
"connection": [
{
"type": "ShaderInput",
"shadrIndex": 2,
"id": "o_foo"
"name": "o_foo"
}
]
}
@@ -929,10 +964,10 @@ namespace UnitTest
EXPECT_EQ(AZ::JsonSerializationResult::Tasks::ReadField, loadResult.m_jsonResultCode.GetTask());
EXPECT_EQ(AZ::JsonSerializationResult::Processing::Completed, loadResult.m_jsonResultCode.GetProcessing());
EXPECT_EQ(propertyData.m_nameId, "testProperty");
EXPECT_EQ(propertyData.m_name, "testProperty");
EXPECT_EQ(propertyData.m_dataType, MaterialPropertyDataType::Float);
EXPECT_EQ(propertyData.m_outputConnections.size(), 1);
EXPECT_EQ(propertyData.m_outputConnections[0].m_nameId, "o_foo");
EXPECT_EQ(propertyData.m_outputConnections[0].m_fieldName, "o_foo");
EXPECT_EQ(propertyData.m_outputConnections[0].m_type, MaterialPropertyOutputType::ShaderInput);
EXPECT_EQ(propertyData.m_outputConnections[0].m_shaderIndex, -1);
@@ -89,14 +89,14 @@ namespace UnitTest
}
};
void AddPropertyGroup(MaterialSourceData& material, AZStd::string_view groupNameId)
void AddPropertyGroup(MaterialSourceData& material, AZStd::string_view groupName)
{
material.m_properties.insert(groupNameId);
material.m_properties.insert(groupName);
}
void AddProperty(MaterialSourceData& material, AZStd::string_view groupNameId, AZStd::string_view propertyNameId, const MaterialPropertyValue& anyValue)
void AddProperty(MaterialSourceData& material, AZStd::string_view groupName, AZStd::string_view propertyName, const MaterialPropertyValue& anyValue)
{
material.m_properties[groupNameId][propertyNameId].m_value = anyValue;
material.m_properties[groupName][propertyName].m_value = anyValue;
}
TEST_F(MaterialSourceDataTests, CreateMaterialAsset_BasicProperties)
@@ -205,25 +205,25 @@ namespace UnitTest
" \"propertyLayout\": { \n"
" \"version\": 1, \n"
" \"groups\": [ \n"
" { \"id\": \"groupA\" }, \n"
" { \"id\": \"groupB\" }, \n"
" { \"id\": \"groupC\" } \n"
" { \"name\": \"groupA\" }, \n"
" { \"name\": \"groupB\" }, \n"
" { \"name\": \"groupC\" } \n"
" ], \n"
" \"properties\": { \n"
" \"groupA\": [ \n"
" {\"id\": \"MyBool\", \"type\": \"bool\"}, \n"
" {\"id\": \"MyInt\", \"type\": \"int\"}, \n"
" {\"id\": \"MyUInt\", \"type\": \"uint\"} \n"
" {\"name\": \"MyBool\", \"type\": \"bool\"}, \n"
" {\"name\": \"MyInt\", \"type\": \"int\"}, \n"
" {\"name\": \"MyUInt\", \"type\": \"uint\"} \n"
" ], \n"
" \"groupB\": [ \n"
" {\"id\": \"MyFloat\", \"type\": \"float\"}, \n"
" {\"id\": \"MyFloat2\", \"type\": \"vector2\"}, \n"
" {\"id\": \"MyFloat3\", \"type\": \"vector3\"} \n"
" {\"name\": \"MyFloat\", \"type\": \"float\"}, \n"
" {\"name\": \"MyFloat2\", \"type\": \"vector2\"}, \n"
" {\"name\": \"MyFloat3\", \"type\": \"vector3\"} \n"
" ], \n"
" \"groupC\": [ \n"
" {\"id\": \"MyFloat4\", \"type\": \"vector4\"}, \n"
" {\"id\": \"MyColor\", \"type\": \"color\"}, \n"
" {\"id\": \"MyImage\", \"type\": \"image\"} \n"
" {\"name\": \"MyFloat4\", \"type\": \"vector4\"}, \n"
" {\"name\": \"MyColor\", \"type\": \"color\"}, \n"
" {\"name\": \"MyImage\", \"type\": \"image\"} \n"
" ] \n"
" } \n"
" } \n"
@@ -271,7 +271,7 @@ namespace UnitTest
"properties": {
"general": [
{
"id": "testColor",
"name": "testColor",
"type": "color"
}
]
@@ -381,7 +381,7 @@ namespace UnitTest
"properties": {
"general": [
{
"id": "testColor",
"name": "testColor",
"type": "color"
}
]
@@ -427,7 +427,7 @@ namespace UnitTest
"properties": {
"general": [
{
"id": "testColor",
"name": "testColor",
"type": "color"
}
]
@@ -510,7 +510,7 @@ namespace UnitTest
sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{ TestShaderFilename });
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_nameId = "MyBool";
propertySource.m_name = "MyBool";
propertySource.m_displayName = "My Bool";
propertySource.m_description = "This is a bool";
propertySource.m_dataType = MaterialPropertyDataType::Bool;
@@ -536,7 +536,7 @@ namespace UnitTest
sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{ TestShaderFilename });
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_nameId = "MyFloat";
propertySource.m_name = "MyFloat";
propertySource.m_displayName = "My Float";
propertySource.m_description = "This is a float";
propertySource.m_min = 0.0f;
@@ -566,7 +566,7 @@ namespace UnitTest
sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{ TestShaderFilename });
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_nameId = "MyImage";
propertySource.m_name = "MyImage";
propertySource.m_displayName = "My Image";
propertySource.m_description = "This is an image";
propertySource.m_dataType = MaterialPropertyDataType::Image;
@@ -591,7 +591,7 @@ namespace UnitTest
sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{TestShaderFilename});
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_nameId = "MyInt";
propertySource.m_name = "MyInt";
propertySource.m_displayName = "My Integer";
propertySource.m_dataType = MaterialPropertyDataType::Int;
propertySource.m_outputConnections.push_back(MaterialTypeSourceData::PropertyConnection{MaterialPropertyOutputType::ShaderOption, AZStd::string("o_foo"), 0});
@@ -614,7 +614,7 @@ namespace UnitTest
sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{TestShaderFilename});
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_nameId = "MyInt";
propertySource.m_name = "MyInt";
propertySource.m_dataType = MaterialPropertyDataType::Int;
propertySource.m_outputConnections.push_back(MaterialTypeSourceData::PropertyConnection{MaterialPropertyOutputType::ShaderOption, AZStd::string("DoesNotExist"), 0});
sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource);
@@ -633,7 +633,7 @@ namespace UnitTest
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_dataType = MaterialPropertyDataType::Int;
propertySource.m_nameId = "a";
propertySource.m_name = "a";
sourceData.m_propertyLayout.m_properties["not a valid name because it has spaces"].push_back(propertySource);
// Expected errors:
@@ -654,7 +654,7 @@ namespace UnitTest
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_dataType = MaterialPropertyDataType::Int;
propertySource.m_nameId = "not a valid name because it has spaces";
propertySource.m_name = "not a valid name because it has spaces";
sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource);
// Expected errors:
@@ -674,7 +674,7 @@ namespace UnitTest
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_dataType = MaterialPropertyDataType::Int;
propertySource.m_nameId = "a";
propertySource.m_name = "a";
sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource);
sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource);
@@ -738,7 +738,7 @@ namespace UnitTest
sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{ "shaderC.shader" });
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_nameId = "MyInt";
propertySource.m_name = "MyInt";
propertySource.m_displayName = "Integer";
propertySource.m_description = "Integer property that is connected to multiple shader settings";
propertySource.m_dataType = MaterialPropertyDataType::Int;
@@ -797,7 +797,7 @@ namespace UnitTest
MaterialTypeSourceData sourceData;
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_nameId = "NonAliasFloat";
propertySource.m_name = "NonAliasFloat";
propertySource.m_displayName = "Non-Alias Float";
propertySource.m_description = "This float is processed by a functor, not with a direct alias";
propertySource.m_dataType = MaterialPropertyDataType::Float;
@@ -842,13 +842,13 @@ namespace UnitTest
sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{TestShaderFilename});
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_nameId = "EnableSpecialPassA";
propertySource.m_name = "EnableSpecialPassA";
propertySource.m_displayName = "Enable Special Pass";
propertySource.m_description = "This is a bool to enable an extra shader/pass";
propertySource.m_dataType = MaterialPropertyDataType::Bool;
// Note that we don't fill propertySource.m_outputConnections because this is not a direct-connected property
sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource);
propertySource.m_nameId = "EnableSpecialPassB";
propertySource.m_name = "EnableSpecialPassB";
sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource);
sourceData.m_materialFunctorSourceData.push_back(
@@ -902,7 +902,7 @@ namespace UnitTest
sourceData.m_shaderCollection.push_back(MaterialTypeSourceData::ShaderVariantReferenceData{TestShaderFilename});
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_nameId = "MyProperty";
propertySource.m_name = "MyProperty";
propertySource.m_dataType = MaterialPropertyDataType::Bool;
// Note that we don't fill propertySource.m_outputConnections because this is not a direct-connected property
sourceData.m_propertyLayout.m_properties["general"].push_back(propertySource);
@@ -938,7 +938,7 @@ namespace UnitTest
auto addProperty = [&sourceData](MaterialPropertyDataType dateType, const char* propertyName, const char* srgConstantName, const AZ::RPI::MaterialPropertyValue& value)
{
MaterialTypeSourceData::PropertyDefinition propertySource;
propertySource.m_nameId = propertyName;
propertySource.m_name = propertyName;
propertySource.m_dataType = dateType;
propertySource.m_outputConnections.push_back(MaterialTypeSourceData::PropertyConnection{ MaterialPropertyOutputType::ShaderInput, AZStd::string(srgConstantName) });
propertySource.m_value = value;
@@ -975,6 +975,152 @@ namespace UnitTest
// Note that serialization of individual fields within material properties is thoroughly tested in
// MaterialPropertySerializerTests, so the sample property data used here is cursory.
const AZStd::string inputJson = R"(
{
"description": "This is a general description about the material",
"propertyLayout": {
"version": 2,
"groups": [
{
"name": "groupA",
"displayName": "Property Group A",
"description": "Description of property group A"
},
{
"name": "groupB",
"displayName": "Property Group B",
"description": "Description of property group B"
}
],
"properties": {
"groupA": [
{
"name": "foo",
"type": "Bool",
"defaultValue": true
},
{
"name": "bar",
"type": "Image",
"defaultValue": "Default.png",
"visibility": "Hidden"
}
],
"groupB": [
{
"name": "foo",
"type": "Float",
"defaultValue": 0.5
},
{
"name": "bar",
"type": "Color",
"defaultValue": [0.5, 0.5, 0.5],
"visibility": "Disabled"
}
]
}
},
"shaders": [
{
"file": "ForwardPass.shader",
"tag": "ForwardPass",
"options": {
"o_optionA": "False",
"o_optionB": "True"
}
},
{
"file": "DepthPass.shader",
"options": {
"o_optionC": "1",
"o_optionD": "2"
}
}
],
"functors": [
{
"type": "EnableShader",
"args": {
"enablePassProperty": "groupA.foo",
"shaderIndex": 1
}
},
{
"type": "Splat3",
"args": {
"floatPropertyInput": "groupB.foo",
"float3ShaderSettingOutput": "m_someFloat3"
}
}
]
}
)";
MaterialTypeSourceData material;
JsonTestResult loadResult = LoadTestDataFromJson(material, inputJson);
EXPECT_EQ(material.m_description, "This is a general description about the material");
EXPECT_EQ(material.m_propertyLayout.m_version, 2);
EXPECT_EQ(material.m_propertyLayout.m_groups.size(), 2);
EXPECT_TRUE(material.FindGroup("groupA") != nullptr);
EXPECT_TRUE(material.FindGroup("groupB") != nullptr);
EXPECT_EQ(material.FindGroup("groupA")->m_displayName, "Property Group A");
EXPECT_EQ(material.FindGroup("groupB")->m_displayName, "Property Group B");
EXPECT_EQ(material.FindGroup("groupA")->m_description, "Description of property group A");
EXPECT_EQ(material.FindGroup("groupB")->m_description, "Description of property group B");
EXPECT_EQ(material.m_propertyLayout.m_properties.size(), 2);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"].size(), 2);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"].size(), 2);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_name, "foo");
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_name, "bar");
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_name, "foo");
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][1].m_name, "bar");
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_dataType, MaterialPropertyDataType::Bool);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_dataType, MaterialPropertyDataType::Image);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_dataType, MaterialPropertyDataType::Float);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][1].m_dataType, MaterialPropertyDataType::Color);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_visibility, MaterialPropertyVisibility::Enabled);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_visibility, MaterialPropertyVisibility::Hidden);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_visibility, MaterialPropertyVisibility::Enabled);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][1].m_visibility, MaterialPropertyVisibility::Disabled);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_value, true);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_value, AZStd::string{"Default.png"});
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_value, 0.5f);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][1].m_value, AZ::Color(0.5f, 0.5f, 0.5f, 1.0f));
EXPECT_EQ(material.m_shaderCollection.size(), 2);
EXPECT_EQ(material.m_shaderCollection[0].m_shaderFilePath, "ForwardPass.shader");
EXPECT_EQ(material.m_shaderCollection[1].m_shaderFilePath, "DepthPass.shader");
EXPECT_EQ(material.m_shaderCollection[0].m_shaderOptionValues.size(), 2);
EXPECT_EQ(material.m_shaderCollection[1].m_shaderOptionValues.size(), 2);
EXPECT_EQ(material.m_shaderCollection[0].m_shaderOptionValues[Name{"o_optionA"}], Name{"False"});
EXPECT_EQ(material.m_shaderCollection[0].m_shaderOptionValues[Name{"o_optionB"}], Name{"True"});
EXPECT_EQ(material.m_shaderCollection[1].m_shaderOptionValues[Name{"o_optionC"}], Name{"1"});
EXPECT_EQ(material.m_shaderCollection[1].m_shaderOptionValues[Name{"o_optionD"}], Name{"2"});
EXPECT_EQ(material.m_shaderCollection[0].m_shaderTag, Name{"ForwardPass"});
EXPECT_EQ(material.m_materialFunctorSourceData.size(), 2);
EXPECT_TRUE(azrtti_cast<const EnableShaderFunctorSourceData*>(material.m_materialFunctorSourceData[0]->GetActualSourceData().get()));
EXPECT_EQ(azrtti_cast<const EnableShaderFunctorSourceData*>(material.m_materialFunctorSourceData[0]->GetActualSourceData().get())->m_enablePassPropertyId, "groupA.foo");
EXPECT_EQ(azrtti_cast<const EnableShaderFunctorSourceData*>(material.m_materialFunctorSourceData[0]->GetActualSourceData().get())->m_shaderIndex, 1);
EXPECT_TRUE(azrtti_cast<const Splat3FunctorSourceData*>(material.m_materialFunctorSourceData[1]->GetActualSourceData().get()));
EXPECT_EQ(azrtti_cast<const Splat3FunctorSourceData*>(material.m_materialFunctorSourceData[1]->GetActualSourceData().get())->m_floatPropertyInputId, "groupB.foo");
EXPECT_EQ(azrtti_cast<const Splat3FunctorSourceData*>(material.m_materialFunctorSourceData[1]->GetActualSourceData().get())->m_float3ShaderSettingOutputId, "m_someFloat3");
AZStd::string outputJson;
JsonTestResult storeResult = StoreTestDataToJson(material, outputJson);
ExpectSimilarJson(inputJson, outputJson);
}
TEST_F(MaterialTypeSourceDataTests, LoadAllFieldsUsingOldFormat)
{
// The content of this test was copied from LoadAndStoreJson_AllFields to prove backward compatibility.
// (The "store" part of the test was not included because the saved data will be the new format).
const AZStd::string inputJson = R"(
{
"description": "This is a general description about the material",
@@ -1075,10 +1221,10 @@ namespace UnitTest
EXPECT_EQ(material.m_propertyLayout.m_properties.size(), 2);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"].size(), 2);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"].size(), 2);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_nameId, "foo");
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_nameId, "bar");
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_nameId, "foo");
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][1].m_nameId, "bar");
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_name, "foo");
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_name, "bar");
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_name, "foo");
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][1].m_name, "bar");
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][0].m_dataType, MaterialPropertyDataType::Bool);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupA"][1].m_dataType, MaterialPropertyDataType::Image);
EXPECT_EQ(material.m_propertyLayout.m_properties["groupB"][0].m_dataType, MaterialPropertyDataType::Float);
@@ -1110,10 +1256,6 @@ namespace UnitTest
EXPECT_TRUE(azrtti_cast<const Splat3FunctorSourceData*>(material.m_materialFunctorSourceData[1]->GetActualSourceData().get()));
EXPECT_EQ(azrtti_cast<const Splat3FunctorSourceData*>(material.m_materialFunctorSourceData[1]->GetActualSourceData().get())->m_floatPropertyInputId, "groupB.foo");
EXPECT_EQ(azrtti_cast<const Splat3FunctorSourceData*>(material.m_materialFunctorSourceData[1]->GetActualSourceData().get())->m_float3ShaderSettingOutputId, "m_someFloat3");
AZStd::string outputJson;
JsonTestResult storeResult = StoreTestDataToJson(material, outputJson);
ExpectSimilarJson(inputJson, outputJson);
}
TEST_F(MaterialTypeSourceDataTests, CreateMaterialTypeAsset_PropertyImagePath)
@@ -1127,7 +1269,7 @@ namespace UnitTest
"version": 2,
"groups": [
{
"id": "general",
"name": "general",
"displayName": "General",
"description": ""
}
@@ -1135,12 +1277,12 @@ namespace UnitTest
"properties": {
"general": [
{
"id": "absolute",
"name": "absolute",
"type": "Image",
"defaultValue": "%s"
},
{
"id": "relative",
"name": "relative",
"type": "Image",
"defaultValue": "%s"
}
@@ -18,6 +18,8 @@ set(FILES
Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h
Include/Atom/RPI.Edit/Material/MaterialConverterBus.h
Include/Atom/RPI.Edit/Material/MaterialPropertyId.h
Include/Atom/RPI.Edit/Material/MaterialPropertyConnectionSerializer.h
Include/Atom/RPI.Edit/Material/MaterialPropertyGroupSerializer.h
Include/Atom/RPI.Edit/Material/MaterialPropertySerializer.h
Include/Atom/RPI.Edit/Material/MaterialPropertyValueSerializer.h
Include/Atom/RPI.Edit/Material/MaterialPropertyValueSourceData.h
@@ -36,6 +38,8 @@ set(FILES
Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp
Source/RPI.Edit/Material/MaterialTypeSourceData.cpp
Source/RPI.Edit/Material/MaterialPropertyId.cpp
Source/RPI.Edit/Material/MaterialPropertyGroupSerializer.cpp
Source/RPI.Edit/Material/MaterialPropertyConnectionSerializer.cpp
Source/RPI.Edit/Material/MaterialPropertySerializer.cpp
Source/RPI.Edit/Material/MaterialPropertyValueSerializer.cpp
Source/RPI.Edit/Material/MaterialPropertyValueSourceData.cpp
@@ -4,12 +4,12 @@
"version": 3,
"groups": [
{
"id": "shape",
"name": "shape",
"displayName": "Shape",
"description": "Properties for configuring size, shape, and position of the bricks."
},
{
"id": "appearance",
"name": "appearance",
"displayName": "Appearance",
"description": "Properties for configuring the appearance of the bricks and grout lines."
}
@@ -17,7 +17,7 @@
"properties": {
"shape": [
{
"id": "brickWidth",
"name": "brickWidth",
"displayName": "Brick Width",
"description": "The width of each brick.",
"type": "Float",
@@ -27,11 +27,11 @@
"step": 0.001,
"connection": {
"type": "ShaderInput",
"id": "m_brickWidth"
"name": "m_brickWidth"
}
},
{
"id": "brickHeight",
"name": "brickHeight",
"displayName": "Brick Height",
"description": "The height of each brick.",
"type": "Float",
@@ -41,11 +41,11 @@
"step": 0.001,
"connection": {
"type": "ShaderInput",
"id": "m_brickHeight"
"name": "m_brickHeight"
}
},
{
"id": "brickOffset",
"name": "brickOffset",
"displayName": "Offset",
"description": "The offset of each stack of bricks as a percentage of brick width.",
"type": "Float",
@@ -54,11 +54,11 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_brickOffset"
"name": "m_brickOffset"
}
},
{
"id": "lineWidth",
"name": "lineWidth",
"displayName": "Line Width",
"description": "The width of the grout lines.",
"type": "Float",
@@ -68,11 +68,11 @@
"step": 0.0001,
"connection": {
"type": "ShaderInput",
"id": "m_lineWidth"
"name": "m_lineWidth"
}
},
{
"id": "lineDepth",
"name": "lineDepth",
"displayName": "Line Depth",
"description": "The depth of the grout lines.",
"type": "Float",
@@ -81,34 +81,34 @@
"softMax": 0.02,
"connection": {
"type": "ShaderInput",
"id": "m_lineDepth"
"name": "m_lineDepth"
}
}
],
"appearance": [
{
"id": "noiseTexture",
"name": "noiseTexture",
"type": "Image",
"defaultValue": "TestData/Textures/noise512.png",
"visibility": "Hidden",
"connection": {
"type": "ShaderInput",
"id": "m_noise"
"name": "m_noise"
}
},
{
"id": "brickColor",
"name": "brickColor",
"displayName": "Brick Color",
"description": "The color of the bricks.",
"type": "Color",
"defaultValue": [1.0,1.0,1.0],
"connection": {
"type": "ShaderInput",
"id": "m_brickColor"
"name": "m_brickColor"
}
},
{
"id": "brickColorNoise",
"name": "brickColorNoise",
"displayName": "Brick Color Noise",
"description": "Scale the variation of brick color.",
"type": "Float",
@@ -117,22 +117,22 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_brickNoiseFactor"
"name": "m_brickNoiseFactor"
}
},
{
"id": "lineColor",
"name": "lineColor",
"displayName": "Line Color",
"description": "The color of the grout lines.",
"type": "Color",
"defaultValue": [0.5,0.5,0.5],
"connection": {
"type": "ShaderInput",
"id": "m_lineColor"
"name": "m_lineColor"
}
},
{
"id": "lineColorNoise",
"name": "lineColorNoise",
"displayName": "Line Color Noise",
"description": "Scale the variation of grout line color.",
"type": "Float",
@@ -141,11 +141,11 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_lineNoiseFactor"
"name": "m_lineNoiseFactor"
}
},
{
"id": "brickColorBleed",
"name": "brickColorBleed",
"displayName": "Brick Color Bleed",
"description": "Distance into the grout line that the brick color will continue.",
"type": "Float",
@@ -154,11 +154,11 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_brickColorBleed"
"name": "m_brickColorBleed"
}
},
{
"id": "ao",
"name": "ao",
"displayName": "Ambient Occlusion",
"description": "The strength of baked ambient occlusion in the grout lines.",
"type": "Float",
@@ -167,7 +167,7 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_aoFactor"
"name": "m_aoFactor"
}
}
]
@@ -4,24 +4,24 @@
"version": 3,
"groups": [
{
"id": "settings",
"name": "settings",
"displayName": "Settings"
}
],
"properties": {
"settings": [
{
"id": "color",
"name": "color",
"displayName": "Color",
"type": "Color",
"defaultValue": [ 1.0, 1.0, 1.0 ],
"connection": {
"type": "ShaderInput",
"id": "m_baseColor"
"name": "m_baseColor"
}
},
{
"id": "metallic",
"name": "metallic",
"displayName": "Metallic",
"type": "Float",
"defaultValue": 0.0,
@@ -29,11 +29,11 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_metallic"
"name": "m_metallic"
}
},
{
"id": "roughness",
"name": "roughness",
"displayName": "Roughness",
"type": "Float",
"defaultValue": 1.0,
@@ -41,7 +41,7 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_roughness"
"name": "m_roughness"
}
}
]
@@ -32,10 +32,10 @@ namespace AtomToolsFramework
// AtomToolsDocumentRequestBus::Handler implementation
AZStd::string_view GetAbsolutePath() const override;
AZStd::string_view GetRelativePath() const override;
const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const override;
const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const override;
const AZStd::any& GetPropertyValue(const AZ::Name& propertyId) const override;
const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyId) const override;
bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override;
void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override;
void SetPropertyValue(const AZ::Name& propertyId, const AZStd::any& value) override;
bool Open(AZStd::string_view loadPath) override;
bool Reopen() override;
bool Save() override;
@@ -42,8 +42,8 @@ namespace AtomToolsFramework
AZ_CLASS_ALLOCATOR(DynamicPropertyConfig, AZ::SystemAllocator, 0);
DynamicPropertyType m_dataType = DynamicPropertyType::Invalid;
AZ::Name m_id;
AZStd::string m_nameId;
AZ::Name m_id; //!< The full property ID, which will normally be "groupName.propertyName"
AZStd::string m_name;
AZStd::string m_displayName;
AZStd::string m_groupName;
AZStd::string m_description;
@@ -41,27 +41,27 @@ namespace AtomToolsFramework
//! Add a group consisting of a collapsable header and widget
virtual void AddGroup(
const AZStd::string& groupNameId,
const AZStd::string& groupName,
const AZStd::string& groupDisplayName,
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;
virtual void SetGroupVisible(const AZStd::string& groupName, bool visible) = 0;
//! Returns whether a specific property is visible.
//! Note this follows the same rules as QWidget::isVisible(), meaning a group could be not visible due to the widget's parents being not visible.
virtual bool IsGroupVisible(const AZStd::string& groupNameId) const = 0;
virtual bool IsGroupVisible(const AZStd::string& groupName) const = 0;
//! Returns whether a specific property is explicitly hidden.
//! Note this follows the same rules as QWidget::isHidden(), meaning a group that is hidden will not become visible automatically when the parent becomes visible.
virtual bool IsGroupHidden(const AZStd::string& groupNameId) const = 0;
virtual bool IsGroupHidden(const AZStd::string& groupName) const = 0;
//! Calls Refresh for a specific InspectorGroupWidget, allowing for non-destructive UI changes
virtual void RefreshGroup(const AZStd::string& groupNameId) = 0;
virtual void RefreshGroup(const AZStd::string& groupName) = 0;
//! Calls Rebuild for a specific InspectorGroupWidget, allowing for destructive UI changes
virtual void RebuildGroup(const AZStd::string& groupNameId) = 0;
virtual void RebuildGroup(const AZStd::string& groupName) = 0;
//! Calls Refresh for all InspectorGroupWidget, allowing for non-destructive UI changes
virtual void RefreshAll() = 0;
@@ -70,13 +70,13 @@ namespace AtomToolsFramework
virtual void RebuildAll() = 0;
//! Expands a specific group
virtual void ExpandGroup(const AZStd::string& groupNameId) = 0;
virtual void ExpandGroup(const AZStd::string& groupName) = 0;
//! Collapses a specific group
virtual void CollapseGroup(const AZStd::string& groupNameId) = 0;
virtual void CollapseGroup(const AZStd::string& groupName) = 0;
//! Checks the expansion state of a specific group
virtual bool IsGroupExpanded(const AZStd::string& groupNameId) const = 0;
virtual bool IsGroupExpanded(const AZStd::string& groupName) const = 0;
//! Expands all groups and headers
virtual void ExpandAll() = 0;
@@ -52,33 +52,33 @@ namespace AtomToolsFramework
void AddGroupsEnd() override;
void AddGroup(
const AZStd::string& groupNameId,
const AZStd::string& groupName,
const AZStd::string& groupDisplayName,
const AZStd::string& groupDescription,
QWidget* groupWidget) override;
void SetGroupVisible(const AZStd::string& groupNameId, bool visible) override;
bool IsGroupVisible(const AZStd::string& groupNameId) const override;
bool IsGroupHidden(const AZStd::string& groupNameId) const override;
void SetGroupVisible(const AZStd::string& groupName, bool visible) override;
bool IsGroupVisible(const AZStd::string& groupName) const override;
bool IsGroupHidden(const AZStd::string& groupName) const override;
void RefreshGroup(const AZStd::string& groupNameId) override;
void RebuildGroup(const AZStd::string& groupNameId) override;
void RefreshGroup(const AZStd::string& groupName) override;
void RebuildGroup(const AZStd::string& groupName) override;
void RefreshAll() override;
void RebuildAll() override;
void ExpandGroup(const AZStd::string& groupNameId) override;
void CollapseGroup(const AZStd::string& groupNameId) override;
bool IsGroupExpanded(const AZStd::string& groupNameId) const override;
void ExpandGroup(const AZStd::string& groupName) override;
void CollapseGroup(const AZStd::string& groupName) override;
bool IsGroupExpanded(const AZStd::string& groupName) const override;
void ExpandAll() override;
void CollapseAll() override;
protected:
virtual bool ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const;
virtual void OnGroupExpanded(const AZStd::string& groupNameId);
virtual void OnGroupCollapsed(const AZStd::string& groupNameId);
virtual void OnHeaderClicked(const AZStd::string& groupNameId, QMouseEvent* event);
virtual bool ShouldGroupAutoExpanded(const AZStd::string& groupName) const;
virtual void OnGroupExpanded(const AZStd::string& groupName);
virtual void OnGroupCollapsed(const AZStd::string& groupName);
virtual void OnHeaderClicked(const AZStd::string& groupName, QMouseEvent* event);
private:
QScopedPointer<Ui::InspectorWidget> m_ui;
@@ -38,16 +38,16 @@ namespace AtomToolsFramework
return m_relativePath;
}
const AZStd::any& AtomToolsDocument::GetPropertyValue([[maybe_unused]] const AZ::Name& propertyFullName) const
const AZStd::any& AtomToolsDocument::GetPropertyValue([[maybe_unused]] const AZ::Name& propertyId) const
{
AZ_UNUSED(propertyFullName);
AZ_UNUSED(propertyId);
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return m_invalidValue;
}
const AtomToolsFramework::DynamicProperty& AtomToolsDocument::GetProperty([[maybe_unused]] const AZ::Name& propertyFullName) const
const AtomToolsFramework::DynamicProperty& AtomToolsDocument::GetProperty([[maybe_unused]] const AZ::Name& propertyId) const
{
AZ_UNUSED(propertyFullName);
AZ_UNUSED(propertyId);
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return m_invalidProperty;
}
@@ -59,9 +59,9 @@ namespace AtomToolsFramework
return false;
}
void AtomToolsDocument::SetPropertyValue([[maybe_unused]] const AZ::Name& propertyFullName, [[maybe_unused]] const AZStd::any& value)
void AtomToolsDocument::SetPropertyValue([[maybe_unused]] const AZ::Name& propertyId, [[maybe_unused]] const AZStd::any& value)
{
AZ_UNUSED(propertyFullName);
AZ_UNUSED(propertyId);
AZ_UNUSED(value);
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
}
@@ -192,7 +192,7 @@ namespace AtomToolsFramework
AZStd::string DynamicProperty::GetDisplayName() const
{
return !m_config.m_displayName.empty() ? m_config.m_displayName : m_config.m_nameId;
return !m_config.m_displayName.empty() ? m_config.m_displayName : m_config.m_name;
}
AZStd::string DynamicProperty::GetGroupName() const
@@ -72,7 +72,7 @@ namespace AtomToolsFramework
}
void InspectorWidget::AddGroup(
const AZStd::string& groupNameId,
const AZStd::string& groupName,
const AZStd::string& groupDisplayName,
const AZStd::string& groupDescription,
QWidget* groupWidget)
@@ -82,31 +82,31 @@ namespace AtomToolsFramework
groupHeader->setToolTip(groupDescription.c_str());
m_ui->m_groupContentsLayout->addWidget(groupHeader);
groupWidget->setObjectName(groupNameId.c_str());
groupWidget->setObjectName(groupName.c_str());
groupWidget->setParent(m_ui->m_groupContents);
m_ui->m_groupContentsLayout->addWidget(groupWidget);
m_groups[groupNameId] = {groupHeader, groupWidget};
m_groups[groupName] = {groupHeader, groupWidget};
connect(groupHeader, &InspectorGroupHeaderWidget::clicked, this, [this, groupNameId](QMouseEvent* event) {
OnHeaderClicked(groupNameId, event);
connect(groupHeader, &InspectorGroupHeaderWidget::clicked, this, [this, groupName](QMouseEvent* event) {
OnHeaderClicked(groupName, event);
});
connect(groupHeader, &InspectorGroupHeaderWidget::expanded, this, [this, groupNameId]() { OnGroupExpanded(groupNameId); });
connect(groupHeader, &InspectorGroupHeaderWidget::collapsed, this, [this, groupNameId]() { OnGroupCollapsed(groupNameId); });
connect(groupHeader, &InspectorGroupHeaderWidget::expanded, this, [this, groupName]() { OnGroupExpanded(groupName); });
connect(groupHeader, &InspectorGroupHeaderWidget::collapsed, this, [this, groupName]() { OnGroupCollapsed(groupName); });
if (ShouldGroupAutoExpanded(groupNameId))
if (ShouldGroupAutoExpanded(groupName))
{
ExpandGroup(groupNameId);
ExpandGroup(groupName);
}
else
{
CollapseGroup(groupNameId);
CollapseGroup(groupName);
}
}
void InspectorWidget::SetGroupVisible(const AZStd::string& groupNameId, bool visible)
void InspectorWidget::SetGroupVisible(const AZStd::string& groupName, bool visible)
{
auto groupItr = m_groups.find(groupNameId);
auto groupItr = m_groups.find(groupName);
if (groupItr != m_groups.end())
{
groupItr->second.m_header->setVisible(visible);
@@ -114,29 +114,29 @@ namespace AtomToolsFramework
}
}
bool InspectorWidget::IsGroupVisible(const AZStd::string& groupNameId) const
bool InspectorWidget::IsGroupVisible(const AZStd::string& groupName) const
{
auto groupItr = m_groups.find(groupNameId);
auto groupItr = m_groups.find(groupName);
return groupItr != m_groups.end() ? groupItr->second.m_header->isVisible() : false;
}
bool InspectorWidget::IsGroupHidden(const AZStd::string& groupNameId) const
bool InspectorWidget::IsGroupHidden(const AZStd::string& groupName) const
{
auto groupItr = m_groups.find(groupNameId);
auto groupItr = m_groups.find(groupName);
return groupItr != m_groups.end() ? groupItr->second.m_header->isHidden() : false;
}
void InspectorWidget::RefreshGroup(const AZStd::string& groupNameId)
void InspectorWidget::RefreshGroup(const AZStd::string& groupName)
{
for (auto groupWidget : m_ui->m_groupContents->findChildren<InspectorGroupWidget*>(groupNameId.c_str()))
for (auto groupWidget : m_ui->m_groupContents->findChildren<InspectorGroupWidget*>(groupName.c_str()))
{
groupWidget->Refresh();
}
}
void InspectorWidget::RebuildGroup(const AZStd::string& groupNameId)
void InspectorWidget::RebuildGroup(const AZStd::string& groupName)
{
for (auto groupWidget : m_ui->m_groupContents->findChildren<InspectorGroupWidget*>(groupNameId.c_str()))
for (auto groupWidget : m_ui->m_groupContents->findChildren<InspectorGroupWidget*>(groupName.c_str()))
{
groupWidget->Rebuild();
}
@@ -158,9 +158,9 @@ namespace AtomToolsFramework
}
}
void InspectorWidget::ExpandGroup(const AZStd::string& groupNameId)
void InspectorWidget::ExpandGroup(const AZStd::string& groupName)
{
auto groupItr = m_groups.find(groupNameId);
auto groupItr = m_groups.find(groupName);
if (groupItr != m_groups.end())
{
groupItr->second.m_header->SetExpanded(true);
@@ -168,9 +168,9 @@ namespace AtomToolsFramework
}
}
void InspectorWidget::CollapseGroup(const AZStd::string& groupNameId)
void InspectorWidget::CollapseGroup(const AZStd::string& groupName)
{
auto groupItr = m_groups.find(groupNameId);
auto groupItr = m_groups.find(groupName);
if (groupItr != m_groups.end())
{
groupItr->second.m_header->SetExpanded(false);
@@ -178,9 +178,9 @@ namespace AtomToolsFramework
}
}
bool InspectorWidget::IsGroupExpanded(const AZStd::string& groupNameId) const
bool InspectorWidget::IsGroupExpanded(const AZStd::string& groupName) const
{
auto groupItr = m_groups.find(groupNameId);
auto groupItr = m_groups.find(groupName);
return groupItr != m_groups.end() ? groupItr->second.m_header->IsExpanded() : false;
}
@@ -202,33 +202,33 @@ namespace AtomToolsFramework
}
}
bool InspectorWidget::ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const
bool InspectorWidget::ShouldGroupAutoExpanded(const AZStd::string& groupName) const
{
AZ_UNUSED(groupNameId);
AZ_UNUSED(groupName);
return true;
}
void InspectorWidget::OnGroupExpanded(const AZStd::string& groupNameId)
void InspectorWidget::OnGroupExpanded(const AZStd::string& groupName)
{
AZ_UNUSED(groupNameId);
AZ_UNUSED(groupName);
}
void InspectorWidget::OnGroupCollapsed(const AZStd::string& groupNameId)
void InspectorWidget::OnGroupCollapsed(const AZStd::string& groupName)
{
AZ_UNUSED(groupNameId);
AZ_UNUSED(groupName);
}
void InspectorWidget::OnHeaderClicked(const AZStd::string& groupNameId, QMouseEvent* event)
void InspectorWidget::OnHeaderClicked(const AZStd::string& groupName, QMouseEvent* event)
{
if (event->button() == Qt::MouseButton::LeftButton)
{
if (!IsGroupExpanded(groupNameId))
if (!IsGroupExpanded(groupName))
{
ExpandGroup(groupNameId);
ExpandGroup(groupName);
}
else
{
CollapseGroup(groupNameId);
CollapseGroup(groupName);
}
return;
}
@@ -236,8 +236,8 @@ namespace AtomToolsFramework
if (event->button() == Qt::MouseButton::RightButton)
{
QMenu menu;
menu.addAction("Expand", [this, groupNameId]() { ExpandGroup(groupNameId); })->setEnabled(!IsGroupExpanded(groupNameId));
menu.addAction("Collapse", [this, groupNameId]() { CollapseGroup(groupNameId); })->setEnabled(IsGroupExpanded(groupNameId));
menu.addAction("Expand", [this, groupName]() { ExpandGroup(groupName); })->setEnabled(!IsGroupExpanded(groupName));
menu.addAction("Collapse", [this, groupName]() { CollapseGroup(groupName); })->setEnabled(IsGroupExpanded(groupName));
menu.addAction("Expand All", [this]() { ExpandAll(); });
menu.addAction("Collapse All", [this]() { CollapseAll(); });
menu.exec(event->globalPos());
@@ -74,7 +74,7 @@ namespace AtomToolsFramework
void ConvertToPropertyConfig(AtomToolsFramework::DynamicPropertyConfig& propertyConfig, const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition)
{
propertyConfig.m_dataType = ConvertToEditableType(propertyDefinition.m_dataType);
propertyConfig.m_nameId = propertyDefinition.m_nameId;
propertyConfig.m_name = propertyDefinition.m_name;
propertyConfig.m_displayName = propertyDefinition.m_displayName;
propertyConfig.m_description = propertyDefinition.m_description;
propertyConfig.m_defaultValue = ConvertToEditableType(propertyDefinition.m_value);
@@ -59,7 +59,7 @@ namespace MaterialEditor
return &m_materialTypeSourceData;
}
const AZStd::any& MaterialDocument::GetPropertyValue(const AZ::Name& propertyFullName) const
const AZStd::any& MaterialDocument::GetPropertyValue(const AZ::Name& propertyId) const
{
using namespace AZ;
using namespace RPI;
@@ -70,10 +70,10 @@ namespace MaterialEditor
return m_invalidValue;
}
const auto it = m_properties.find(propertyFullName);
const auto it = m_properties.find(propertyId);
if (it == m_properties.end())
{
AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyFullName.GetCStr());
AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyId.GetCStr());
return m_invalidValue;
}
@@ -81,7 +81,7 @@ namespace MaterialEditor
return property.GetValue();
}
const AtomToolsFramework::DynamicProperty& MaterialDocument::GetProperty(const AZ::Name& propertyFullName) const
const AtomToolsFramework::DynamicProperty& MaterialDocument::GetProperty(const AZ::Name& propertyId) const
{
if (!IsOpen())
{
@@ -89,10 +89,10 @@ namespace MaterialEditor
return m_invalidProperty;
}
const auto it = m_properties.find(propertyFullName);
const auto it = m_properties.find(propertyId);
if (it == m_properties.end())
{
AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyFullName.GetCStr());
AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyId.GetCStr());
return m_invalidProperty;
}
@@ -118,7 +118,7 @@ namespace MaterialEditor
return it->second;
}
void MaterialDocument::SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value)
void MaterialDocument::SetPropertyValue(const AZ::Name& propertyId, const AZStd::any& value)
{
using namespace AZ;
using namespace RPI;
@@ -129,10 +129,10 @@ namespace MaterialEditor
return;
}
const auto it = m_properties.find(propertyFullName);
const auto it = m_properties.find(propertyId);
if (it == m_properties.end())
{
AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyFullName.GetCStr());
AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyId.GetCStr());
return;
}
@@ -143,8 +143,7 @@ namespace MaterialEditor
AtomToolsFramework::DynamicProperty& property = it->second;
property.SetValue(AtomToolsFramework::ConvertToEditableType(propertyValue));
const AZ::RPI::MaterialPropertyId propertyId = AZ::RPI::MaterialPropertyId::Parse(propertyFullName.GetStringView());
const auto propertyIndex = m_materialInstance->FindPropertyIndex(propertyFullName);
const auto propertyIndex = m_materialInstance->FindPropertyIndex(propertyId);
if (!propertyIndex.IsNull())
{
if (m_materialInstance->SetPropertyValue(propertyIndex, propertyValue))
@@ -593,8 +592,9 @@ namespace MaterialEditor
bool result = true;
// populate sourceData with properties that meet the filter
m_materialTypeSourceData.EnumerateProperties([this, &sourceData, &propertyFilter, &result](const AZStd::string& groupNameId, const AZStd::string& propertyNameId, const auto& propertyDefinition) {
const MaterialPropertyId propertyId(groupNameId, propertyNameId);
m_materialTypeSourceData.EnumerateProperties([this, &sourceData, &propertyFilter, &result](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition) {
const MaterialPropertyId propertyId(groupName, propertyName);
const auto it = m_properties.find(propertyId.GetFullName());
if (it != m_properties.end() && propertyFilter(it->second))
@@ -609,7 +609,7 @@ namespace MaterialEditor
return false;
}
sourceData.m_properties[groupNameId][propertyNameId].m_value = propertyValue;
sourceData.m_properties[groupName][propertyName].m_value = propertyValue;
}
}
return true;
@@ -770,11 +770,11 @@ namespace MaterialEditor
// Populate the property map from a combination of source data and assets
// Assets must still be used for now because they contain the final accumulated value after all other materials
// in the hierarchy are applied
m_materialTypeSourceData.EnumerateProperties([this, &parentPropertyValues](const AZStd::string& groupNameId, const AZStd::string& propertyNameId, const auto& propertyDefinition) {
m_materialTypeSourceData.EnumerateProperties([this, &parentPropertyValues](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition) {
AtomToolsFramework::DynamicPropertyConfig propertyConfig;
// Assign id before conversion so it can be used in dynamic description
propertyConfig.m_id = MaterialPropertyId(groupNameId, propertyNameId).GetCStr();
propertyConfig.m_id = MaterialPropertyId(groupName, propertyName).GetCStr();
const auto& propertyIndex = m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyConfig.m_id);
const bool propertyIndexInBounds = propertyIndex.IsValid() && propertyIndex.GetIndex() < m_materialAsset->GetPropertyValues().size();
@@ -786,8 +786,8 @@ namespace MaterialEditor
propertyConfig.m_showThumbnail = true;
propertyConfig.m_originalValue = AtomToolsFramework::ConvertToEditableType(m_materialAsset->GetPropertyValues()[propertyIndex.GetIndex()]);
propertyConfig.m_parentValue = AtomToolsFramework::ConvertToEditableType(parentPropertyValues[propertyIndex.GetIndex()]);
auto groupDefinition = m_materialTypeSourceData.FindGroup(groupNameId);
propertyConfig.m_groupName = groupDefinition ? groupDefinition->m_displayName : groupNameId;
auto groupDefinition = m_materialTypeSourceData.FindGroup(groupName);
propertyConfig.m_groupName = groupDefinition ? groupDefinition->m_displayName : groupName;
m_properties[propertyConfig.m_id] = AtomToolsFramework::DynamicProperty(propertyConfig);
}
return true;
@@ -796,7 +796,7 @@ namespace MaterialEditor
// Populate the property group visibility map
for (MaterialTypeSourceData::GroupDefinition& group : m_materialTypeSourceData.GetGroupDefinitionsInDisplayOrder())
{
m_propertyGroupVisibility[AZ::Name{group.m_nameId}] = true;
m_propertyGroupVisibility[AZ::Name{group.m_name}] = true;
}
// Adding properties for material type and parent as part of making dynamic
@@ -808,7 +808,7 @@ namespace MaterialEditor
AtomToolsFramework::DynamicPropertyConfig propertyConfig;
propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::Asset;
propertyConfig.m_id = "overview.materialType";
propertyConfig.m_nameId = "materialType";
propertyConfig.m_name = "materialType";
propertyConfig.m_displayName = "Material Type";
propertyConfig.m_groupName = "Overview";
propertyConfig.m_description = "The material type defines the layout, properties, default values, shader connections, and other "
@@ -823,7 +823,7 @@ namespace MaterialEditor
propertyConfig = {};
propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::Asset;
propertyConfig.m_id = "overview.parentMaterial";
propertyConfig.m_nameId = "parentMaterial";
propertyConfig.m_name = "parentMaterial";
propertyConfig.m_displayName = "Parent Material";
propertyConfig.m_groupName = "Overview";
propertyConfig.m_description =
@@ -846,7 +846,7 @@ namespace MaterialEditor
propertyConfig = {};
propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::String;
propertyConfig.m_id = MaterialPropertyId(UvGroupName, shaderInput).GetCStr();
propertyConfig.m_nameId = shaderInput;
propertyConfig.m_name = shaderInput;
propertyConfig.m_displayName = shaderInput;
propertyConfig.m_groupName = "UV Sets";
propertyConfig.m_description = shaderInput;
@@ -43,10 +43,10 @@ namespace MaterialEditor
////////////////////////////////////////////////////////////////////////
// AtomToolsFramework::AtomToolsDocument
////////////////////////////////////////////////////////////////////////
const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const override;
const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyFullName) const override;
const AZStd::any& GetPropertyValue(const AZ::Name& propertyId) const override;
const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyId) const override;
bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override;
void SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value) override;
void SetPropertyValue(const AZ::Name& propertyId, const AZStd::any& value) override;
bool Open(AZStd::string_view loadPath) override;
bool Reopen() override;
bool Save() override;
@@ -44,20 +44,20 @@ namespace MaterialEditor
AtomToolsFramework::InspectorWidget::Reset();
}
bool MaterialInspector::ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const
bool MaterialInspector::ShouldGroupAutoExpanded(const AZStd::string& groupName) const
{
auto stateItr = m_windowSettings->m_inspectorCollapsedGroups.find(GetGroupSaveStateKey(groupNameId));
auto stateItr = m_windowSettings->m_inspectorCollapsedGroups.find(GetGroupSaveStateKey(groupName));
return stateItr == m_windowSettings->m_inspectorCollapsedGroups.end();
}
void MaterialInspector::OnGroupExpanded(const AZStd::string& groupNameId)
void MaterialInspector::OnGroupExpanded(const AZStd::string& groupName)
{
m_windowSettings->m_inspectorCollapsedGroups.erase(GetGroupSaveStateKey(groupNameId));
m_windowSettings->m_inspectorCollapsedGroups.erase(GetGroupSaveStateKey(groupName));
}
void MaterialInspector::OnGroupCollapsed(const AZStd::string& groupNameId)
void MaterialInspector::OnGroupCollapsed(const AZStd::string& groupName)
{
m_windowSettings->m_inspectorCollapsedGroups.insert(GetGroupSaveStateKey(groupNameId));
m_windowSettings->m_inspectorCollapsedGroups.insert(GetGroupSaveStateKey(groupName));
}
void MaterialInspector::OnDocumentOpened(const AZ::Uuid& documentId)
@@ -86,9 +86,9 @@ namespace MaterialEditor
AddGroupsEnd();
}
AZ::Crc32 MaterialInspector::GetGroupSaveStateKey(const AZStd::string& groupNameId) const
AZ::Crc32 MaterialInspector::GetGroupSaveStateKey(const AZStd::string& groupName) const
{
return AZ::Crc32(AZStd::string::format("MaterialInspector::PropertyGroup::%s::%s", m_documentPath.c_str(), groupNameId.c_str()));
return AZ::Crc32(AZStd::string::format("MaterialInspector::PropertyGroup::%s::%s", m_documentPath.c_str(), groupName.c_str()));
}
bool MaterialInspector::CompareInstanceNodeProperties(
@@ -105,10 +105,10 @@ namespace MaterialEditor
MaterialDocumentRequestBus::EventResult(
materialTypeSourceData, m_documentId, &MaterialDocumentRequestBus::Events::GetMaterialTypeSourceData);
const AZStd::string groupNameId = "overview";
const AZStd::string groupName = "overview";
const AZStd::string groupDisplayName = "Overview";
const AZStd::string groupDescription = materialTypeSourceData->m_description;
auto& group = m_groups[groupNameId];
auto& group = m_groups[groupName];
AtomToolsFramework::DynamicProperty property;
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
@@ -122,9 +122,9 @@ namespace MaterialEditor
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
&group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupNameId),
&group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupName),
[this](const auto source, const auto target) { return CompareInstanceNodeProperties(source, target); });
AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget);
AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupWidget);
}
void MaterialInspector::AddUvNamesGroup()
@@ -132,10 +132,10 @@ namespace MaterialEditor
AZ::Data::Asset<AZ::RPI::MaterialAsset> materialAsset;
MaterialDocumentRequestBus::EventResult(materialAsset, m_documentId, &MaterialDocumentRequestBus::Events::GetAsset);
const AZStd::string groupNameId = UvGroupName;
const AZStd::string groupName = UvGroupName;
const AZStd::string groupDisplayName = "UV Sets";
const AZStd::string groupDescription = "UV set names in this material, which can be renamed to match those in the model.";
auto& group = m_groups[groupNameId];
auto& group = m_groups[groupName];
const auto& uvNameMap = materialAsset->GetMaterialTypeAsset()->GetUvNameMap();
group.m_properties.reserve(uvNameMap.size());
@@ -145,7 +145,7 @@ namespace MaterialEditor
AtomToolsFramework::DynamicProperty property;
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty,
AZ::RPI::MaterialPropertyId(groupNameId, uvNamePair.m_shaderInput.ToString()).GetFullName());
AZ::RPI::MaterialPropertyId(groupName, uvNamePair.m_shaderInput.ToString()).GetFullName());
group.m_properties.push_back(property);
property.SetValue(property.GetConfig().m_parentValue);
@@ -153,9 +153,9 @@ namespace MaterialEditor
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
&group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupNameId),
&group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupName),
[this](const auto source, const auto target) { return CompareInstanceNodeProperties(source, target); });
AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget);
AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupWidget);
}
void MaterialInspector::AddPropertiesGroup()
@@ -166,14 +166,14 @@ namespace MaterialEditor
for (const auto& groupDefinition : materialTypeSourceData->GetGroupDefinitionsInDisplayOrder())
{
const AZStd::string& groupNameId = groupDefinition.m_nameId;
const AZStd::string& groupDisplayName = !groupDefinition.m_displayName.empty() ? groupDefinition.m_displayName : groupNameId;
const AZStd::string& groupName = groupDefinition.m_name;
const AZStd::string& groupDisplayName = !groupDefinition.m_displayName.empty() ? groupDefinition.m_displayName : groupName;
const AZStd::string& groupDescription =
!groupDefinition.m_description.empty() ? groupDefinition.m_description : groupDisplayName;
auto& group = m_groups[groupNameId];
auto& group = m_groups[groupName];
const auto& propertyLayout = materialTypeSourceData->m_propertyLayout;
const auto& propertyListItr = propertyLayout.m_properties.find(groupNameId);
const auto& propertyListItr = propertyLayout.m_properties.find(groupName);
if (propertyListItr != propertyLayout.m_properties.end())
{
group.m_properties.reserve(propertyListItr->second.size());
@@ -182,21 +182,21 @@ namespace MaterialEditor
AtomToolsFramework::DynamicProperty property;
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
property, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetProperty,
AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName());
AZ::RPI::MaterialPropertyId(groupName, propertyDefinition.m_name).GetFullName());
group.m_properties.push_back(property);
}
}
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
&group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupNameId),
&group, &group, group.TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupName),
[this](const auto source, const auto target) { return CompareInstanceNodeProperties(source, target); });
AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget);
AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupWidget);
bool isGroupVisible = false;
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(
isGroupVisible, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsPropertyGroupVisible, AZ::Name{groupNameId});
SetGroupVisible(groupNameId, isGroupVisible);
isGroupVisible, m_documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::IsPropertyGroupVisible, AZ::Name{groupName});
SetGroupVisible(groupName, isGroupVisible);
}
}
@@ -37,12 +37,12 @@ namespace MaterialEditor
void Reset() override;
protected:
bool ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const override;
void OnGroupExpanded(const AZStd::string& groupNameId) override;
void OnGroupCollapsed(const AZStd::string& groupNameId) override;
bool ShouldGroupAutoExpanded(const AZStd::string& groupName) const override;
void OnGroupExpanded(const AZStd::string& groupName) override;
void OnGroupCollapsed(const AZStd::string& groupName) override;
private:
AZ::Crc32 GetGroupSaveStateKey(const AZStd::string& groupNameId) const;
AZ::Crc32 GetGroupSaveStateKey(const AZStd::string& groupName) const;
bool CompareInstanceNodeProperties(
const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) const;
@@ -35,26 +35,26 @@ namespace MaterialEditor
void SettingsWidget::AddDocumentSettingsGroup()
{
const AZStd::string groupNameId = "documentSettings";
const AZStd::string groupName = "documentSettings";
const AZStd::string groupDisplayName = "Document Settings";
const AZStd::string groupDescription = "Document Settings";
const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSettingsGroup"));
AddGroup(
groupNameId, groupDisplayName, groupDescription,
groupName, groupDisplayName, groupDescription,
new AtomToolsFramework::InspectorPropertyGroupWidget(
m_documentSettings.get(), nullptr, m_documentSettings->TYPEINFO_Uuid(), this, this, saveStateKey));
}
void SettingsWidget::AddDocumentSystemSettingsGroup()
{
const AZStd::string groupNameId = "documentSystemSettings";
const AZStd::string groupName = "documentSystemSettings";
const AZStd::string groupDisplayName = "Document System Settings";
const AZStd::string groupDescription = "Document System Settings";
const AZ::Crc32 saveStateKey(AZStd::string::format("SettingsWidget::DocumentSystemSettingsGroup"));
AddGroup(
groupNameId, groupDisplayName, groupDescription,
groupName, groupDisplayName, groupDescription,
new AtomToolsFramework::InspectorPropertyGroupWidget(
m_documentSystemSettings.get(), nullptr, m_documentSystemSettings->TYPEINFO_Uuid(), this, this, saveStateKey));
}
@@ -54,19 +54,19 @@ namespace MaterialEditor
void ViewportSettingsInspector::AddGeneralGroup()
{
const AZStd::string groupNameId = "generalSettings";
const AZStd::string groupName = "generalSettings";
const AZStd::string groupDisplayName = "General Settings";
const AZStd::string groupDescription = "General Settings";
AddGroup(
groupNameId, groupDisplayName, groupDescription,
groupName, groupDisplayName, groupDescription,
new AtomToolsFramework::InspectorPropertyGroupWidget(
m_viewportSettings.get(), nullptr, m_viewportSettings->TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupNameId)));
m_viewportSettings.get(), nullptr, m_viewportSettings->TYPEINFO_Uuid(), this, this, GetGroupSaveStateKey(groupName)));
}
void ViewportSettingsInspector::AddModelGroup()
{
const AZStd::string groupNameId = "modelSettings";
const AZStd::string groupName = "modelSettings";
const AZStd::string groupDisplayName = "Model Settings";
const AZStd::string groupDescription = "Model Settings";
@@ -94,12 +94,12 @@ namespace MaterialEditor
if (m_modelPreset)
{
auto inspectorWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
m_modelPreset.get(), nullptr, m_modelPreset.get()->TYPEINFO_Uuid(), this, groupWidget, GetGroupSaveStateKey(groupNameId));
m_modelPreset.get(), nullptr, m_modelPreset.get()->TYPEINFO_Uuid(), this, groupWidget, GetGroupSaveStateKey(groupName));
groupWidget->layout()->addWidget(inspectorWidget);
}
AddGroup(groupNameId, groupDisplayName, groupDescription, groupWidget);
AddGroup(groupName, groupDisplayName, groupDescription, groupWidget);
}
void ViewportSettingsInspector::AddModelPreset()
@@ -153,7 +153,7 @@ namespace MaterialEditor
void ViewportSettingsInspector::AddLightingGroup()
{
const AZStd::string groupNameId = "lightingSettings";
const AZStd::string groupName = "lightingSettings";
const AZStd::string groupDisplayName = "Lighting Settings";
const AZStd::string groupDescription = "Lighting Settings";
@@ -182,12 +182,12 @@ namespace MaterialEditor
{
auto inspectorWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
m_lightingPreset.get(), nullptr, m_lightingPreset.get()->TYPEINFO_Uuid(), this, groupWidget,
GetGroupSaveStateKey(groupNameId));
GetGroupSaveStateKey(groupName));
groupWidget->layout()->addWidget(inspectorWidget);
}
AddGroup(groupNameId, groupDisplayName, groupDescription, groupWidget);
AddGroup(groupName, groupDisplayName, groupDescription, groupWidget);
}
void ViewportSettingsInspector::AddLightingPreset()
@@ -355,25 +355,25 @@ namespace MaterialEditor
return savePath;
}
AZ::Crc32 ViewportSettingsInspector::GetGroupSaveStateKey(const AZStd::string& groupNameId) const
AZ::Crc32 ViewportSettingsInspector::GetGroupSaveStateKey(const AZStd::string& groupName) const
{
return AZ::Crc32(AZStd::string::format("ViewportSettingsInspector::PropertyGroup::%s", groupNameId.c_str()));
return AZ::Crc32(AZStd::string::format("ViewportSettingsInspector::PropertyGroup::%s", groupName.c_str()));
}
bool ViewportSettingsInspector::ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const
bool ViewportSettingsInspector::ShouldGroupAutoExpanded(const AZStd::string& groupName) const
{
auto stateItr = m_windowSettings->m_inspectorCollapsedGroups.find(GetGroupSaveStateKey(groupNameId));
auto stateItr = m_windowSettings->m_inspectorCollapsedGroups.find(GetGroupSaveStateKey(groupName));
return stateItr == m_windowSettings->m_inspectorCollapsedGroups.end();
}
void ViewportSettingsInspector::OnGroupExpanded(const AZStd::string& groupNameId)
void ViewportSettingsInspector::OnGroupExpanded(const AZStd::string& groupName)
{
m_windowSettings->m_inspectorCollapsedGroups.erase(GetGroupSaveStateKey(groupNameId));
m_windowSettings->m_inspectorCollapsedGroups.erase(GetGroupSaveStateKey(groupName));
}
void ViewportSettingsInspector::OnGroupCollapsed(const AZStd::string& groupNameId)
void ViewportSettingsInspector::OnGroupCollapsed(const AZStd::string& groupName)
{
m_windowSettings->m_inspectorCollapsedGroups.insert(GetGroupSaveStateKey(groupNameId));
m_windowSettings->m_inspectorCollapsedGroups.insert(GetGroupSaveStateKey(groupName));
}
} // namespace MaterialEditor
@@ -75,10 +75,10 @@ namespace MaterialEditor
AZStd::string GetDefaultUniqueSaveFilePath(const AZStd::string& baseName) const;
AZ::Crc32 GetGroupSaveStateKey(const AZStd::string& groupNameId) const;
bool ShouldGroupAutoExpanded(const AZStd::string& groupNameId) const override;
void OnGroupExpanded(const AZStd::string& groupNameId) override;
void OnGroupCollapsed(const AZStd::string& groupNameId) override;
AZ::Crc32 GetGroupSaveStateKey(const AZStd::string& groupName) const;
bool ShouldGroupAutoExpanded(const AZStd::string& groupName) const override;
void OnGroupExpanded(const AZStd::string& groupName) override;
void OnGroupCollapsed(const AZStd::string& groupName) override;
AZ::Render::ModelPresetPtr m_modelPreset;
AZ::Render::LightingPresetPtr m_lightingPreset;
@@ -175,7 +175,7 @@ namespace AZ
void MaterialPropertyInspector::AddDetailsGroup()
{
const AZStd::string& groupNameId = "Details";
const AZStd::string& groupName = "Details";
const AZStd::string& groupDisplayName = "Details";
const AZStd::string& groupDescription = "";
@@ -241,15 +241,15 @@ namespace AZ
propertyGroupContainer->layout()->addWidget(materialInfoWidget);
AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupContainer);
AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupContainer);
}
void MaterialPropertyInspector::AddUvNamesGroup()
{
const AZStd::string groupNameId = AZ::RPI::UvGroupName;
const AZStd::string groupName = AZ::RPI::UvGroupName;
const AZStd::string groupDisplayName = "UV Sets";
const AZStd::string groupDescription = "UV set names in this material, which can be renamed to match those in the model.";
auto& group = m_groups[groupNameId];
auto& group = m_groups[groupName];
const RPI::MaterialUvNameMap& uvNameMap = m_editData.m_materialAsset->GetMaterialTypeAsset()->GetUvNameMap();
group.m_properties.reserve(uvNameMap.size());
@@ -263,8 +263,8 @@ namespace AZ
propertyConfig = {};
propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::String;
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, shaderInputStr).GetCStr();
propertyConfig.m_nameId = shaderInputStr;
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupName, shaderInputStr).GetCStr();
propertyConfig.m_name = shaderInputStr;
propertyConfig.m_displayName = shaderInputStr;
propertyConfig.m_groupName = groupDisplayName;
propertyConfig.m_description = shaderInputStr;
@@ -277,8 +277,8 @@ namespace AZ
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
&group, nullptr, group.TYPEINFO_Uuid(), this, this, GetSaveStateKeyForGroup(groupNameId));
AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget);
&group, nullptr, group.TYPEINFO_Uuid(), this, this, GetSaveStateKeyForGroup(groupName));
AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupWidget);
}
void MaterialPropertyInspector::Populate()
@@ -291,13 +291,13 @@ namespace AZ
// Copy all of the properties from the material asset to the source data that will be exported
for (const auto& groupDefinition : m_editData.m_materialTypeSourceData.GetGroupDefinitionsInDisplayOrder())
{
const AZStd::string& groupNameId = groupDefinition.m_nameId;
const AZStd::string& groupDisplayName = !groupDefinition.m_displayName.empty() ? groupDefinition.m_displayName : groupNameId;
const AZStd::string& groupName = groupDefinition.m_name;
const AZStd::string& groupDisplayName = !groupDefinition.m_displayName.empty() ? groupDefinition.m_displayName : groupName;
const AZStd::string& groupDescription = !groupDefinition.m_description.empty() ? groupDefinition.m_description : groupDisplayName;
auto& group = m_groups[groupNameId];
auto& group = m_groups[groupName];
const auto& propertyLayout = m_editData.m_materialTypeSourceData.m_propertyLayout;
const auto& propertyListItr = propertyLayout.m_properties.find(groupNameId);
const auto& propertyListItr = propertyLayout.m_properties.find(groupName);
if (propertyListItr != propertyLayout.m_properties.end())
{
group.m_properties.reserve(propertyListItr->second.size());
@@ -306,7 +306,7 @@ namespace AZ
AtomToolsFramework::DynamicPropertyConfig propertyConfig;
// Assign id before conversion so it can be used in dynamic description
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName();
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupName, propertyDefinition.m_name).GetFullName();
AtomToolsFramework::ConvertToPropertyConfig(propertyConfig, propertyDefinition);
@@ -322,8 +322,8 @@ namespace AZ
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget(
&group, nullptr, group.TYPEINFO_Uuid(), this, this, GetSaveStateKeyForGroup(groupNameId));
AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget);
&group, nullptr, group.TYPEINFO_Uuid(), this, this, GetSaveStateKeyForGroup(groupName));
AddGroup(groupName, groupDisplayName, groupDescription, propertyGroupWidget);
}
AddGroupsEnd();
@@ -502,11 +502,11 @@ namespace AZ
}
}
AZ::Crc32 MaterialPropertyInspector::GetSaveStateKeyForGroup(const AZStd::string& groupNameId) const
AZ::Crc32 MaterialPropertyInspector::GetSaveStateKeyForGroup(const AZStd::string& groupName) const
{
return AZ::Crc32(AZStd::string::format(
"MaterialPropertyInspector::PropertyGroup::%s::%s", m_editData.m_materialAssetId.ToString<AZStd::string>().c_str(),
groupNameId.c_str()));
groupName.c_str()));
}
bool MaterialPropertyInspector::AreNodePropertyValuesEqual(
@@ -100,7 +100,7 @@ namespace AZ
void RunEditorMaterialFunctors();
void UpdateMaterialInstanceProperty(const AtomToolsFramework::DynamicProperty& property);
AZ::Crc32 GetSaveStateKeyForGroup(const AZStd::string& groupNameId) const;
AZ::Crc32 GetSaveStateKeyForGroup(const AZStd::string& groupName) const;
static bool AreNodePropertyValuesEqual(
const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target);
@@ -137,8 +137,8 @@ namespace AZ
// Copy all of the properties from the material asset to the source data that will be exported
result = true;
editData.m_materialTypeSourceData.EnumerateProperties([&](const AZStd::string& groupNameId, const AZStd::string& propertyNameId, const auto& propertyDefinition) {
const AZ::RPI::MaterialPropertyId propertyId(groupNameId, propertyNameId);
editData.m_materialTypeSourceData.EnumerateProperties([&](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition) {
const AZ::RPI::MaterialPropertyId propertyId(groupName, propertyName);
const AZ::RPI::MaterialPropertyIndex propertyIndex =
editData.m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyId.GetFullName());
@@ -170,7 +170,7 @@ namespace AZ
return true;
}
exportData.m_properties[groupNameId][propertyDefinition.m_nameId].m_value = propertyValue;
exportData.m_properties[groupName][propertyDefinition.m_name].m_value = propertyValue;
return true;
});
@@ -81,7 +81,7 @@ namespace AZ
{
AddGroupsBegin();
const AZStd::string groupNameId = "ModelUvMap";
const AZStd::string groupName = "ModelUvMap";
const AZStd::string groupDisplayName = "Material to Model UV Map";
const AZStd::string groupDescription = "Custom map that maps a UV name from the material to one from the model.";
@@ -96,8 +96,8 @@ namespace AZ
const AZStd::string materialUvName = m_materialUvNames[i].m_uvName.GetStringView();
propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::Enum;
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, shaderInput).GetFullName();
propertyConfig.m_nameId = shaderInput;
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupName, shaderInput).GetFullName();
propertyConfig.m_name = shaderInput;
propertyConfig.m_displayName = materialUvName;
propertyConfig.m_description = shaderInput;
propertyConfig.m_defaultValue = 0u;
@@ -108,7 +108,7 @@ namespace AZ
m_group.m_properties.back().SetValue(AZStd::any(m_modelUvNameIndices[i]));
}
AddGroup(groupNameId, groupDisplayName, groupDescription,
AddGroup(groupName, groupDisplayName, groupDescription,
new AtomToolsFramework::InspectorPropertyGroupWidget(&m_group, nullptr, m_group.TYPEINFO_Uuid(), this));
AddGroupsEnd();
@@ -238,7 +238,7 @@ namespace AZ
ResetModelUvNameIndices();
const AZStd::string groupNameId = "ModelUvMap";
const AZStd::string groupName = "ModelUvMap";
size_t uvSize = m_materialUvNames.size();
for (size_t i = 0u; i < uvSize; ++i)
@@ -248,8 +248,8 @@ namespace AZ
const AZStd::string materialUvName = m_materialUvNames[i].m_uvName.GetStringView();
propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::Enum;
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, shaderInput).GetFullName();
propertyConfig.m_nameId = shaderInput;
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupName, shaderInput).GetFullName();
propertyConfig.m_name = shaderInput;
propertyConfig.m_displayName = materialUvName;
propertyConfig.m_description = shaderInput;
propertyConfig.m_defaultValue = 0u;