| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- /*
- * 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 <AzTest/AzTest.h>
- #include <Common/RPITestFixture.h>
- #include <Common/JsonTestUtils.h>
- #include <Common/TestUtils.h>
- #include <Tests/Serialization/Json/JsonSerializerConformityTests.h>
- #include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
- #include <Atom/RPI.Edit/Material/MaterialFunctorSourceData.h>
- #include <Atom/RPI.Edit/Material/MaterialPropertyValueSourceData.h>
- #include <Atom/RPI.Edit/Material/MaterialPropertyValueSourceDataSerializer.h>
- #include <Atom/RPI.Reflect/Material/MaterialTypeAsset.h>
- #include <Atom/RPI.Reflect/Material/MaterialPropertiesLayout.h>
- #include <Atom/RPI.Reflect/Material/MaterialTypeAssetCreator.h>
- #include <Atom/RPI.Reflect/Material/MaterialNameContext.h>
- namespace JsonSerializationTests
- {
- class MaterialPropertyValueSourceDataSerializerTestDescription :
- public JsonSerializerConformityTestDescriptor<AZ::RPI::MaterialPropertyValueSourceData>
- {
- public:
- void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
- {
- AZ::RPI::MaterialPropertyValueSourceData::Reflect(context.get());
- }
- void Reflect(AZStd::unique_ptr<AZ::JsonRegistrationContext>& context) override
- {
- context->Serializer<AZ::RPI::JsonMaterialPropertyValueSourceDataSerializer>()->HandlesType<AZ::RPI::MaterialPropertyValueSourceData>();
- }
- AZStd::shared_ptr<AZ::BaseJsonSerializer> CreateSerializer() override
- {
- return AZStd::make_shared<AZ::RPI::JsonMaterialPropertyValueSourceDataSerializer>();
- }
- AZStd::shared_ptr<AZ::RPI::MaterialPropertyValueSourceData> CreateDefaultInstance() override
- {
- return AZStd::make_shared<AZ::RPI::MaterialPropertyValueSourceData>();
- }
- AZStd::shared_ptr<AZ::RPI::MaterialPropertyValueSourceData> CreateFullySetInstance() override
- {
- auto result = AZStd::make_shared<AZ::RPI::MaterialPropertyValueSourceData>();
- result->SetValue(42);
- return result;
- }
- AZStd::string_view GetJsonForFullySetInstance() override
- {
- return R"(42)";
- }
- void ConfigureFeatures(JsonSerializerConformityTestDescriptorFeatures& features) override
- {
- features.EnableJsonType(rapidjson::kFalseType);
- features.EnableJsonType(rapidjson::kTrueType);
- features.EnableJsonType(rapidjson::kArrayType);
- features.EnableJsonType(rapidjson::kStringType);
- features.EnableJsonType(rapidjson::kNumberType);
- features.m_fixedSizeArray = true;
- features.m_supportsPartialInitialization = false;
- features.m_supportsInjection = false;
- }
- bool AreEqual(
- const AZ::RPI::MaterialPropertyValueSourceData& lhs,
- const AZ::RPI::MaterialPropertyValueSourceData& rhs) override
- {
- return AZ::RPI::MaterialPropertyValueSourceData::AreSimilar(lhs, rhs);
- }
- };
- using MaterialPropertyValueSourceDataSerializerTestTypes = ::testing::Types<MaterialPropertyValueSourceDataSerializerTestDescription>;
- IF_JSON_CONFORMITY_ENABLED(INSTANTIATE_TYPED_TEST_CASE_P(MaterialPropertyValueSourceDataTests, JsonSerializerConformityTests, MaterialPropertyValueSourceDataSerializerTestTypes));
- } // namespace JsonSerializationTests
- namespace UnitTest
- {
- using namespace AZ;
- using namespace RPI;
- class MaterialPropertyValueSourceDataTests
- : public RPITestFixture
- {
- protected:
- //! A dummy material creator filled with necessary data.
- //! It is kept alive between SetUp and TearDown, so that MaterialPropertyValueSourceData can have access to the layout and resolve its value.
- MaterialTypeAssetCreator m_materialTypeCreator;
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Samples used for testing MaterialFunctor
- class ValueFunctor final
- : public MaterialFunctor
- {
- public:
- AZ_CLASS_ALLOCATOR(ValueFunctor, SystemAllocator)
- AZ_RTTI(MaterialPropertyValueSourceDataTests::ValueFunctor, "{07CE498C-6E97-45C9-8B2D-18BC03724055}", AZ::RPI::MaterialFunctor);
- static void Reflect(ReflectContext* context)
- {
- if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
- {
- serializeContext->Class<ValueFunctor, AZ::RPI::MaterialFunctor>()
- ->Version(1)
- ->Field("propertyIndex", &ValueFunctor::m_propertyIndex)
- ->Field("propertyValue", &ValueFunctor::m_propertyValue)
- ;
- }
- }
- MaterialPropertyIndex m_propertyIndex;
- MaterialPropertyValue m_propertyValue;
- };
- class ValueFunctorSourceData final
- : public MaterialFunctorSourceData
- {
- public:
- AZ_CLASS_ALLOCATOR(ValueFunctorSourceData, AZ::SystemAllocator)
- AZ_RTTI(ValueFunctorSourceData, "{777CE7A5-3023-4C63-BA43-5763DF51D82D}", AZ::RPI::MaterialFunctorSourceData);
- static void Reflect(ReflectContext* context)
- {
- if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
- {
- serializeContext->Class<ValueFunctorSourceData>()
- ->Version(1)
- ->Field("propertyName", &ValueFunctorSourceData::m_propertyName)
- ->Field("propertyValue", &ValueFunctorSourceData::m_propertyValue)
- ;
- }
- }
- AZStd::string m_propertyName;
- MaterialPropertyValueSourceData m_propertyValue;
- using MaterialFunctorSourceData::CreateFunctor;
- FunctorResult CreateFunctor(const RuntimeContext& context) const override
- {
- Ptr<ValueFunctor> functor = aznew ValueFunctor;
- functor->m_propertyIndex = context.FindMaterialPropertyIndex(Name(m_propertyName));
- EXPECT_TRUE(functor->m_propertyIndex.IsValid());
- m_propertyValue.Resolve(*context.GetMaterialPropertiesLayout(), AZ::Name(m_propertyName));
- functor->m_propertyValue = m_propertyValue.GetValue();
- return Success(Ptr<MaterialFunctor>(functor));
- }
- };
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- void Reflect(ReflectContext* context) override
- {
- RPITestFixture::Reflect(context);
- MaterialPropertyValueSourceData::Reflect(context);
- MaterialFunctorSourceDataHolder::Reflect(context);
- ValueFunctorSourceData::Reflect(context);
- ValueFunctor::Reflect(context);
- }
- void SetUp() override
- {
- RPITestFixture::SetUp();
- m_materialTypeCreator.Begin(Data::AssetId(Uuid::CreateRandom()));
- m_materialTypeCreator.BeginMaterialProperty(AZ::Name{"general.Bool"}, MaterialPropertyDataType::Bool);
- m_materialTypeCreator.EndMaterialProperty();
- m_materialTypeCreator.BeginMaterialProperty(AZ::Name{"general.Int"}, MaterialPropertyDataType::Int);
- m_materialTypeCreator.EndMaterialProperty();
- m_materialTypeCreator.BeginMaterialProperty(AZ::Name{"general.UInt"}, MaterialPropertyDataType::UInt);
- m_materialTypeCreator.EndMaterialProperty();
- m_materialTypeCreator.BeginMaterialProperty(AZ::Name{"general.Float"}, MaterialPropertyDataType::Float);
- m_materialTypeCreator.EndMaterialProperty();
- m_materialTypeCreator.BeginMaterialProperty(AZ::Name{"general.Vector2"}, MaterialPropertyDataType::Vector2);
- m_materialTypeCreator.EndMaterialProperty();
- m_materialTypeCreator.BeginMaterialProperty(AZ::Name{"general.Vector3"}, MaterialPropertyDataType::Vector3);
- m_materialTypeCreator.EndMaterialProperty();
- m_materialTypeCreator.BeginMaterialProperty(AZ::Name{"general.Vector4"}, MaterialPropertyDataType::Vector4);
- m_materialTypeCreator.EndMaterialProperty();
- m_materialTypeCreator.BeginMaterialProperty(AZ::Name{"general.Color"}, MaterialPropertyDataType::Color);
- m_materialTypeCreator.EndMaterialProperty();
- m_materialTypeCreator.BeginMaterialProperty(AZ::Name{"general.Image"}, MaterialPropertyDataType::Image);
- m_materialTypeCreator.EndMaterialProperty();
- m_materialTypeCreator.BeginMaterialProperty(AZ::Name{ "general.Enum" }, MaterialPropertyDataType::Enum);
- m_materialTypeCreator.SetMaterialPropertyEnumNames(AZStd::vector<AZStd::string>({ "DummyEnum" }));
- m_materialTypeCreator.EndMaterialProperty();
- }
- void TearDown() override
- {
- {
- Data::Asset<MaterialTypeAsset> testAsset;
- m_materialTypeCreator.End(testAsset);
- }
- RPITestFixture::TearDown();
- }
- };
- TEST_F(MaterialPropertyValueSourceDataTests, MaterialFunctorTest)
- {
- AZStd::unordered_map<MaterialPropertyDataType, const char *> typeValue =
- {
- {MaterialPropertyDataType::Bool, "true"},
- {MaterialPropertyDataType::Int, "-42"},
- {MaterialPropertyDataType::UInt, "42"},
- {MaterialPropertyDataType::Float, "42.0"},
- {MaterialPropertyDataType::Vector2, "[42.0, 42.0]"},
- {MaterialPropertyDataType::Vector3, "[42.0, 42.0, 42.0]"},
- {MaterialPropertyDataType::Vector4, "[42.0, 42.0, 42.0, 42.0]"},
- {MaterialPropertyDataType::Color, "[0.0, 0.0, 0.0, 1.0]"},
- {MaterialPropertyDataType::Image, "\"DummyImagePath.png\""},
- {MaterialPropertyDataType::Enum, "\"DummyEnum\""},
- };
- AZStd::array<Ptr<MaterialFunctor>, static_cast<uint32_t>(MaterialPropertyDataType::Count)> valueFunctors;
- valueFunctors.fill(nullptr);
- char inputJson[2048];
- AZStd::string outputJson;
- uint32_t propertyTypeCount = static_cast<uint32_t>(MaterialPropertyDataType::Count);
- static_assert(static_cast<uint32_t>(MaterialPropertyDataType::Invalid) == 0u, "If MaterialPropertyDataType::Invalid has changed its order, the following logic should change accordingly.");
- // Test through each type, serialization and deserialization.
- // Collect the functors and test the serialized value later.
- for (uint32_t i = static_cast<uint32_t>(MaterialPropertyDataType::Invalid) + 1u; i < propertyTypeCount; ++i)
- {
- MaterialPropertyDataType type = static_cast<MaterialPropertyDataType>(i);
- azsnprintf(inputJson, AZ_ARRAY_SIZE(inputJson),
- R"(
- {
- "propertyName": "general.%s",
- "propertyValue": %s
- }
- )",
- ToString(type),
- typeValue[type]
- );
- // Stored as base class.
- Ptr<ValueFunctorSourceData> functorData = aznew ValueFunctorSourceData;
- JsonTestResult loadResult = LoadTestDataFromJson(*functorData, inputJson);
- MaterialNameContext nameContext;
- // Where type resolving happens.
- MaterialFunctorSourceData::FunctorResult functorResult = functorData->CreateFunctor(
- MaterialFunctorSourceData::RuntimeContext(
- "Dummy.materialtype",
- m_materialTypeCreator.GetMaterialPropertiesLayout(),
- m_materialTypeCreator.GetMaterialShaderResourceGroupLayout(),
- &nameContext
- )
- );
- valueFunctors[i] = functorResult.GetValue();
- // Store back to json after type is resolved.
- outputJson.clear();
- JsonTestResult storeResult = StoreTestDataToJson(*functorData, outputJson);
- ExpectSimilarJson(inputJson, outputJson);
- }
- MaterialPropertyValue& value = static_cast<ValueFunctor*>(valueFunctors[static_cast<uint32_t>(MaterialPropertyDataType::Bool)].get())->m_propertyValue;
- EXPECT_TRUE(value == true);
- value = static_cast<ValueFunctor*>(valueFunctors[static_cast<uint32_t>(MaterialPropertyDataType::Int)].get())->m_propertyValue;
- EXPECT_TRUE(value == -42);
- value = static_cast<ValueFunctor*>(valueFunctors[static_cast<uint32_t>(MaterialPropertyDataType::UInt)].get())->m_propertyValue;
- EXPECT_TRUE(value == 42u);
- value = static_cast<ValueFunctor*>(valueFunctors[static_cast<uint32_t>(MaterialPropertyDataType::Float)].get())->m_propertyValue;
- EXPECT_TRUE(value == 42.0f);
- value = static_cast<ValueFunctor*>(valueFunctors[static_cast<uint32_t>(MaterialPropertyDataType::Vector2)].get())->m_propertyValue;
- EXPECT_TRUE(value == Vector2(42.0f, 42.0f));
- value = static_cast<ValueFunctor*>(valueFunctors[static_cast<uint32_t>(MaterialPropertyDataType::Vector3)].get())->m_propertyValue;
- EXPECT_TRUE(value == Vector3(42.0f, 42.0f, 42.0f));
- value = static_cast<ValueFunctor*>(valueFunctors[static_cast<uint32_t>(MaterialPropertyDataType::Vector4)].get())->m_propertyValue;
- EXPECT_TRUE(value == Vector4(42.0f, 42.0f, 42.0f, 42.0f));
- value = static_cast<ValueFunctor*>(valueFunctors[static_cast<uint32_t>(MaterialPropertyDataType::Color)].get())->m_propertyValue;
- EXPECT_TRUE(value == Color(0.0f, 0.0f, 0.0f, 1.0f));
- value = static_cast<ValueFunctor*>(valueFunctors[static_cast<uint32_t>(MaterialPropertyDataType::Image)].get())->m_propertyValue;
- EXPECT_TRUE(value == AZStd::string("DummyImagePath.png"));
- value = static_cast<ValueFunctor*>(valueFunctors[static_cast<uint32_t>(MaterialPropertyDataType::Enum)].get())->m_propertyValue;
- EXPECT_TRUE(value == AZStd::string("DummyEnum"));
- }
- TEST_F(MaterialPropertyValueSourceDataTests, DataSimilarityTest)
- {
- MaterialPropertyValueSourceData emptyValue;
- MaterialPropertyValueSourceData onlyResolvedValue[2];
- MaterialPropertyValueSourceData onlyPossibleValue[2];
- MaterialPropertyValueSourceData fullValue[2];
- // Load data
- static const char* source[] = { R"(42)", R"(43)" };
- constexpr int32_t value[] = { 42, 43 };
- for (int32_t i = 0; i < 2; ++i)
- {
- LoadTestDataFromJson(onlyPossibleValue[i], source[i]);
- LoadTestDataFromJson(fullValue[i], source[i]);
- onlyResolvedValue[i].SetValue(value[i]);
- fullValue[i].SetValue(value[i]);
- }
- // Group them into 2 based on the source data.
- // Within each set, AreSimilar should return true.
- // Between two sets, assuming different source data, AreSimilar should return false.
- MaterialPropertyValueSourceData* setA[] = {
- &onlyResolvedValue[0],
- &onlyPossibleValue[0],
- &fullValue[0]
- };
- MaterialPropertyValueSourceData* setB[] = {
- &onlyResolvedValue[1],
- &onlyPossibleValue[1],
- &fullValue[1]
- };
- EXPECT_TRUE(AZ::RPI::MaterialPropertyValueSourceData::AreSimilar(emptyValue, emptyValue));
- for (int32_t i = 0; i < 3; ++i)
- {
- for (int32_t j = 0; j < 3; ++j)
- {
- // Test within each set and between them, including comparing to the element itself.
- EXPECT_TRUE(AZ::RPI::MaterialPropertyValueSourceData::AreSimilar(*setA[i], *setA[j]));
- EXPECT_TRUE(AZ::RPI::MaterialPropertyValueSourceData::AreSimilar(*setB[i], *setB[j]));
- EXPECT_FALSE(AZ::RPI::MaterialPropertyValueSourceData::AreSimilar(*setA[i], *setB[j]));
- }
- // Test against empty.
- EXPECT_FALSE(AZ::RPI::MaterialPropertyValueSourceData::AreSimilar(*setA[i], emptyValue));
- EXPECT_FALSE(AZ::RPI::MaterialPropertyValueSourceData::AreSimilar(*setB[i], emptyValue));
- }
- }
- }
|