diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h index 987e78ae0f..40555bae00 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Material/MaterialAssignment.h @@ -39,13 +39,24 @@ namespace AZ //! Otherwise an attempt will be made to find or create a shared instance. void RebuildInstance(); + //! Release asset and instance references + void Release(); + + //! 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; Data::Asset m_materialAsset; + Data::Asset m_defaultMaterialAsset; Data::Instance m_materialInstance; MaterialPropertyOverrideMap m_propertyOverrides; RPI::MaterialModelUvOverrideMap m_matModUvOverrides; + bool m_materialInstancePreCreated = false; }; using MaterialAssignmentMap = AZStd::unordered_map; diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp index 5b90ed7f06..8984ec160b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Material/MaterialAssignment.cpp @@ -71,9 +71,9 @@ namespace AZ } MaterialAssignment::MaterialAssignment(const AZ::Data::AssetId& materialAssetId) - : m_materialInstance() + : m_materialAsset(materialAssetId, AZ::AzTypeInfo::Uuid()) + , m_materialInstance() { - m_materialAsset.Create(materialAssetId); } MaterialAssignment::MaterialAssignment(const Data::Asset& asset) @@ -90,12 +90,70 @@ namespace AZ void MaterialAssignment::RebuildInstance() { + if (m_materialInstancePreCreated) + { + return; + } + if (m_materialAsset.IsReady()) { - m_materialInstance = - m_propertyOverrides.empty() ? RPI::Material::FindOrCreate(m_materialAsset) : RPI::Material::Create(m_materialAsset); + m_materialInstance = m_propertyOverrides.empty() ? RPI::Material::FindOrCreate(m_materialAsset) : RPI::Material::Create(m_materialAsset); AZ_Error("MaterialAssignment", m_materialInstance, "Material instance not initialized"); } + else if (m_defaultMaterialAsset.IsReady()) + { + m_materialInstance = m_propertyOverrides.empty() ? RPI::Material::FindOrCreate(m_defaultMaterialAsset) : RPI::Material::Create(m_defaultMaterialAsset); + AZ_Error("MaterialAssignment", m_materialInstance, "Material instance not initialized"); + } + } + + void MaterialAssignment::Release() + { + if (!m_materialInstancePreCreated) + { + m_materialInstance = nullptr; + } + m_materialAsset.Release(); + m_defaultMaterialAsset.Release(); + } + + bool MaterialAssignment::RequiresLoading() const + { + return + !m_materialInstancePreCreated && + !m_materialAsset.IsReady() && + !m_materialAsset.IsLoading() && + !m_defaultMaterialAsset.IsReady() && + !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 diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp index 7edff11174..6d6fd377e3 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp @@ -182,7 +182,9 @@ namespace MaterialEditor AZ_Error("MaterialViewportRenderer", m_shadowCatcherMaterial != nullptr, "Could not create shadow catcher material."); AZ::Render::MaterialAssignmentMap shadowCatcherMaterials; - shadowCatcherMaterials[AZ::Render::DefaultMaterialAssignmentId].m_materialInstance = m_shadowCatcherMaterial; + auto& shadowCatcherMaterialAssignment = shadowCatcherMaterials[AZ::Render::DefaultMaterialAssignmentId]; + shadowCatcherMaterialAssignment.m_materialInstance = m_shadowCatcherMaterial; + shadowCatcherMaterialAssignment.m_materialInstancePreCreated = true; AZ::Render::MaterialComponentRequestBus::Event(m_shadowCatcherEntity->GetId(), &AZ::Render::MaterialComponentRequestBus::Events::SetMaterialOverrides, shadowCatcherMaterials); @@ -291,7 +293,9 @@ namespace MaterialEditor MaterialDocumentRequestBus::EventResult(materialInstance, documentId, &MaterialDocumentRequestBus::Events::GetInstance); AZ::Render::MaterialAssignmentMap materials; - materials[AZ::Render::DefaultMaterialAssignmentId].m_materialInstance = materialInstance; + auto& materialAssignment = materials[AZ::Render::DefaultMaterialAssignmentId]; + materialAssignment.m_materialInstance = materialInstance; + materialAssignment.m_materialInstancePreCreated = true; AZ::Render::MaterialComponentRequestBus::Event(m_modelEntity->GetId(), &AZ::Render::MaterialComponentRequestBus::Events::SetMaterialOverrides, materials); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h index ace16ba6ca..ed7f1564ac 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h @@ -151,7 +151,9 @@ namespace AZ //! Returns the list of all ModelMaterialSlot's for the model, across all LODs. virtual RPI::ModelMaterialSlotMap GetModelMaterialSlots() const = 0; + //! Returns the available, overridable material slots and the default assigned materials virtual MaterialAssignmentMap GetMaterialAssignments() const = 0; + virtual AZStd::unordered_set GetModelUvNames() const = 0; }; using MaterialReceiverRequestBus = EBus; @@ -161,6 +163,7 @@ namespace AZ : public ComponentBus { public: + //! Notification that overridable material slots are available or have changed virtual void OnMaterialAssignmentsChanged() = 0; }; using MaterialReceiverNotificationBus = EBus; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp index a3152faf87..f526abde0c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp @@ -88,6 +88,12 @@ namespace AZ AZ::Data::AssetId materialAssetId = {}; MaterialComponentRequestBus::EventResult( materialAssetId, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialOverride, m_materialAssignmentId); + if (!materialAssetId.IsValid()) + { + MaterialComponentRequestBus::EventResult( + materialAssetId, m_entityId, &MaterialComponentRequestBus::Events::GetDefaultMaterialAssetId, + m_materialAssignmentId); + } if (!materialAssetId.IsValid()) { @@ -728,11 +734,16 @@ namespace AZ void MaterialPropertyInspector::UpdateUI() { - AZ::Data::AssetId assetId; + AZ::Data::AssetId materialAssetId = {}; MaterialComponentRequestBus::EventResult( - assetId, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialOverride, m_materialAssignmentId); + materialAssetId, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialOverride, m_materialAssignmentId); + if (!materialAssetId.IsValid()) + { + MaterialComponentRequestBus::EventResult( + materialAssetId, m_entityId, &MaterialComponentRequestBus::Events::GetDefaultMaterialAssetId, m_materialAssignmentId); + } - if (IsLoaded() && m_editData.m_materialAssetId == assetId) + if (IsLoaded() && m_editData.m_materialAssetId == materialAssetId) { LoadOverridesFromEntity(); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index c4d21ba599..f5d38f48c4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -118,10 +118,16 @@ namespace AZ } }; + AZ::Data::AssetId EditorMaterialComponentSlot::GetActiveAssetId() const + { + return m_materialAsset.GetId().IsValid() ? m_materialAsset.GetId() : GetDefaultAssetId(); + } + AZ::Data::AssetId EditorMaterialComponentSlot::GetDefaultAssetId() const { AZ::Data::AssetId assetId; - MaterialComponentRequestBus::EventResult(assetId, m_entityId, &MaterialComponentRequestBus::Events::GetDefaultMaterialAssetId, m_id); + MaterialComponentRequestBus::EventResult( + assetId, m_entityId, &MaterialComponentRequestBus::Events::GetDefaultMaterialAssetId, m_id); return assetId; } @@ -135,7 +141,7 @@ namespace AZ bool EditorMaterialComponentSlot::HasSourceData() const { // The slot only has valid source data if the source path is valid and the file has the correct extension - const AZStd::string& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(m_materialAsset.GetId()); + const AZStd::string& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(GetActiveAssetId()); return !sourcePath.empty() && AZ::StringFunc::Path::IsExtension(sourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension); } @@ -220,7 +226,7 @@ namespace AZ void EditorMaterialComponentSlot::OpenMaterialEditor() const { - const AZStd::string& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(m_materialAsset.GetId()); + const AZStd::string& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(GetActiveAssetId()); if (!sourcePath.empty() && AZ::StringFunc::Path::IsExtension(sourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension)) { EditorMaterialSystemComponentRequestBus::Broadcast( @@ -236,7 +242,7 @@ namespace AZ void EditorMaterialComponentSlot::OpenUvNameMapInspector() { - if (m_materialAsset.GetId().IsValid()) + if (GetActiveAssetId().IsValid()) { AZStd::unordered_set modelUvNames; MaterialReceiverRequestBus::EventResult(modelUvNames, m_entityId, &MaterialReceiverRequestBus::Events::GetModelUvNames); @@ -252,7 +258,7 @@ namespace AZ }; if (EditorMaterialComponentInspector::OpenInspectorDialog( - m_materialAsset.GetId(), matModUvOverrides, modelUvNames, applyMatModUvOverrideChangedCallback)) + GetActiveAssetId(), matModUvOverrides, modelUvNames, applyMatModUvOverrideChangedCallback)) { OnDataChanged(); } @@ -274,10 +280,10 @@ namespace AZ action->setEnabled(HasSourceData()); action = menu.addAction("Edit Material Instance...", [this]() { OpenMaterialInspector(); }); - action->setEnabled(m_materialAsset.GetId().IsValid()); + action->setEnabled(GetActiveAssetId().IsValid()); action = menu.addAction("Edit Material Instance UV Map...", [this]() { OpenUvNameMapInspector(); }); - action->setEnabled(m_materialAsset.GetId().IsValid()); + action->setEnabled(GetActiveAssetId().IsValid()); menu.addSeparator(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h index 01e357f1bb..377fe9a18b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h @@ -30,6 +30,7 @@ namespace AZ static void Reflect(ReflectContext* context); static bool ConvertVersion(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement); + AZ::Data::AssetId GetActiveAssetId() const; AZ::Data::AssetId GetDefaultAssetId() const; AZStd::string GetLabel() const; bool HasSourceData() const; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp index bd148c8ba4..4c26042a26 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp @@ -111,12 +111,14 @@ namespace AZ m_queuedMaterialUpdateNotification = false; MaterialComponentRequestBus::Handler::BusConnect(m_entityId); + MaterialReceiverNotificationBus::Handler::BusConnect(m_entityId); LoadMaterials(); } void MaterialComponentController::Deactivate() { MaterialComponentRequestBus::Handler::BusDisconnect(); + MaterialReceiverNotificationBus::Handler::BusDisconnect(); TickBus::Handler::BusDisconnect(); ReleaseMaterials(); @@ -146,56 +148,26 @@ namespace AZ void MaterialComponentController::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) { - AZStd::unordered_set propertyOverrides; - AZStd::swap(m_queuedPropertyOverrides, propertyOverrides); + AZStd::unordered_set 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) { @@ -213,15 +185,35 @@ namespace AZ Data::AssetBus::MultiHandler::BusDisconnect(); bool anyQueued = false; - for (auto& materialPair : m_configuration.m_materials) + auto queueAsset = [&anyQueued, this](AZ::Data::Asset& materialAsset) -> bool { - auto& materialAsset = materialPair.second.m_materialAsset; - - if (materialAsset.GetId().IsValid() && !Data::AssetBus::MultiHandler::BusIsConnectedId(materialAsset.GetId())) + if (materialAsset.GetId().IsValid() && !this->Data::AssetBus::MultiHandler::BusIsConnectedId(materialAsset.GetId())) { anyQueued = true; materialAsset.QueueLoad(); - Data::AssetBus::MultiHandler::BusConnect(materialAsset.GetId()); + this->Data::AssetBus::MultiHandler::BusConnect(materialAsset.GetId()); + return true; + } + return false; + }; + + for (auto& materialPair : m_configuration.m_materials) + { + if (materialPair.second.m_materialInstancePreCreated) + { + continue; + } + + materialPair.second.m_defaultMaterialAsset = {}; + if (!queueAsset(materialPair.second.m_materialAsset)) + { + // 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( + GetDefaultMaterialAssetId(materialPair.first), AZ::AzTypeInfo::Uuid()); + queueAsset(materialPair.second.m_defaultMaterialAsset); + } } } @@ -234,10 +226,8 @@ namespace AZ void MaterialComponentController::InitializeMaterialInstance(const Data::Asset& asset) { bool allReady = true; - - for (auto& materialPair : m_configuration.m_materials) + auto updateAsset = [&](AZ::Data::Asset& materialAsset) { - auto& materialAsset = materialPair.second.m_materialAsset; if (materialAsset.GetId() == asset.GetId()) { materialAsset = asset; @@ -247,6 +237,12 @@ namespace AZ { allReady = false; } + }; + + for (auto& materialPair : m_configuration.m_materials) + { + updateAsset(materialPair.second.m_materialAsset); + updateAsset(materialPair.second.m_defaultMaterialAsset); } if (allReady) @@ -269,11 +265,7 @@ namespace AZ for (auto& materialPair : m_configuration.m_materials) { - if (materialPair.second.m_materialAsset.GetId().IsValid()) - { - materialPair.second.m_materialAsset.Release(); - materialPair.second.m_materialInstance = nullptr; - } + materialPair.second.Release(); } MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsUpdated, m_configuration.m_materials); @@ -441,12 +433,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) @@ -460,18 +447,21 @@ namespace AZ void MaterialComponentController::SetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZStd::any& value) { auto& materialAssignment = m_configuration.m_materials[materialAssignmentId]; + const bool wasEmpty = materialAssignment.m_propertyOverrides.empty(); + materialAssignment.m_propertyOverrides[AZ::Name(propertyName)] = value; - // When applying property overrides for the first time, new instance needs to be created in case the current instance is already used somewhere else to keep overrides local - if (materialAssignment.m_propertyOverrides.empty()) + if (materialAssignment.RequiresLoading()) { - materialAssignment.m_propertyOverrides[AZ::Name(propertyName)] = value; - materialAssignment.RebuildInstance(); - MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialInstanceCreated, materialAssignment); - QueueMaterialUpdateNotification(); + LoadMaterials(); + return; } - else + + if (wasEmpty != materialAssignment.m_propertyOverrides.empty()) { - materialAssignment.m_propertyOverrides[AZ::Name(propertyName)] = value; + materialAssignment.RebuildInstance(); + MaterialComponentNotificationBus::Event( + m_entityId, &MaterialComponentNotifications::OnMaterialInstanceCreated, materialAssignment); + QueueMaterialUpdateNotification(); } QueuePropertyChanges(materialAssignmentId); @@ -704,6 +694,12 @@ namespace AZ const bool wasEmpty = materialAssignment.m_propertyOverrides.empty(); materialAssignment.m_propertyOverrides = propertyOverrides; + if (materialAssignment.RequiresLoading()) + { + LoadMaterials(); + return; + } + if (wasEmpty != materialAssignment.m_propertyOverrides.empty()) { materialAssignment.RebuildInstance(); @@ -713,14 +709,11 @@ namespace AZ QueuePropertyChanges(materialAssignmentId); } - MaterialPropertyOverrideMap MaterialComponentController::GetPropertyOverrides(const MaterialAssignmentId& materialAssignmentId) const + MaterialPropertyOverrideMap MaterialComponentController::GetPropertyOverrides( + const MaterialAssignmentId& materialAssignmentId) const { const auto materialIt = m_configuration.m_materials.find(materialAssignmentId); - if (materialIt == m_configuration.m_materials.end()) - { - return {}; - } - return materialIt->second.m_propertyOverrides; + return materialIt != m_configuration.m_materials.end() ? materialIt->second.m_propertyOverrides : MaterialPropertyOverrideMap(); } void MaterialComponentController::SetModelUvOverrides( @@ -730,6 +723,12 @@ namespace AZ const bool wasEmpty = materialAssignment.m_matModUvOverrides.empty(); materialAssignment.m_matModUvOverrides = modelUvOverrides; + if (materialAssignment.RequiresLoading()) + { + LoadMaterials(); + return; + } + if (wasEmpty != materialAssignment.m_matModUvOverrides.empty()) { materialAssignment.RebuildInstance(); @@ -743,16 +742,24 @@ namespace AZ const MaterialAssignmentId& materialAssignmentId) const { const auto materialIt = m_configuration.m_materials.find(materialAssignmentId); - if (materialIt == m_configuration.m_materials.end()) + return materialIt != m_configuration.m_materials.end() ? materialIt->second.m_matModUvOverrides : AZ::RPI::MaterialModelUvOverrideMap(); + } + + void MaterialComponentController::OnMaterialAssignmentsChanged() + { + for (const auto& materialPair : m_configuration.m_materials) { - return {}; + if (materialPair.second.RequiresLoading()) + { + LoadMaterials(); + return; + } } - return materialIt->second.m_matModUvOverrides; } void MaterialComponentController::QueuePropertyChanges(const MaterialAssignmentId& materialAssignmentId) { - m_queuedPropertyOverrides.emplace(materialAssignmentId); + m_materialsWithDirtyProperties.emplace(materialAssignmentId); if (!TickBus::Handler::BusIsConnected()) { TickBus::Handler::BusConnect(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h index 2bf15ca3b8..1594456a31 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h @@ -22,6 +22,7 @@ namespace AZ //! to provide material overrides on a per-entity basis. class MaterialComponentController final : MaterialComponentRequestBus::Handler + , MaterialReceiverNotificationBus::Handler , Data::AssetBus::MultiHandler , TickBus::Handler { @@ -100,6 +101,9 @@ namespace AZ const MaterialAssignmentId& materialAssignmentId, const AZ::RPI::MaterialModelUvOverrideMap& modelUvOverrides) override; AZ::RPI::MaterialModelUvOverrideMap GetModelUvOverrides(const MaterialAssignmentId& materialAssignmentId) const override; + //! MaterialReceiverNotificationBus::Handler overrides... + void OnMaterialAssignmentsChanged() override; + private: AZ_DISABLE_COPY(MaterialComponentController); @@ -121,7 +125,7 @@ namespace AZ EntityId m_entityId; MaterialComponentConfig m_configuration; - AZStd::unordered_set m_queuedPropertyOverrides; + AZStd::unordered_set m_materialsWithDirtyProperties; bool m_queuedMaterialUpdateNotification = false; }; } // namespace Render