/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace AZ { namespace RPI { void MaterialSourceData::Reflect(ReflectContext* context) { if (JsonRegistrationContext* jsonContext = azrtti_cast(context)) { jsonContext->Serializer()->HandlesType(); jsonContext->Serializer()->HandlesType(); } else if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() ->Version(1) ; serializeContext->RegisterGenericType(); serializeContext->RegisterGenericType(); serializeContext->Class() ->Version(1) ; } } // Helper function for CreateMaterialAsset, for applying basic material property values template void ApplyMaterialValues(MaterialAssetCreator& materialAssetCreator, const AZStd::map& values) { for (auto& entry : values) { const Name& propertyId = entry.first; materialAssetCreator.SetPropertyValue(propertyId, entry.second); } } Outcome > MaterialSourceData::CreateMaterialAsset(Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings, bool includeMaterialPropertyNames) const { MaterialAssetCreator materialAssetCreator; materialAssetCreator.SetElevateWarnings(elevateWarnings); if (m_parentMaterial.empty()) { auto materialTypeAsset = AssetUtils::LoadAsset(materialSourceFilePath, m_materialType); if (!materialTypeAsset.IsSuccess()) { return Failure(); } materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); } else { auto parentMaterialAsset = AssetUtils::LoadAsset(materialSourceFilePath, m_parentMaterial); if (!parentMaterialAsset.IsSuccess()) { return Failure(); } // Make sure the parent material has the same material type { auto materialTypeIdOutcome = AssetUtils::MakeAssetId(materialSourceFilePath, m_materialType, 0); if (!materialTypeIdOutcome.IsSuccess()) { return Failure(); } Data::AssetId expectedMaterialTypeId = materialTypeIdOutcome.GetValue(); Data::AssetId parentMaterialId = parentMaterialAsset.GetValue().GetId(); // This will only be valid if the parent material is not a material type Data::AssetId parentsMaterialTypeId = parentMaterialAsset.GetValue()->GetMaterialTypeAsset().GetId(); if (expectedMaterialTypeId != parentMaterialId && expectedMaterialTypeId != parentsMaterialTypeId) { AZ_Error("MaterialSourceData", false, "This material and its parent material do not share the same material type."); return Failure(); } } materialAssetCreator.Begin(assetId, *parentMaterialAsset.GetValue().Get(), includeMaterialPropertyNames); } for (auto& group : m_properties) { for (auto& property : group.second) { MaterialPropertyId propertyId{ group.first, property.first }; if (!property.second.m_value.IsValid()) { AZ_Warning("Material source data", false, "Source data for material property value is invalid."); } else { MaterialPropertyIndex propertyIndex = materialAssetCreator.m_materialPropertiesLayout->FindPropertyIndex(propertyId.GetFullName()); if (propertyIndex.IsValid()) { const MaterialPropertyDescriptor* propertyDescriptor = materialAssetCreator.m_materialPropertiesLayout->GetPropertyDescriptor(propertyIndex); switch (propertyDescriptor->GetDataType()) { case MaterialPropertyDataType::Image: { Outcome> imageAssetResult = MaterialUtils::GetImageAssetReference(materialSourceFilePath, property.second.m_value.GetValue()); if (imageAssetResult.IsSuccess()) { auto& imageAsset = imageAssetResult.GetValue(); // Load referenced images when load material imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); } else { materialAssetCreator.ReportError("Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), property.second.m_value.GetValue().data()); } } break; case MaterialPropertyDataType::Enum: { AZ::Name enumName = AZ::Name(property.second.m_value.GetValue()); uint32_t enumValue = propertyDescriptor->GetEnumValue(enumName); if (enumValue == MaterialPropertyDescriptor::InvalidEnumValue) { materialAssetCreator.ReportError("Enum value '%s' couldn't be found in the 'enumValues' list", enumName.GetCStr()); } else { materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), enumValue); } } break; default: materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), property.second.m_value); break; } } else { materialAssetCreator.ReportWarning("Can not find property id '%s' in MaterialPropertyLayout", propertyId.GetFullName().GetStringView().data()); } } } } Data::Asset material; if (materialAssetCreator.End(material)) { return Success(material); } else { return Failure(); } } } // namespace RPI } // namespace AZ