/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include #include #include #include #include namespace AZ { namespace Render { void MaterialAssignment::Reflect(ReflectContext* context) { MaterialAssignmentId::Reflect(context); if (auto jsonContext = azrtti_cast(context)) { jsonContext->Serializer()->HandlesType(); } if (auto serializeContext = azrtti_cast(context)) { serializeContext->RegisterGenericType(); serializeContext->RegisterGenericType(); serializeContext->Class() ->Version(1) ->Field("MaterialAsset", &MaterialAssignment::m_materialAsset) ->Field("PropertyOverrides", &MaterialAssignment::m_propertyOverrides) ; } if (auto behaviorContext = azrtti_cast(context)) { behaviorContext->Class("MaterialAssignment") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "render") ->Attribute(AZ::Script::Attributes::Module, "render") ->Constructor() ->Constructor() ->Constructor() ->Constructor&>() ->Constructor&, const Data::Instance&>() ->Method("ToString", &MaterialAssignment::ToString) ->Property("materialAsset", BehaviorValueProperty(&MaterialAssignment::m_materialAsset)) ->Property("propertyOverrides", BehaviorValueProperty(&MaterialAssignment::m_propertyOverrides)) ; behaviorContext->ConstantProperty("DefaultMaterialAssignment", BehaviorConstant(DefaultMaterialAssignment)) ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "render") ->Attribute(AZ::Script::Attributes::Module, "render"); behaviorContext->ConstantProperty("DefaultMaterialAssignmentId", BehaviorConstant(DefaultMaterialAssignmentId)) ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "render") ->Attribute(AZ::Script::Attributes::Module, "render"); behaviorContext->ConstantProperty("DefaultMaterialAssignmentMap", BehaviorConstant(DefaultMaterialAssignmentMap)) ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "render") ->Attribute(AZ::Script::Attributes::Module, "render"); } } MaterialAssignment::MaterialAssignment(const AZ::Data::AssetId& materialAssetId) : m_materialInstance() { m_materialAsset.Create(materialAssetId); } MaterialAssignment::MaterialAssignment(const Data::Asset& asset) : m_materialAsset(asset) , m_materialInstance() { } MaterialAssignment::MaterialAssignment(const Data::Asset& asset, const Data::Instance& instance) : m_materialAsset(asset) , m_materialInstance(instance) { } void MaterialAssignment::RebuildInstance() { if (m_materialAsset.IsReady()) { m_materialInstance = m_propertyOverrides.empty() ? RPI::Material::FindOrCreate(m_materialAsset) : RPI::Material::Create(m_materialAsset); AZ_Error("MaterialAssignment", m_materialInstance, "Material instance not initialized"); } } AZStd::string MaterialAssignment::ToString() const { AZStd::string assetPathString; AZ::Data::AssetCatalogRequestBus::BroadcastResult( assetPathString, &AZ::Data::AssetCatalogRequests::GetAssetPathById, m_materialAsset.GetId()); return assetPathString; } const MaterialAssignment& GetMaterialAssignmentFromMap(const MaterialAssignmentMap& materials, const MaterialAssignmentId& id) { const auto& materialItr = materials.find(id); return materialItr != materials.end() ? materialItr->second : DefaultMaterialAssignment; } const MaterialAssignment& GetMaterialAssignmentFromMapWithFallback( const MaterialAssignmentMap& materials, const MaterialAssignmentId& id) { const MaterialAssignment& lodAssignment = GetMaterialAssignmentFromMap(materials, id); if (lodAssignment.m_materialInstance.get()) { return lodAssignment; } const MaterialAssignment& assetAssignment = GetMaterialAssignmentFromMap(materials, MaterialAssignmentId::CreateFromAssetOnly(id.m_materialAssetId)); if (assetAssignment.m_materialInstance.get()) { return assetAssignment; } const MaterialAssignment& defaultAssignment = GetMaterialAssignmentFromMap(materials, DefaultMaterialAssignmentId); if (defaultAssignment.m_materialInstance.get()) { return defaultAssignment; } return DefaultMaterialAssignment; } MaterialAssignmentMap GetMaterialAssignmentsFromModel(Data::Instance model) { MaterialAssignmentMap materials; materials[DefaultMaterialAssignmentId] = MaterialAssignment(); if (model) { size_t lodIndex = 0; for (const Data::Instance& lod : model->GetLods()) { for (const AZ::RPI::ModelLod::Mesh& mesh : lod->GetMeshes()) { if (mesh.m_material) { const MaterialAssignmentId generalId = MaterialAssignmentId::CreateFromAssetOnly(mesh.m_material->GetAssetId()); materials[generalId] = MaterialAssignment(mesh.m_material->GetAsset(), mesh.m_material); const MaterialAssignmentId specificId = MaterialAssignmentId::CreateFromLodAndAsset(lodIndex, mesh.m_material->GetAssetId()); materials[specificId] = MaterialAssignment(mesh.m_material->GetAsset(), mesh.m_material); } } ++lodIndex; } } return materials; } } // namespace Render } // namespace AZ