Tied up some loose ends with nested property group support.

Fixed the MaterialBuilder to report source dependencies on imported JSON files, so the material type will rebuild when you edit an imported file that contains shared property data.
Fixed a spot in LuaMaterialFunctorSourceData where it was only applying the old "prefix" feature and not the new name context.
Updated a couple built-in material functors to take advantage of the name context (they were using RuntimeContext::GetShaderResourceGroupLayout instead of the RuntimeContext::FindShaderInputConstantIndex wrapper utility function).
Fixed an issue with EnumeratePropertyGroups where it wasn't passing the right name context, so Material Editor wasn't able to load some material types.
Reordered the parameters in the MaterialTypeSourceData enumerate callback functions, I felt this order was more natural.

Signed-off-by: santorac <55155825+santorac@users.noreply.github.com>
monroegm-disable-blank-issue-2
santorac 4 years ago
parent 2c59f1b8a4
commit a7bdb05d66

@ -72,9 +72,9 @@ namespace AZ
AddMaterialPropertyDependency(functor, functor->m_scatterDistanceColor);
AddMaterialPropertyDependency(functor, functor->m_scatterDistanceIntensity);
functor->m_scatterDistance = context.GetShaderResourceGroupLayout()->FindShaderInputConstantIndex(Name{ m_scatterDistance });
functor->m_transmissionParams = context.GetShaderResourceGroupLayout()->FindShaderInputConstantIndex(Name{ m_transmissionParams });
functor->m_transmissionTintThickness = context.GetShaderResourceGroupLayout()->FindShaderInputConstantIndex(Name{ m_transmissionTintThickness });
functor->m_scatterDistance = context.FindShaderInputConstantIndex(Name{ m_scatterDistance });
functor->m_transmissionParams = context.FindShaderInputConstantIndex(Name{ m_transmissionParams });
functor->m_transmissionTintThickness = context.FindShaderInputConstantIndex(Name{ m_transmissionTintThickness });
if (functor->m_scatterDistance.IsNull())
{

@ -62,7 +62,7 @@ namespace AZ
AddMaterialPropertyDependency(functor, functor->m_translateY);
AddMaterialPropertyDependency(functor, functor->m_rotateDegrees);
functor->m_transformMatrix = context.GetShaderResourceGroupLayout()->FindShaderInputConstantIndex(Name{m_transformMatrix});
functor->m_transformMatrix = context.FindShaderInputConstantIndex(Name{m_transformMatrix});
if (functor->m_transformMatrix.IsNull())
{
@ -74,7 +74,7 @@ namespace AZ
// In that case, the.materialtype file will not provide the name of an inverse matrix because it doesn't have one.
if (!m_transformMatrixInverse.empty())
{
functor->m_transformMatrixInverse = context.GetShaderResourceGroupLayout()->FindShaderInputConstantIndex(Name{m_transformMatrixInverse});
functor->m_transformMatrixInverse = context.FindShaderInputConstantIndex(Name{m_transformMatrixInverse});
if (functor->m_transformMatrixInverse.IsNull())
{

@ -284,8 +284,8 @@ namespace AZ
//! Call back function type used with the enumeration functions.
//! Return false to terminate the traversal.
using EnumeratePropertyGroupsCallback = AZStd::function<bool(
const MaterialNameContext&, // The name context used to scope properties and shader connections (i.e. "levelA.levelB.")
const PropertyGroup* // the next property group in the tree
const PropertyGroup*, // the next property group in the tree
const MaterialNameContext& // The PropertyGroup's name context, used to scope properties and shader connections (i.e. "levelA.levelB.")
)>;
//! Recursively traverses all of the property groups contained in the material type, executing a callback function for each.
@ -295,8 +295,8 @@ namespace AZ
//! Call back function type used with the numeration functions.
//! Return false to terminate the traversal.
using EnumeratePropertiesCallback = AZStd::function<bool(
const MaterialNameContext&, // The name context used to scope properties and shader connections (i.e. "levelA.levelB.")
const PropertyDefinition* // the property definition object
const PropertyDefinition*, // the property definition object
const MaterialNameContext& // The property's name context, used to scope properties and shader connections (i.e. "levelA.levelB.")
)>;
//! Recursively traverses all of the properties contained in the material type, executing a callback function for each.

@ -28,6 +28,8 @@ namespace AZ
namespace MaterialUtils
{
using ImportedJsonFiles = AZStd::unordered_set<AZStd::string>;
enum class GetImageAssetResult
{
Empty, //! No image was actually requested, the path was empty
@ -52,7 +54,8 @@ namespace AZ
//! Otherwise, it will use the passed in document first if not null, or load the json document from the path.
//! @param filePath path to the JSON file to load, unless the @document is already provided. In either case, this path will be used to resolve any relative file references.
//! @param document an optional already loaded json document.
AZ::Outcome<MaterialTypeSourceData> LoadMaterialTypeSourceData(const AZStd::string& filePath, rapidjson::Document* document = nullptr);
//! @param importedFiles receives the list of files that were imported by the JSON serializer
AZ::Outcome<MaterialTypeSourceData> LoadMaterialTypeSourceData(const AZStd::string& filePath, rapidjson::Document* document = nullptr, ImportedJsonFiles* importedFiles = 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.

@ -187,13 +187,21 @@ namespace AZ
const bool isMaterialTypeFile = AzFramework::StringFunc::Path::IsExtension(request.m_sourceFile.c_str(), MaterialTypeSourceData::Extension);
if (isMaterialTypeFile)
{
auto materialTypeSourceData = MaterialUtils::LoadMaterialTypeSourceData(fullSourcePath, &document);
MaterialUtils::ImportedJsonFiles importedJsonFiles;
auto materialTypeSourceData = MaterialUtils::LoadMaterialTypeSourceData(fullSourcePath, &document, &importedJsonFiles);
if (!materialTypeSourceData.IsSuccess())
{
return;
}
for (auto& importedJsonFile : importedJsonFiles)
{
AssetBuilderSDK::SourceFileDependency sourceDependency;
sourceDependency.m_sourceFileDependencyPath = importedJsonFile;
response.m_sourceFileDependencyList.push_back(sourceDependency);
}
for (auto& shader : materialTypeSourceData.GetValue().m_shaderCollection)
{
AddPossibleDependencies(request.m_sourceFile,

@ -198,7 +198,10 @@ namespace AZ
for (const Name& materialProperty : materialPropertyDependencies.GetValue())
{
MaterialPropertyIndex index = propertiesLayout->FindPropertyIndex(Name{m_propertyNamePrefix + materialProperty.GetCStr()});
Name propertyName{materialProperty.GetCStr()};
functor->m_materialNameContext.ContextualizeProperty(propertyName);
MaterialPropertyIndex index = propertiesLayout->FindPropertyIndex(propertyName);
if (!index.IsValid())
{
AZ_Error("LuaMaterialFunctorSourceData", false, "Property '%s' is not found in material type.", materialProperty.GetCStr());

@ -381,13 +381,13 @@ namespace AZ
{
for (auto& propertyGroup : inPropertyGroupList)
{
if (!callback(materialNameContext, propertyGroup.get()))
MaterialNameContext materialNameContext2 = ExtendNameContext(materialNameContext, *propertyGroup);
if (!callback(propertyGroup.get(), materialNameContext2))
{
return false; // Stop processing
}
MaterialNameContext materialNameContext2 = ExtendNameContext(materialNameContext, *propertyGroup);
if (!EnumeratePropertyGroups(callback, materialNameContext2, propertyGroup->m_propertyGroups))
{
return false; // Stop processing
@ -415,7 +415,7 @@ namespace AZ
for (auto& property : propertyGroup->m_properties)
{
if (!callback(materialNameContext2, property.get()))
if (!callback(property.get(), materialNameContext2))
{
return false; // Stop processing
}
@ -483,7 +483,7 @@ namespace AZ
enumValues.push_back(uvNamePair.second);
}
EnumerateProperties([&enumValues](const MaterialNameContext&, const MaterialTypeSourceData::PropertyDefinition* property)
EnumerateProperties([&enumValues](const MaterialTypeSourceData::PropertyDefinition* property, const MaterialNameContext&)
{
if (property->m_dataType == AZ::RPI::MaterialPropertyDataType::Enum && property->m_enumIsUv)
{

@ -74,7 +74,7 @@ namespace AZ
return true;
}
AZ::Outcome<MaterialTypeSourceData> LoadMaterialTypeSourceData(const AZStd::string& filePath, rapidjson::Document* document)
AZ::Outcome<MaterialTypeSourceData> LoadMaterialTypeSourceData(const AZStd::string& filePath, rapidjson::Document* document, ImportedJsonFiles* importedFiles)
{
rapidjson::Document localDocument;
@ -96,6 +96,10 @@ namespace AZ
importSettings.m_importer = &jsonImporter;
importSettings.m_loadedJsonPath = filePath;
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ResolveImports(document->GetObject(), document->GetAllocator(), importSettings);
if (importedFiles)
{
*importedFiles = importSettings.m_importer->GetImportedFiles();
}
MaterialTypeSourceData materialType;

@ -486,8 +486,8 @@ namespace UnitTest
struct EnumeratePropertyGroupsResult
{
MaterialNameContext m_materialNameContext;
const MaterialTypeSourceData::PropertyGroup* m_propertyGroup;
MaterialNameContext m_materialNameContext;
void Check(AZStd::string expectedIdContext, const MaterialTypeSourceData::PropertyGroup* expectedPropertyGroup)
{
@ -502,9 +502,9 @@ namespace UnitTest
};
AZStd::vector<EnumeratePropertyGroupsResult> enumeratePropertyGroupsResults;
sourceData.EnumeratePropertyGroups([&enumeratePropertyGroupsResults](const MaterialNameContext& materialNameContext, const MaterialTypeSourceData::PropertyGroup* propertyGroup)
sourceData.EnumeratePropertyGroups([&enumeratePropertyGroupsResults](const MaterialTypeSourceData::PropertyGroup* propertyGroup, const MaterialNameContext& nameContext)
{
enumeratePropertyGroupsResults.push_back(EnumeratePropertyGroupsResult{materialNameContext, propertyGroup});
enumeratePropertyGroupsResults.push_back(EnumeratePropertyGroupsResult{propertyGroup, nameContext});
return true;
});
@ -525,8 +525,8 @@ namespace UnitTest
struct EnumeratePropertiesResult
{
MaterialNameContext m_materialNameContext;
const MaterialTypeSourceData::PropertyDefinition* m_propertyDefinition;
MaterialNameContext m_materialNameContext;
void Check(AZStd::string expectedIdContext, const MaterialTypeSourceData::PropertyDefinition* expectedPropertyDefinition)
{
@ -541,9 +541,9 @@ namespace UnitTest
};
AZStd::vector<EnumeratePropertiesResult> enumeratePropertiesResults;
sourceData.EnumerateProperties([&enumeratePropertiesResults](const MaterialNameContext& materialNameContext, const MaterialTypeSourceData::PropertyDefinition* propertyDefinition)
sourceData.EnumerateProperties([&enumeratePropertiesResults](const MaterialTypeSourceData::PropertyDefinition* propertyDefinition, const MaterialNameContext& nameContext)
{
enumeratePropertiesResults.push_back(EnumeratePropertiesResult{materialNameContext, propertyDefinition});
enumeratePropertiesResults.push_back(EnumeratePropertiesResult{propertyDefinition, nameContext});
return true;
});

@ -586,10 +586,10 @@ namespace MaterialEditor
bool result = true;
// populate sourceData with properties that meet the filter
m_materialTypeSourceData.EnumerateProperties([&](const MaterialNameContext& materialNameContext, const auto& propertyDefinition) {
m_materialTypeSourceData.EnumerateProperties([&](const auto& propertyDefinition, const MaterialNameContext& nameContext) {
Name propertyId{propertyDefinition->GetName()};
materialNameContext.ContextualizeProperty(propertyId);
nameContext.ContextualizeProperty(propertyId);
const auto it = m_properties.find(propertyId);
if (it != m_properties.end() && propertyFilter(it->second))
@ -783,17 +783,15 @@ 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.EnumeratePropertyGroups([this, &parentPropertyValues](const MaterialNameContext& materialNameContext, const MaterialTypeSourceData::PropertyGroup* propertyGroup)
m_materialTypeSourceData.EnumeratePropertyGroups([this, &parentPropertyValues](const MaterialTypeSourceData::PropertyGroup* propertyGroup, const MaterialNameContext& nameContext)
{
AtomToolsFramework::DynamicPropertyConfig propertyConfig;
for (const auto& propertyDefinition : propertyGroup->GetProperties())
{
// Assign id before conversion so it can be used in dynamic description
MaterialNameContext groupNameContext = materialNameContext;
groupNameContext.ExtendPropertyIdContext(propertyGroup->GetName());
propertyConfig.m_id = propertyDefinition->GetName();
groupNameContext.ContextualizeProperty(propertyConfig.m_id);
nameContext.ContextualizeProperty(propertyConfig.m_id);
const auto& propertyIndex = m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyConfig.m_id);
const bool propertyIndexInBounds = propertyIndex.IsValid() && propertyIndex.GetIndex() < m_materialAsset->GetPropertyValues().size();
@ -907,7 +905,7 @@ namespace MaterialEditor
// Add any material functors that are located inside each property group.
bool enumerateResult = m_materialTypeSourceData.EnumeratePropertyGroups(
[this](const MaterialNameContext& nameContext, const MaterialTypeSourceData::PropertyGroup* propertyGroup)
[this](const MaterialTypeSourceData::PropertyGroup* propertyGroup, const MaterialNameContext& nameContext)
{
const MaterialFunctorSourceData::EditorContext editorContext = MaterialFunctorSourceData::EditorContext(
m_materialSourceData.m_materialType, m_materialAsset->GetMaterialPropertiesLayout(), &nameContext);

@ -114,10 +114,10 @@ namespace AZ
// Copy all of the properties from the material asset to the source data that will be exported
bool result = true;
editData.m_materialTypeSourceData.EnumerateProperties([&](const AZ::RPI::MaterialNameContext& materialNameContext, const AZ::RPI::MaterialTypeSourceData::PropertyDefinition* propertyDefinition)
editData.m_materialTypeSourceData.EnumerateProperties([&](const AZ::RPI::MaterialTypeSourceData::PropertyDefinition* propertyDefinition, const AZ::RPI::MaterialNameContext& nameContext)
{
AZ::Name propertyId{propertyDefinition->GetName()};
materialNameContext.ContextualizeProperty(propertyId);
nameContext.ContextualizeProperty(propertyId);
const AZ::RPI::MaterialPropertyIndex propertyIndex =
editData.m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyId);

Loading…
Cancel
Save