moved code for applying properties to MaterialAssignment

added lambdas for queuing and updating assets

Signed-off-by: Guthrie Adams <guthadam@amazon.com>
This commit is contained in:
Guthrie Adams
2021-09-24 13:03:44 -05:00
parent ebcf3723f9
commit b0ea4ac389
4 changed files with 78 additions and 82 deletions
@@ -45,6 +45,9 @@ namespace AZ
//! Return true if contained assets have not been loaded
bool RequiresLoading() const;
//! Applies property overrides to material instance
bool ApplyProperties();
//! Returns a string composed of the asset path.
AZStd::string ToString() const;
@@ -132,6 +132,35 @@ namespace AZ
!m_defaultMaterialAsset.IsLoading();
}
bool MaterialAssignment::ApplyProperties()
{
// if there is no instance or no properties there's nothing to apply
if (!m_materialInstance || m_propertyOverrides.empty())
{
return true;
}
if (m_materialInstance->CanCompile())
{
for (const auto& propertyPair : m_propertyOverrides)
{
if (!propertyPair.second.empty())
{
const auto& materialPropertyIndex = m_materialInstance->FindPropertyIndex(propertyPair.first);
if (!materialPropertyIndex.IsNull())
{
m_materialInstance->SetPropertyValue(
materialPropertyIndex, AZ::RPI::MaterialPropertyValue::FromAny(propertyPair.second));
}
}
}
return m_materialInstance->Compile();
}
return false;
}
AZStd::string MaterialAssignment::ToString() const
{
AZStd::string assetPathString;
@@ -147,56 +147,26 @@ namespace AZ
void MaterialComponentController::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
{
AZStd::unordered_set<MaterialAssignmentId> propertyOverrides;
AZStd::swap(m_queuedPropertyOverrides, propertyOverrides);
AZStd::unordered_set<MaterialAssignmentId> materialsWithDirtyProperties;
AZStd::swap(m_materialsWithDirtyProperties, materialsWithDirtyProperties);
// Iterate through all MaterialAssignmentId's that have property overrides and attempt to apply them
// if material instance is already compiling, delay application of property overrides until next frame
for (const auto& materialAssignmentId : propertyOverrides)
for (const auto& materialAssignmentId : materialsWithDirtyProperties)
{
const auto materialIt = m_configuration.m_materials.find(materialAssignmentId);
if (materialIt == m_configuration.m_materials.end())
if (materialIt != m_configuration.m_materials.end())
{
//Skip materials that do not exist in the map
continue;
}
auto materialInstance = materialIt->second.m_materialInstance;
if (!materialInstance)
{
//Skip materials with an invalid instances
continue;
}
if (!materialInstance->CanCompile())
{
//If a material cannot currently be compiled then it must be queued again
m_queuedPropertyOverrides.emplace(materialAssignmentId);
continue;
}
const auto& propertyOverrides2 = materialIt->second.m_propertyOverrides;
for (auto& propertyPair : propertyOverrides2)
{
if (propertyPair.second.empty())
if (!materialIt->second.ApplyProperties())
{
continue;
// If a material cannot currently be compiled then it must be queued again
m_materialsWithDirtyProperties.emplace(materialAssignmentId);
}
const auto& materialPropertyIndex = materialInstance->FindPropertyIndex(propertyPair.first);
if (materialPropertyIndex.IsNull())
{
continue;
}
materialInstance->SetPropertyValue(materialPropertyIndex, AZ::RPI::MaterialPropertyValue::FromAny(propertyPair.second));
}
materialInstance->Compile();
}
// Only disconnect from tick bus and send notification after all pending properties have been applied
if (m_queuedPropertyOverrides.empty())
if (m_materialsWithDirtyProperties.empty())
{
if (m_queuedMaterialUpdateNotification)
{
@@ -214,6 +184,18 @@ namespace AZ
Data::AssetBus::MultiHandler::BusDisconnect();
bool anyQueued = false;
auto queueAsset = [&anyQueued, this](AZ::Data::Asset<AZ::RPI::MaterialAsset>& materialAsset) -> bool
{
if (materialAsset.GetId().IsValid() && !this->Data::AssetBus::MultiHandler::BusIsConnectedId(materialAsset.GetId()))
{
anyQueued = true;
materialAsset.QueueLoad();
this->Data::AssetBus::MultiHandler::BusConnect(materialAsset.GetId());
return true;
}
return false;
};
for (auto& materialPair : m_configuration.m_materials)
{
if (materialPair.second.m_materialInstancePreCreated)
@@ -221,24 +203,16 @@ namespace AZ
continue;
}
if (materialPair.second.m_materialAsset.GetId().IsValid() &&
!Data::AssetBus::MultiHandler::BusIsConnectedId(materialPair.second.m_materialAsset.GetId()))
materialPair.second.m_defaultMaterialAsset = {};
if (!queueAsset(materialPair.second.m_materialAsset))
{
anyQueued = true;
materialPair.second.m_materialAsset.QueueLoad();
Data::AssetBus::MultiHandler::BusConnect(materialPair.second.m_materialAsset.GetId());
continue;
}
materialPair.second.m_defaultMaterialAsset = AZ::Data::Asset<AZ::RPI::MaterialAsset>(
GetDefaultMaterialAssetId(materialPair.first), AZ::AzTypeInfo<AZ::RPI::MaterialAsset>::Uuid());
if (materialPair.second.m_defaultMaterialAsset.GetId().IsValid() &&
!Data::AssetBus::MultiHandler::BusIsConnectedId(materialPair.second.m_defaultMaterialAsset.GetId()))
{
anyQueued = true;
materialPair.second.m_defaultMaterialAsset.QueueLoad();
Data::AssetBus::MultiHandler::BusConnect(materialPair.second.m_defaultMaterialAsset.GetId());
// Only assign and load the default material if there was no material override and there are propoerties to apply
if (!materialPair.second.m_propertyOverrides.empty() || !materialPair.second.m_matModUvOverrides.empty())
{
materialPair.second.m_defaultMaterialAsset = AZ::Data::Asset<AZ::RPI::MaterialAsset>(
GetDefaultMaterialAssetId(materialPair.first), AZ::AzTypeInfo<AZ::RPI::MaterialAsset>::Uuid());
queueAsset(materialPair.second.m_defaultMaterialAsset);
}
}
}
@@ -251,28 +225,23 @@ namespace AZ
void MaterialComponentController::InitializeMaterialInstance(const Data::Asset<Data::AssetData>& asset)
{
bool allReady = true;
auto updateAsset = [&](AZ::Data::Asset<AZ::RPI::MaterialAsset>& materialAsset)
{
if (materialAsset.GetId() == asset.GetId())
{
materialAsset = asset;
}
if (materialAsset.GetId().IsValid() && !materialAsset.IsReady())
{
allReady = false;
}
};
for (auto& materialPair : m_configuration.m_materials)
{
if (materialPair.second.m_materialAsset.GetId() == asset.GetId())
{
materialPair.second.m_materialAsset = asset;
}
if (materialPair.second.m_materialAsset.GetId().IsValid() && !materialPair.second.m_materialAsset.IsReady())
{
allReady = false;
}
if (materialPair.second.m_defaultMaterialAsset.GetId() == asset.GetId())
{
materialPair.second.m_defaultMaterialAsset = asset;
}
if (materialPair.second.m_defaultMaterialAsset.GetId().IsValid() && !materialPair.second.m_defaultMaterialAsset.IsReady())
{
allReady = false;
}
updateAsset(materialPair.second.m_materialAsset);
updateAsset(materialPair.second.m_defaultMaterialAsset);
}
if (allReady)
@@ -463,12 +432,7 @@ namespace AZ
AZ::Data::AssetId MaterialComponentController::GetMaterialOverride(const MaterialAssignmentId& materialAssignmentId) const
{
auto materialIt = m_configuration.m_materials.find(materialAssignmentId);
if (materialIt == m_configuration.m_materials.end())
{
return {};
}
return materialIt->second.m_materialAsset.GetId();
return materialIt != m_configuration.m_materials.end() ? materialIt->second.m_materialAsset.GetId() : AZ::Data::AssetId();
}
void MaterialComponentController::ClearMaterialOverride(const MaterialAssignmentId& materialAssignmentId)
@@ -794,7 +758,7 @@ namespace AZ
void MaterialComponentController::QueuePropertyChanges(const MaterialAssignmentId& materialAssignmentId)
{
m_queuedPropertyOverrides.emplace(materialAssignmentId);
m_materialsWithDirtyProperties.emplace(materialAssignmentId);
if (!TickBus::Handler::BusIsConnected())
{
TickBus::Handler::BusConnect();
@@ -125,7 +125,7 @@ namespace AZ
EntityId m_entityId;
MaterialComponentConfig m_configuration;
AZStd::unordered_set<MaterialAssignmentId> m_queuedPropertyOverrides;
AZStd::unordered_set<MaterialAssignmentId> m_materialsWithDirtyProperties;
bool m_queuedMaterialUpdateNotification = false;
};
} // namespace Render