Merge branch 'development' into Atom/santorac/RemixableMaterialTypes

This commit is contained in:
santorac
2021-09-30 09:30:17 -07:00
132 changed files with 3532 additions and 3844 deletions
@@ -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();
}
@@ -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<AZ::Name> 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();
@@ -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;
@@ -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<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)
{
@@ -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<AZ::RPI::MaterialAsset>& 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<AZ::RPI::MaterialAsset>(
GetDefaultMaterialAssetId(materialPair.first), AZ::AzTypeInfo<AZ::RPI::MaterialAsset>::Uuid());
queueAsset(materialPair.second.m_defaultMaterialAsset);
}
}
}
@@ -234,10 +226,8 @@ namespace AZ
void MaterialComponentController::InitializeMaterialInstance(const Data::Asset<Data::AssetData>& asset)
{
bool allReady = true;
for (auto& materialPair : m_configuration.m_materials)
auto updateAsset = [&](AZ::Data::Asset<AZ::RPI::MaterialAsset>& 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();
@@ -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<MaterialAssignmentId> m_queuedPropertyOverrides;
AZStd::unordered_set<MaterialAssignmentId> m_materialsWithDirtyProperties;
bool m_queuedMaterialUpdateNotification = false;
};
} // namespace Render