Add material property names to material assets, disable FBX dependency on materialtype files. (#3408)

* Add material property names to material assets, disable FBX dependency on materialtype files.

Signed-off-by: Robin <rbarrand@amazon.com>

* Add reflection for MaterialAssets. Update member variable comment.

Signed-off-by: Robin <rbarrand@amazon.com>

* Switch cvar to using bus value. Refine comments.

Signed-off-by: Robin <rbarrand@amazon.com>

* Refactor functions and refine comments.

Signed-off-by: Robin <rbarrand@amazon.com>

* Realign property values when material property names are populated.

Signed-off-by: Robin <rbarrand@amazon.com>

* Switch PostLoadInit check to on asset status ready. Add realign property values code to PostLoadInit as well.

Signed-off-by: Robin <rbarrand@amazon.com>

* Stash@{1} code.

Signed-off-by: Robin <rbarrand@amazon.com>

* Refactor realignment code into the right places.

Signed-off-by: Robin <rbarrand@amazon.com>

* Remove pragma optmize off.

Signed-off-by: Robin <rbarrand@amazon.com>

* More refactoring.

Signed-off-by: Robin <rbarrand@amazon.com>

* Refactor comments and remove code no longer needed.

Signed-off-by: Robin <rbarrand@amazon.com>

* Refactor comments and remove unused include.

Signed-off-by: Robin <rbarrand@amazon.com>

* Comment refactor, corrected some code.

Signed-off-by: Robin <rbarrand@amazon.com>

Co-authored-by: Robin <rbarrand@amazon.com>
monroegm-disable-blank-issue-2
hershey5045 4 years ago committed by GitHub
parent 413e82428c
commit 4249ceeae7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -26,9 +26,10 @@ namespace AZ
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<MaterialConverterSettings>()
->Version(1)
->Version(2)
->Field("Enable", &MaterialConverterSettings::m_enable)
->Field("DefaultMaterial", &MaterialConverterSettings::m_defaultMaterial);
->Field("DefaultMaterial", &MaterialConverterSettings::m_defaultMaterial)
->Field("IncludeMaterialPropertyNames", &MaterialConverterSettings::m_includeMaterialPropertyNames);
}
}
@ -69,6 +70,11 @@ namespace AZ
return m_settings.m_enable;
}
bool MaterialConverterSystemComponent::ShouldIncludeMaterialPropertyNames() const
{
return m_settings.m_includeMaterialPropertyNames;
}
bool MaterialConverterSystemComponent::ConvertMaterial(
const AZ::SceneAPI::DataTypes::IMaterialData& materialData, RPI::MaterialSourceData& sourceData)
{

@ -26,6 +26,11 @@ namespace AZ
bool m_enable = true;
AZStd::string m_defaultMaterial;
//! Sets whether to include material property names when generating material assets. If this
//! setting is true, material property name resolution and validation is deferred into load
//! time rather than at build time, allowing to break some dependencies (e.g. fbx files will no
//! longer need to be dependent on materialtype files).
bool m_includeMaterialPropertyNames = true;
};
//! Atom's implementation of converting SceneAPI data into Atom's default material: StandardPBR
@ -45,6 +50,7 @@ namespace AZ
// MaterialConverterBus overrides ...
bool IsEnabled() const override;
bool ShouldIncludeMaterialPropertyNames() const override;
bool ConvertMaterial(const AZ::SceneAPI::DataTypes::IMaterialData& materialData, RPI::MaterialSourceData& out) override;
AZStd::string GetMaterialTypePath() const override;
AZStd::string GetDefaultMaterialPath() const override;

@ -32,6 +32,10 @@ namespace AZ
virtual bool IsEnabled() const = 0;
//! Returns true if material property names should be included in azmaterials. This allows unlinking of dependencies for some
//! file types to materialtype files (e.g. fbx).
virtual bool ShouldIncludeMaterialPropertyNames() const = 0;
//! Converts data from a IMaterialData object to an Atom MaterialSourceData.
//! Only works when IsEnabled() is true.
//! @return true if the MaterialSourceData output was populated with converted material data.

@ -68,12 +68,12 @@ namespace AZ
//! @param assetId ID for the MaterialAsset
//! @param materialSourceFilePath Indicates the path of the .material file that the MaterialSourceData represents. Used for resolving file-relative paths.
//! @param elevateWarnings Indicates whether to treat warnings as errors
//! @param materialTypeSourceData The function sometimes needs metadata from the .materialtype file.
//! It will either load the .materialtype file from disk, or use this MaterialTypeSourceData if it's provided.
//! @param includeMaterialPropertyNames Indicates whether to save material property names into the material asset file
Outcome<Data::Asset<MaterialAsset>> CreateMaterialAsset(
Data::AssetId assetId,
AZStd::string_view materialSourceFilePath = "",
bool elevateWarnings = true
bool elevateWarnings = true,
bool includeMaterialPropertyNames = true
) const;
};
} // namespace RPI

@ -108,6 +108,11 @@ namespace AZ
private:
bool PostLoadInit() override;
//! Realigns property value and name indices with MaterialProperiesLayout by using m_propertyNames. Property names not found in the
//! MaterialPropertiesLayout are discarded, while property names not included in m_propertyNames will use the default value
//! from m_materialTypeAsset.
void RealignPropertyValuesAndNames();
//! Called by asset creators to assign the asset to a ready state.
void SetReady();
@ -121,11 +126,20 @@ namespace AZ
// MaterialReloadNotificationBus overrides...
void OnMaterialTypeAssetReinitialized(const Data::Asset<MaterialTypeAsset>& materialTypeAsset) override;
static const char* s_debugTraceName;
Data::Asset<MaterialTypeAsset> m_materialTypeAsset;
//! Holds values for each material property, used to initialize Material instances.
//! This is indexed by MaterialPropertyIndex and aligns with entries in m_materialPropertiesLayout.
AZStd::vector<MaterialPropertyValue> m_propertyValues;
//! This is used to realign m_propertyValues as well as itself with MaterialPropertiesLayout when not empty.
//! If empty, this implies that m_propertyValues is aligned with the entries in m_materialPropertiesLayout.
AZStd::vector<AZ::Name> m_propertyNames;
//! A flag to determine if m_propertyValues needs to be aligned with MaterialPropertiesLayout. Set to true whenever
//! m_materialTypeAsset is reinitializing.
bool m_isDirty = true;
};

@ -26,11 +26,13 @@ namespace AZ
public:
friend class MaterialSourceData;
void Begin(const Data::AssetId& assetId, MaterialAsset& parentMaterial);
void Begin(const Data::AssetId& assetId, MaterialTypeAsset& materialType);
void Begin(const Data::AssetId& assetId, MaterialAsset& parentMaterial, bool includeMaterialPropertyNames = true);
void Begin(const Data::AssetId& assetId, MaterialTypeAsset& materialType, bool includeMaterialPropertyNames = true);
bool End(Data::Asset<MaterialAsset>& result);
private:
void PopulatePropertyNameList();
const MaterialPropertiesLayout* m_materialPropertiesLayout = nullptr;
};
} // namespace RPI

@ -78,7 +78,9 @@ namespace AZ
AZStd::string materialTypePath;
RPI::MaterialConverterBus::BroadcastResult(materialTypePath, &RPI::MaterialConverterBus::Events::GetMaterialTypePath);
if (conversionEnabled && !materialTypePath.empty())
bool includeMaterialPropertyNames = true;
RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames);
if (conversionEnabled && !materialTypePath.empty() && !includeMaterialPropertyNames)
{
AssetBuilderSDK::SourceFileDependency materialTypeSource;
materialTypeSource.m_sourceFileDependencyPath = materialTypePath;
@ -101,6 +103,10 @@ namespace AZ
RPI::MaterialConverterBus::BroadcastResult(conversionEnabled, &RPI::MaterialConverterBus::Events::IsEnabled);
fingerprintInfo.insert(AZStd::string::format("[MaterialConverter enabled=%d]", conversionEnabled));
bool includeMaterialPropertyNames = true;
RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames);
fingerprintInfo.insert(AZStd::string::format("[MaterialConverter includeMaterialPropertyNames=%d]", includeMaterialPropertyNames));
if (!conversionEnabled)
{
AZStd::string defaultMaterialPath;
@ -219,6 +225,8 @@ namespace AZ
}
}
bool includeMaterialPropertyNames = true;
RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames);
// Build material assets.
for (auto& itr : materialSourceDataByUid)
{
@ -226,7 +234,7 @@ namespace AZ
Data::AssetId assetId(sourceSceneUuid, GetMaterialAssetSubId(materialUid));
auto materialSourceData = itr.second;
Outcome<Data::Asset<MaterialAsset>> result = materialSourceData.m_data.CreateMaterialAsset(assetId, "", false);
Outcome<Data::Asset<MaterialAsset>> result = materialSourceData.m_data.CreateMaterialAsset(assetId, "", false, includeMaterialPropertyNames);
if (result.IsSuccess())
{
context.m_outputMaterialsByUid[materialUid] = { result.GetValue(), materialSourceData.m_name };

@ -12,6 +12,7 @@
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialPropertyId.h>
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
#include <Atom/RPI.Edit/Material/MaterialConverterBus.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Common/JsonFileLoadContext.h>
@ -72,7 +73,7 @@ namespace AZ
}
}
Outcome<Data::Asset<MaterialAsset> > MaterialSourceData::CreateMaterialAsset(Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings) const
Outcome<Data::Asset<MaterialAsset> > MaterialSourceData::CreateMaterialAsset(Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings, bool includeMaterialPropertyNames) const
{
MaterialAssetCreator materialAssetCreator;
materialAssetCreator.SetElevateWarnings(elevateWarnings);
@ -85,7 +86,7 @@ namespace AZ
return Failure();
}
materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get());
materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames);
}
else
{
@ -115,7 +116,7 @@ namespace AZ
}
}
materialAssetCreator.Begin(assetId, *parentMaterialAsset.GetValue().Get());
materialAssetCreator.Begin(assetId, *parentMaterialAsset.GetValue().Get(), includeMaterialPropertyNames);
}
for (auto& group : m_properties)

@ -20,6 +20,8 @@ namespace AZ
{
namespace RPI
{
const char* MaterialAsset::s_debugTraceName = "MaterialAsset";
const char* MaterialAsset::DisplayName = "MaterialAsset";
const char* MaterialAsset::Group = "Material";
const char* MaterialAsset::Extension = "azmaterial";
@ -29,9 +31,10 @@ namespace AZ
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
{
serializeContext->Class<MaterialAsset, AZ::Data::AssetData>()
->Version(9)
->Version(10)
->Field("materialTypeAsset", &MaterialAsset::m_materialTypeAsset)
->Field("propertyValues", &MaterialAsset::m_propertyValues)
->Field("propertyNames", &MaterialAsset::m_propertyNames)
;
}
}
@ -99,6 +102,11 @@ namespace AZ
AZStd::array_view<MaterialPropertyValue> MaterialAsset::GetPropertyValues() const
{
if (!m_propertyNames.empty() && m_isDirty)
{
const_cast<MaterialAsset*>(this)->RealignPropertyValuesAndNames();
}
return m_propertyValues;
}
@ -146,6 +154,34 @@ namespace AZ
}
}
void MaterialAsset::RealignPropertyValuesAndNames()
{
const MaterialPropertiesLayout* propertyLayout = GetMaterialPropertiesLayout();
AZStd::vector<MaterialPropertyValue> alignedPropertyValues(m_materialTypeAsset->GetDefaultPropertyValues().begin(), m_materialTypeAsset->GetDefaultPropertyValues().end());
for (size_t i = 0; i < m_propertyNames.size(); ++i)
{
const MaterialPropertyIndex propertyIndex = propertyLayout->FindPropertyIndex(m_propertyNames[i]);
if (propertyIndex.IsValid())
{
alignedPropertyValues[propertyIndex.GetIndex()] = m_propertyValues[i];
}
else
{
AZ_Warning(s_debugTraceName, false, "Material property name \"%s\" is not found in the material properties layout and will not be used.", m_propertyNames[i].GetCStr());
}
}
m_propertyValues.swap(alignedPropertyValues);
const size_t propertyCount = propertyLayout->GetPropertyCount();
m_propertyNames.resize(propertyCount);
for (size_t i = 0; i < propertyCount; ++i)
{
m_propertyNames[i] = propertyLayout->GetPropertyDescriptor(MaterialPropertyIndex{ i })->GetName();
}
m_isDirty = false;
}
void MaterialAsset::ReinitializeMaterialTypeAsset(Data::Asset<Data::AssetData> asset)
{
Data::Asset<MaterialTypeAsset> newMaterialTypeAsset = { asset.GetAs<MaterialTypeAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
@ -157,6 +193,8 @@ namespace AZ
// This also covers the case where just the MaterialTypeAsset is reloaded and not the MaterialAsset.
m_materialTypeAsset = newMaterialTypeAsset;
m_isDirty = true;
// Notify interested parties that this MaterialAsset is changed and may require other data to reinitialize as well
MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialAssetReinitialized, Data::Asset<MaterialAsset>{this, AZ::Data::AssetLoadBehavior::PreLoad});
}

@ -16,7 +16,7 @@ namespace AZ
{
namespace RPI
{
void MaterialAssetCreator::Begin(const Data::AssetId& assetId, MaterialAsset& parentMaterial)
void MaterialAssetCreator::Begin(const Data::AssetId& assetId, MaterialAsset& parentMaterial, bool includeMaterialPropertyNames)
{
BeginCommon(assetId);
@ -36,6 +36,10 @@ namespace AZ
ReportError("MaterialPropertiesLayout is null");
return;
}
if (includeMaterialPropertyNames)
{
PopulatePropertyNameList();
}
// Note we don't have to check the validity of these property values because the parent material's AssetCreator already did that.
m_asset->m_propertyValues.assign(parentMaterial.GetPropertyValues().begin(), parentMaterial.GetPropertyValues().end());
@ -52,14 +56,14 @@ namespace AZ
}
}
void MaterialAssetCreator::Begin(const Data::AssetId& assetId, MaterialTypeAsset& materialType)
void MaterialAssetCreator::Begin(const Data::AssetId& assetId, MaterialTypeAsset& materialType, bool includeMaterialPropertyNames)
{
BeginCommon(assetId);
if (ValidateIsReady())
{
m_asset->m_materialTypeAsset = { &materialType, AZ::Data::AssetLoadBehavior::PreLoad };
if (!m_asset->m_materialTypeAsset)
{
ReportError("MaterialTypeAsset is null");
@ -67,6 +71,11 @@ namespace AZ
}
m_materialPropertiesLayout = m_asset->GetMaterialPropertiesLayout();
if (includeMaterialPropertyNames)
{
PopulatePropertyNameList();
}
if (!m_materialPropertiesLayout)
{
ReportError("MaterialPropertiesLayout is null");
@ -101,5 +110,16 @@ namespace AZ
m_asset->SetReady();
return EndCommon(result);
}
void MaterialAssetCreator::PopulatePropertyNameList()
{
for (int i = 0; i < m_materialPropertiesLayout->GetPropertyCount(); ++i)
{
MaterialPropertyIndex propertyIndex{ i };
auto& propertyName = m_materialPropertiesLayout->GetPropertyDescriptor(propertyIndex)->GetName();
m_asset->m_propertyNames.emplace_back(propertyName);
}
}
} // namespace RPI
} // namespace AZ

Loading…
Cancel
Save