123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784 |
- /*
- * 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 <AzCore/Asset/AssetSerializer.h>
- #include <AzCore/Serialization/SerializeContext.h>
- #include <AzFramework/Components/TransformComponent.h>
- #include <AzFramework/Entity/EntityContext.h>
- #include <AzFramework/Asset/SimpleAsset.h>
- #include <AzTest/AzTest.h>
- #include <AzToolsFramework/Application/ToolsApplication.h>
- #include <AzCore/UnitTest/TestTypes.h>
- #include <AzCore/StringFunc/StringFunc.h>
- #include <AzToolsFramework/PropertyTreeEditor/PropertyTreeEditor.h>
- #include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
- #include <AzToolsFramework/UnitTest/ToolsTestApplication.h>
- #include <QtTest/QtTest>
- #include <QApplication>
- namespace UnitTest
- {
- using namespace AzToolsFramework;
- struct PropertyTreeEditorSubBlockTester
- {
- AZ_TYPE_INFO(PropertyTreeEditorSubBlockTester, "{E9497A1E-9B41-4A33-8F05-92CE41A0ABD9}");
- AZ::s16 m_myNegativeShort = -42;
- };
- struct MockAssetData
- : public AZ::Data::AssetData
- {
- AZ_RTTI(MockAssetData, "{8B0A8DCA-7F29-4B8E-B5D7-08E0EAB2C900}", AZ::Data::AssetData);
- MockAssetData(const AZ::Data::AssetId& assetId)
- : AssetData(assetId)
- {
- // to skip the automatic removal from the asset system
- m_useCount = 2;
- }
- };
- class TestSimpleAsset
- {
- public:
- AZ_TYPE_INFO(TestSimpleAsset, "{10A39072-9287-49FE-93C8-55F7715FC758}");
- bool m_data = false;
- static const char* GetFileFilter()
- {
- return "*.NaN";
- }
- static void Reflect(AZ::ReflectContext* reflection)
- {
- AZ::SerializeContext* serializeContext = AZ::RttiCast<AZ::SerializeContext*>(reflection);
- if (serializeContext)
- {
- serializeContext->Class<TestSimpleAsset>()
- ->Version(0)
- ->Field("data", &TestSimpleAsset::m_data)
- ;
- AzFramework::SimpleAssetReference<TestSimpleAsset>::Register(*serializeContext);
- if (AZ::EditContext* editContext = serializeContext->GetEditContext())
- {
- editContext->Class<TestSimpleAsset>("TestSimpleAsset", "Test data block for a simple asset mock data block")
- ->DataElement(nullptr, &TestSimpleAsset::m_data, "My Data", "A test bool value.")
- ;
- }
- }
- }
- };
- //! Test class
- struct PropertyTreeEditorTester
- {
- AZ_TYPE_INFO(PropertyTreeEditorTester, "{D3E17BE6-0FEB-4A04-B8BE-105A4666E79F}");
- int m_myInt = 42;
- int m_myNewInt = 43;
- bool m_myBool = true;
- float m_myFloat = 42.0f;
- AZStd::string m_myString = "StringValue";
- AZStd::string m_myGroupedString = "GroupedStringValue";
- PropertyTreeEditorSubBlockTester m_mySubBlock;
- double m_myHiddenDouble = 42.0;
- AZ::u16 m_myReadOnlyShort = 42;
- AZ::Data::Asset<MockAssetData> m_myAssetData;
- AzFramework::SimpleAssetReference<TestSimpleAsset> m_myTestSimpleAsset;
- struct PropertyTreeEditorNestedTester
- {
- AZ_TYPE_INFO(PropertyTreeEditorNestedTester, "{F5814544-424D-41C5-A5AB-632371615B6A}");
- AZStd::string m_myNestedString = "NestedString";
- };
- AZStd::vector<PropertyTreeEditorNestedTester> m_myList;
- AZStd::unordered_map<AZStd::string, PropertyTreeEditorNestedTester> m_myMap;
- PropertyTreeEditorNestedTester m_nestedTester;
- PropertyTreeEditorNestedTester m_nestedTesterHiddenChildren;
- void Reflect(AZ::ReflectContext* context)
- {
- TestSimpleAsset::Reflect(context);
- if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
- {
- serializeContext->Class<PropertyTreeEditorSubBlockTester>()
- ->Version(0)
- ->Field("myNegativeShort", &PropertyTreeEditorSubBlockTester::m_myNegativeShort);
- serializeContext->Class<PropertyTreeEditorTester>()
- ->Version(1)
- ->Field("myInt", &PropertyTreeEditorTester::m_myInt)
- ->Field("myBool", &PropertyTreeEditorTester::m_myBool)
- ->Field("myFloat", &PropertyTreeEditorTester::m_myFloat)
- ->Field("myString", &PropertyTreeEditorTester::m_myString)
- ->Field("NestedTester", &PropertyTreeEditorTester::m_nestedTester)
- ->Field("myNewInt", &PropertyTreeEditorTester::m_myNewInt)
- ->Field("myGroupedString", &PropertyTreeEditorTester::m_myGroupedString)
- ->Field("myList", &PropertyTreeEditorTester::m_myList)
- ->Field("myMap", &PropertyTreeEditorTester::m_myMap)
- ->Field("mySubBlock", &PropertyTreeEditorTester::m_mySubBlock)
- ->Field("myHiddenDouble", &PropertyTreeEditorTester::m_myHiddenDouble)
- ->Field("myReadOnlyShort", &PropertyTreeEditorTester::m_myReadOnlyShort)
- ->Field("nestedTesterHiddenChildren", &PropertyTreeEditorTester::m_nestedTesterHiddenChildren)
- ->Field("myAssetData", &PropertyTreeEditorTester::m_myAssetData)
- ->Field("myTestSimpleAsset", &PropertyTreeEditorTester::m_myTestSimpleAsset)
- ;
- serializeContext->Class<PropertyTreeEditorNestedTester>()
- ->Version(1)
- ->Field("myNestedString", &PropertyTreeEditorNestedTester::m_myNestedString)
- ;
- if (AZ::EditContext* editContext = serializeContext->GetEditContext())
- {
- editContext->Class<PropertyTreeEditorSubBlockTester>(
- "PropertyTreeEditorSubBlock Tester", "Tester sub block for the PropertyTreeEditor test")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorSubBlockTester::m_myNegativeShort, "My Negative Short", "A test short int.")
- ;
- editContext->Class<PropertyTreeEditorTester>(
- "PropertyTreeEditor Tester", "Tester for the PropertyTreeEditor")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_myInt, "My Int", "A test int.")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_myBool, "My Bool", "A test bool.")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_myFloat, "My Float", "A test float.")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_myString, "My String", "A test string.")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_nestedTester, "Nested", "A nested class.")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_myNewInt, "My New Int", "A test int.", "My Old Int")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_myList, "My New List", "A test vector<>.", "My Old List")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_myMap, "My Map", "A test unordered_map<>.", "My Old Map")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_myAssetData, "My Asset Data", "An test asset data.")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_myTestSimpleAsset, "My Test Simple Asset", "A test simple asset ref.")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_myHiddenDouble, "My Hidden Double", "A test hidden node.", "My Old Double")
- ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Hide)
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_nestedTesterHiddenChildren, "Nested Hidden Children", "A test node with hidden children.")
- ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::HideChildren)
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_myReadOnlyShort, "My Read Only", "A test read only node.")
- ->Attribute(AZ::Edit::Attributes::ReadOnly, true)
- ->DataElement(nullptr, &PropertyTreeEditorTester::m_mySubBlock, "My Sub Block", "sub block test")
- ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
- ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
- ->ClassElement(AZ::Edit::ClassElements::Group, "Grouped")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorTester::m_myGroupedString, "My Grouped String", "A test grouped string.")
- ;
- editContext->Class<PropertyTreeEditorNestedTester>(
- "PropertyTreeEditor Nested Tester", "SubClass Tester for the PropertyTreeEditor")
- ->DataElement(AZ::Edit::UIHandlers::Default, &PropertyTreeEditorNestedTester::m_myNestedString, "My Nested String", "A test string.")
- ;
- }
- }
- }
- };
- class PropertyTreeEditorTests
- : public UnitTest::LeakDetectionFixture
- {
- public:
- void SetUp() override
- {
- AZ::ComponentApplication::StartupParameters startupParameters;
- startupParameters.m_loadSettingsRegistry = false;
- m_app.Start(AzFramework::Application::Descriptor(), startupParameters);
- // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
- // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
- // in the unit tests.
- AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
- }
- void TearDown() override
- {
- m_app.Stop();
- }
- ToolsTestApplication m_app{ "PropertyTreeEditorTests" };
- AZ::SerializeContext* m_serializeContext = nullptr;
- };
- TEST_F(PropertyTreeEditorTests, ReadPropertyTreeValues)
- {
- AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- PropertyTreeEditorTester propertyTreeEditorTester;
- propertyTreeEditorTester.Reflect(m_serializeContext);
- PropertyTreeEditor propertyTree = PropertyTreeEditor(&propertyTreeEditorTester, AZ::AzTypeInfo<PropertyTreeEditorTester>::Uuid());
- // Test existing properties of different types
- {
- PropertyTreeEditor::PropertyAccessOutcome boolOutcome = propertyTree.GetProperty("My Bool");
- EXPECT_TRUE(boolOutcome.IsSuccess());
- EXPECT_TRUE(AZStd::any_cast<bool>(boolOutcome.GetValue()));
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome intOutcome = propertyTree.GetProperty("My Int");
- EXPECT_TRUE(intOutcome.IsSuccess());
- EXPECT_EQ(AZStd::any_cast<int>(intOutcome.GetValue()), propertyTreeEditorTester.m_myInt);
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome floatOutcome = propertyTree.GetProperty("My Float");
- EXPECT_TRUE(floatOutcome.IsSuccess());
- EXPECT_FLOAT_EQ(AZStd::any_cast<float>(floatOutcome.GetValue()), propertyTreeEditorTester.m_myFloat);
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome stringOutcome = propertyTree.GetProperty("My String");
- EXPECT_TRUE(stringOutcome.IsSuccess());
- EXPECT_STREQ(AZStd::any_cast<AZStd::string>(stringOutcome.GetValue()).data(), propertyTreeEditorTester.m_myString.data());
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome nestedOutcome = propertyTree.GetProperty("Nested|My Nested String");
- EXPECT_TRUE(nestedOutcome.IsSuccess());
- EXPECT_STREQ(AZStd::any_cast<AZStd::string>(nestedOutcome.GetValue()).data(), propertyTreeEditorTester.m_nestedTester.m_myNestedString.data());
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome groupedOutcome = propertyTree.GetProperty("Grouped|My Grouped String");
- EXPECT_TRUE(groupedOutcome.IsSuccess());
- EXPECT_STREQ(AZStd::any_cast<AZStd::string>(groupedOutcome.GetValue()).data(), propertyTreeEditorTester.m_myGroupedString.data());
- }
- // Test non-existing properties
- {
- PropertyTreeEditor::PropertyAccessOutcome intOutcome = propertyTree.GetProperty("Wrong Property");
- EXPECT_FALSE(intOutcome.IsSuccess());
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome nestedOutcome = propertyTree.GetProperty("Nested|Wrong Nested Property");
- EXPECT_FALSE(nestedOutcome.IsSuccess());
- }
- {
- // Addressing the grouped property by name directly without the group should fail
- PropertyTreeEditor::PropertyAccessOutcome groupedOutcome = propertyTree.GetProperty("My Grouped String");
- EXPECT_FALSE(groupedOutcome.IsSuccess());
- }
- }
- TEST_F(PropertyTreeEditorTests, WritePropertyTreeValues)
- {
- AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- PropertyTreeEditorTester propertyTreeEditorTester;
- propertyTreeEditorTester.Reflect(m_serializeContext);
- PropertyTreeEditor propertyTree = PropertyTreeEditor(&propertyTreeEditorTester, AZ::AzTypeInfo<PropertyTreeEditorTester>::Uuid());
- // Test existing properties of different types
- {
- PropertyTreeEditor::PropertyAccessOutcome boolOutcomeSet = propertyTree.SetProperty("My Bool", AZStd::any(false));
- EXPECT_TRUE(boolOutcomeSet.IsSuccess());
- PropertyTreeEditor::PropertyAccessOutcome boolOutcomeGet = propertyTree.GetProperty("My Bool");
- EXPECT_TRUE(boolOutcomeGet.IsSuccess());
- EXPECT_FALSE(AZStd::any_cast<bool>(boolOutcomeGet.GetValue()));
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome intOutcomeSet = propertyTree.SetProperty("My Int", AZStd::any(48));
- EXPECT_TRUE(intOutcomeSet.IsSuccess());
- PropertyTreeEditor::PropertyAccessOutcome intOutcomeGet = propertyTree.GetProperty("My Int");
- EXPECT_TRUE(intOutcomeGet.IsSuccess());
- EXPECT_EQ(AZStd::any_cast<int>(intOutcomeGet.GetValue()), AZStd::any_cast<int>(intOutcomeSet.GetValue()));
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome floatOutcomeSet = propertyTree.SetProperty("My Float", AZStd::any(48.0f));
- EXPECT_TRUE(floatOutcomeSet.IsSuccess());
- PropertyTreeEditor::PropertyAccessOutcome floatOutcomeGet = propertyTree.GetProperty("My Float");
- EXPECT_TRUE(floatOutcomeGet.IsSuccess());
- EXPECT_FLOAT_EQ(AZStd::any_cast<float>(floatOutcomeGet.GetValue()), AZStd::any_cast<float>(floatOutcomeSet.GetValue()));
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome stringOutcomeSet = propertyTree.SetProperty("My String", AZStd::make_any<AZStd::string>("New Value"));
- EXPECT_TRUE(stringOutcomeSet.IsSuccess());
- PropertyTreeEditor::PropertyAccessOutcome stringOutcomeGet = propertyTree.GetProperty("My String");
- EXPECT_TRUE(stringOutcomeGet.IsSuccess());
- EXPECT_STREQ(AZStd::any_cast<AZStd::string>(stringOutcomeSet.GetValue()).data(), AZStd::any_cast<AZStd::string>(stringOutcomeGet.GetValue()).data());
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome stringOutcomeSet = propertyTree.SetProperty("Nested|My Nested String", AZStd::make_any<AZStd::string>("New Nested Value"));
- EXPECT_TRUE(stringOutcomeSet.IsSuccess());
- PropertyTreeEditor::PropertyAccessOutcome stringOutcomeGet = propertyTree.GetProperty("Nested|My Nested String");
- EXPECT_TRUE(stringOutcomeGet.IsSuccess());
- EXPECT_STREQ(AZStd::any_cast<AZStd::string>(stringOutcomeSet.GetValue()).data(), AZStd::any_cast<AZStd::string>(stringOutcomeGet.GetValue()).data());
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome stringOutcomeSet = propertyTree.SetProperty("Grouped|My Grouped String", AZStd::make_any<AZStd::string>("New Grouped Value"));
- EXPECT_TRUE(stringOutcomeSet.IsSuccess());
- PropertyTreeEditor::PropertyAccessOutcome stringOutcomeGet = propertyTree.GetProperty("Grouped|My Grouped String");
- EXPECT_TRUE(stringOutcomeGet.IsSuccess());
- EXPECT_STREQ(AZStd::any_cast<AZStd::string>(stringOutcomeSet.GetValue()).data(), AZStd::any_cast<AZStd::string>(stringOutcomeGet.GetValue()).data());
- }
- // Test non-existing properties
- {
- PropertyTreeEditor::PropertyAccessOutcome intOutcome = propertyTree.SetProperty("Wrong Property", AZStd::any(12));
- EXPECT_FALSE(intOutcome.IsSuccess());
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome nestedOutcome = propertyTree.SetProperty("Nested|Wrong Nested Property", AZStd::make_any<AZStd::string>("Some Value"));
- EXPECT_FALSE(nestedOutcome.IsSuccess());
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome groupedOutcome = propertyTree.SetProperty("Grouped|Wrong Grouped Property", AZStd::make_any<AZStd::string>("Some Value"));
- EXPECT_FALSE(groupedOutcome.IsSuccess());
- }
- {
- // Addressing the grouped property by name directly without the group should fail
- PropertyTreeEditor::PropertyAccessOutcome groupedOutcome = propertyTree.SetProperty("My Grouped String", AZStd::make_any<AZStd::string>("Some Value"));
- EXPECT_FALSE(groupedOutcome.IsSuccess());
- }
- // Test existing properties with wrong type
- {
- PropertyTreeEditor::PropertyAccessOutcome intOutcome = propertyTree.SetProperty("My Int", AZStd::any(12.0f));
- EXPECT_FALSE(intOutcome.IsSuccess());
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome nestedOutcome = propertyTree.SetProperty("Nested|My Nested String", AZStd::any(42.0f));
- EXPECT_FALSE(nestedOutcome.IsSuccess());
- }
- {
- PropertyTreeEditor::PropertyAccessOutcome groupedOutcome = propertyTree.SetProperty("Grouped|My Grouped String", AZStd::any(42.0f));
- EXPECT_FALSE(groupedOutcome.IsSuccess());
- }
- }
- TEST_F(PropertyTreeEditorTests, PropertyTreeVectorContainerSupport)
- {
- AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- PropertyTreeEditorTester propertyTreeEditorTester;
- propertyTreeEditorTester.Reflect(m_serializeContext);
- PropertyTreeEditor propertyTree = PropertyTreeEditor(&propertyTreeEditorTester, AZ::AzTypeInfo<PropertyTreeEditorTester>::Uuid());
- // IsContainer
- {
- EXPECT_FALSE(propertyTree.IsContainer("My New Int"));
- EXPECT_TRUE(propertyTree.IsContainer("My New List"));
- }
- // AddContainerItem
- {
- AZStd::any key = AZStd::make_any<AZ::s32>(0);
- AZStd::any value = AZStd::make_any<PropertyTreeEditorTester::PropertyTreeEditorNestedTester>();
- PropertyTreeEditor::PropertyAccessOutcome outcomeAdd0 = propertyTree.AddContainerItem("My New Int", key, value);
- EXPECT_FALSE(outcomeAdd0.IsSuccess());
- PropertyTreeEditor::PropertyAccessOutcome outcomeAdd1 = propertyTree.AddContainerItem("My New List", key, value);
- EXPECT_TRUE(outcomeAdd1.IsSuccess());
- }
- // GetContainerCount
- {
- EXPECT_FALSE(propertyTree.GetContainerCount("My New Int").IsSuccess());
- EXPECT_EQ(1, AZStd::any_cast<AZ::u64>(propertyTree.GetContainerCount("My New List").GetValue()));
- }
- // GetContainerItem
- {
- AZStd::any key = AZStd::make_any<AZ::s32>(0);
- AZStd::any keyString = AZStd::make_any<AZStd::string_view>("0");
- EXPECT_FALSE(propertyTree.GetContainerItem("My New Int", key).IsSuccess());
- AZ_TEST_START_TRACE_SUPPRESSION;
- EXPECT_FALSE(propertyTree.GetContainerItem("My New List", keyString).IsSuccess());
- AZ_TEST_STOP_TRACE_SUPPRESSION(1);
- PropertyTreeEditor::PropertyAccessOutcome outcome = propertyTree.GetContainerItem("My New List", key);
- EXPECT_TRUE(outcome.IsSuccess());
- if (outcome.IsSuccess())
- {
- auto&& testerValue = AZStd::any_cast<PropertyTreeEditorTester::PropertyTreeEditorNestedTester>(&outcome.GetValue());
- EXPECT_STREQ("NestedString", testerValue->m_myNestedString.c_str());
- }
- }
- // UpdateContainerItem
- {
- AZStd::any key = AZStd::make_any<AZ::s32>(0);
- AZStd::any keyString = AZStd::make_any<AZStd::string_view>("0");
- PropertyTreeEditorTester::PropertyTreeEditorNestedTester testUpdate;
- testUpdate.m_myNestedString = "a new value";
- AZStd::any value = AZStd::make_any<PropertyTreeEditorTester::PropertyTreeEditorNestedTester>(testUpdate);
- EXPECT_FALSE(propertyTree.UpdateContainerItem("My New Int", key, value).IsSuccess());
- AZ_TEST_START_TRACE_SUPPRESSION;
- EXPECT_FALSE(propertyTree.UpdateContainerItem("My New List", keyString, value).IsSuccess());
- AZ_TEST_STOP_TRACE_SUPPRESSION(1);
- EXPECT_TRUE(propertyTree.UpdateContainerItem("My New List", key, value).IsSuccess());
- PropertyTreeEditor::PropertyAccessOutcome outcome = propertyTree.GetContainerItem("My New List", key);
- EXPECT_TRUE(outcome.IsSuccess());
- if (outcome.IsSuccess())
- {
- auto&& testerValue = AZStd::any_cast<PropertyTreeEditorTester::PropertyTreeEditorNestedTester>(&outcome.GetValue());
- EXPECT_STREQ(testUpdate.m_myNestedString.c_str(), testerValue->m_myNestedString.c_str());
- }
- }
- // RemoveContainerItem
- {
- AZStd::any key = AZStd::make_any<AZ::s32>(0);
- AZStd::any keyString = AZStd::make_any<AZStd::string_view>("0");
- EXPECT_FALSE(propertyTree.RemoveContainerItem("My New Int", key).IsSuccess());
- AZ_TEST_START_TRACE_SUPPRESSION;
- EXPECT_FALSE(propertyTree.RemoveContainerItem("My New List", keyString).IsSuccess());
- AZ_TEST_STOP_TRACE_SUPPRESSION(1);
- PropertyTreeEditor::PropertyAccessOutcome outcomeAdd1 = propertyTree.RemoveContainerItem("My New List", key);
- EXPECT_TRUE(outcomeAdd1.IsSuccess());
- EXPECT_EQ(0, AZStd::any_cast<AZ::u64>(propertyTree.GetContainerCount("My New List").GetValue()));
- }
- // ResetContainer
- {
- AZStd::any value = AZStd::make_any<PropertyTreeEditorTester::PropertyTreeEditorNestedTester>();
- propertyTree.AddContainerItem("My New List", AZStd::make_any<AZ::s32>(0), value);
- propertyTree.AddContainerItem("My New List", AZStd::make_any<AZ::s32>(1), value);
- propertyTree.AddContainerItem("My New List", AZStd::make_any<AZ::s32>(2), value);
- EXPECT_EQ(3, AZStd::any_cast<AZ::u64>(propertyTree.GetContainerCount("My New List").GetValue()));
- propertyTree.ResetContainer("My New List");
- EXPECT_EQ(0, AZStd::any_cast<AZ::u64>(propertyTree.GetContainerCount("My New List").GetValue()));
- }
- // AppendContainerItem
- {
- AZStd::any value = AZStd::make_any<PropertyTreeEditorTester::PropertyTreeEditorNestedTester>();
- EXPECT_TRUE(propertyTree.AppendContainerItem("My New List", value).IsSuccess());
- EXPECT_TRUE(propertyTree.AppendContainerItem("My New List", value).IsSuccess());
- EXPECT_TRUE(propertyTree.AppendContainerItem("My New List", value).IsSuccess());
- EXPECT_EQ(3, AZStd::any_cast<AZ::u64>(propertyTree.GetContainerCount("My New List").GetValue()));
- propertyTree.ResetContainer("My New List");
- }
- }
- TEST_F(PropertyTreeEditorTests, PropertyTreeUnorderedMapContainerSupport)
- {
- AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- using TestData = PropertyTreeEditorTester::PropertyTreeEditorNestedTester;
- PropertyTreeEditorTester propertyTreeEditorTester;
- propertyTreeEditorTester.Reflect(m_serializeContext);
- propertyTreeEditorTester.m_myMap.emplace(AZStd::make_pair("one", TestData()));
- const char* testDataString = "a test string";
- PropertyTreeEditor propertyTree = PropertyTreeEditor(&propertyTreeEditorTester, AZ::AzTypeInfo<PropertyTreeEditorTester>::Uuid());
- // AddContainerItem
- {
- AZStd::any key = AZStd::make_any<AZStd::string>("two");
- TestData testItem;
- testItem.m_myNestedString = testDataString;
- AZStd::any value = AZStd::make_any<TestData>(testItem);
- EXPECT_TRUE(propertyTree.AddContainerItem("My Map", key, value).IsSuccess());
- }
- // GetContainerCount
- {
- EXPECT_EQ(2, AZStd::any_cast<AZ::u64>(propertyTree.GetContainerCount("My Map").GetValue()));
- }
- // GetContainerItem
- {
- AZStd::any key = AZStd::make_any<AZStd::string>("two");
- PropertyTreeEditor::PropertyAccessOutcome outcome = propertyTree.GetContainerItem("My Map", key);
- EXPECT_TRUE(outcome.IsSuccess());
- if (outcome.IsSuccess())
- {
- auto&& testerValue = AZStd::any_cast<TestData>(&outcome.GetValue());
- EXPECT_STREQ(testDataString, testerValue->m_myNestedString.c_str());
- }
- }
- // UpdateContainerItem
- {
- AZStd::any key = AZStd::make_any<AZStd::string>("two");
- TestData testUpdate;
- testUpdate.m_myNestedString = "a new value";
- AZStd::any value = AZStd::make_any<TestData>(testUpdate);
- EXPECT_TRUE(propertyTree.UpdateContainerItem("My Map", key, value).IsSuccess());
- PropertyTreeEditor::PropertyAccessOutcome outcome = propertyTree.GetContainerItem("My Map", key);
- if (outcome.IsSuccess())
- {
- auto&& testerValue = AZStd::any_cast<PropertyTreeEditorTester::PropertyTreeEditorNestedTester>(&outcome.GetValue());
- EXPECT_STREQ(testUpdate.m_myNestedString.c_str(), testerValue->m_myNestedString.c_str());
- }
- }
- // RemoveContainerItem
- {
- AZStd::any key = AZStd::make_any<AZStd::string>("two");
- EXPECT_TRUE(propertyTree.RemoveContainerItem("My Map", key).IsSuccess());
- EXPECT_EQ(1, AZStd::any_cast<AZ::u64>(propertyTree.GetContainerCount("My Map").GetValue()));
- }
- // ResetContainer
- {
- EXPECT_EQ(1, AZStd::any_cast<AZ::u64>(propertyTree.GetContainerCount("My Map").GetValue()));
- propertyTree.ResetContainer("My Map");
- EXPECT_EQ(0, AZStd::any_cast<AZ::u64>(propertyTree.GetContainerCount("My Map").GetValue()));
- }
- // AppendContainerItem
- {
- AZStd::any value = AZStd::make_any<PropertyTreeEditorTester::PropertyTreeEditorNestedTester>();
- EXPECT_FALSE(propertyTree.AppendContainerItem("My Map", value).IsSuccess());
- EXPECT_EQ(0, AZStd::any_cast<AZ::u64>(propertyTree.GetContainerCount("My Map").GetValue()));
- }
- }
- TEST_F(PropertyTreeEditorTests, PropertyTreeInspection)
- {
- AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- PropertyTreeEditorTester propertyTreeEditorTester;
- propertyTreeEditorTester.Reflect(m_serializeContext);
- PropertyTreeEditor propertyTree = PropertyTreeEditor(&propertyTreeEditorTester, AZ::AzTypeInfo<PropertyTreeEditorTester>::Uuid());
- // BuildPathsList
- {
- auto&& pathList = propertyTree.BuildPathsList();
- EXPECT_TRUE(!pathList.empty());
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "My Map"; }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "My New List"; }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "Nested|My Nested String"; }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "Grouped|My Grouped String"; }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "My Hidden Double"; }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "My Sub Block|My Negative Short"; }));
- }
- // BuildPathsListWithTypes
- {
- [[maybe_unused]] static auto stringContains = [](const AZStd::string& data, const char* subString) -> bool
- {
- return data.find(subString) != AZStd::string::npos;
- };
- auto&& pathList = propertyTree.BuildPathsListWithTypes();
- EXPECT_TRUE(!pathList.empty());
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return stringContains(path,"NotVisible"); }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return stringContains(path,"Visible"); }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return stringContains(path,"ShowChildrenOnly"); }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return stringContains(path,"HideChildren"); }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return stringContains(path,"ReadOnly"); }));
- }
- // GetPropertyType
- {
- EXPECT_TRUE(propertyTree.GetPropertyType("My Map").starts_with("AZStd::unordered_map"));
- EXPECT_TRUE(propertyTree.GetPropertyType("My New List").starts_with("AZStd::vector"));
- EXPECT_EQ("AZStd::string", propertyTree.GetPropertyType("Nested|My Nested String"));
- EXPECT_EQ("double", propertyTree.GetPropertyType("My Hidden Double"));
- EXPECT_EQ("PropertyTreeEditorNestedTester", propertyTree.GetPropertyType("Nested"));
- }
- // BuildPathsList after enforcement removes the "show children only" nodes from the paths
- {
- propertyTree.SetVisibleEnforcement(true);
- auto&& pathList = propertyTree.BuildPathsList();
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "My Map"; }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "My New List"; }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "Nested|My Nested String"; }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "Grouped|My Grouped String"; }));
- EXPECT_FALSE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "My Hidden Double"; }));
- EXPECT_FALSE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "My Sub Block|My Negative Short"; }));
- EXPECT_TRUE(AZStd::any_of(pathList.begin(), pathList.end(), [](auto&& path) { return path == "My Negative Short"; }));
- }
- }
- TEST_F(PropertyTreeEditorTests, PropertyTreeAttributeInspection)
- {
- AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- PropertyTreeEditorTester propertyTreeEditorTester;
- propertyTreeEditorTester.Reflect(m_serializeContext);
- PropertyTreeEditor propertyTree = PropertyTreeEditor(&propertyTreeEditorTester, AZ::AzTypeInfo<PropertyTreeEditorTester>::Uuid());
- // HasAttribute
- {
- EXPECT_TRUE(propertyTree.HasAttribute("My Read Only", "ReadOnly"));
- EXPECT_TRUE(propertyTree.HasAttribute("My Hidden Double", "Visibility"));
- EXPECT_TRUE(propertyTree.HasAttribute("My Sub Block", "AutoExpand"));
- }
- }
- TEST_F(PropertyTreeEditorTests, HandlesVisibleEnforcement)
- {
- AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- PropertyTreeEditorTester propertyTreeEditorTester;
- propertyTreeEditorTester.Reflect(m_serializeContext);
- PropertyTreeEditor propertyTree = PropertyTreeEditor(&propertyTreeEditorTester, AZ::AzTypeInfo<PropertyTreeEditorTester>::Uuid());
- // can access a hidden value with 'visible enforcement' set to false
- {
- PropertyTreeEditor::PropertyAccessOutcome outcomeGet = propertyTree.GetProperty("My Hidden Double");
- EXPECT_TRUE(outcomeGet.IsSuccess());
- EXPECT_EQ(42.0, AZStd::any_cast<double>(outcomeGet.GetValue()));
- }
- // can mutate a hidden value with 'visible enforcement' set to false
- {
- PropertyTreeEditor::PropertyAccessOutcome outcomeSet = propertyTree.SetProperty("My Hidden Double", AZStd::any(12.0));
- EXPECT_TRUE(outcomeSet.IsSuccess());
- PropertyTreeEditor::PropertyAccessOutcome outcomeGet = propertyTree.GetProperty("My Hidden Double");
- EXPECT_TRUE(outcomeGet.IsSuccess());
- EXPECT_EQ(12.0, AZStd::any_cast<double>(outcomeGet.GetValue()));
- }
- propertyTree.SetVisibleEnforcement(true);
- // can NOT access hidden value with 'visible enforcement' set to true
- {
- PropertyTreeEditor::PropertyAccessOutcome outcomeGet = propertyTree.GetProperty("My Hidden Double");
- EXPECT_FALSE(outcomeGet.IsSuccess());
- }
- // can NOT mutate a hidden value with 'visible enforcement' set to false
- {
- PropertyTreeEditor::PropertyAccessOutcome outcomeSet = propertyTree.SetProperty("My Hidden Double", AZStd::any(42.0));
- EXPECT_FALSE(outcomeSet.IsSuccess());
- }
- }
- TEST_F(PropertyTreeEditorTests, PropertyTreeDeprecatedNamesSupport)
- {
- AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- PropertyTreeEditorTester propertyTreeEditorTester;
- propertyTreeEditorTester.Reflect(m_serializeContext);
- PropertyTreeEditor propertyTree = PropertyTreeEditor(&propertyTreeEditorTester, AZ::AzTypeInfo<PropertyTreeEditorTester>::Uuid());
- // Test that new and deprecated name both refer to the same property
- {
- int newIntValue = 0;
- // get current value of My New Int
- PropertyTreeEditor::PropertyAccessOutcome intOutcomeGet = propertyTree.GetProperty("My New Int");
- EXPECT_TRUE(intOutcomeGet.IsSuccess());
- newIntValue = AZStd::any_cast<int>(intOutcomeGet.GetValue());
- // Set new value to My Old Int
- PropertyTreeEditor::PropertyAccessOutcome intOutcomeSet = propertyTree.SetProperty("My Old Int", AZStd::any(12));
- EXPECT_TRUE(intOutcomeSet.IsSuccess());
- // Read value of My New Int again
- PropertyTreeEditor::PropertyAccessOutcome intOutcomeGetAgain = propertyTree.GetProperty("My New Int");
- EXPECT_TRUE(intOutcomeGetAgain.IsSuccess());
- // Verify that My Old Int and My New Int refer to the same property
- EXPECT_TRUE(AZStd::any_cast<int>(intOutcomeGetAgain.GetValue()) != newIntValue);
- }
- }
- TEST_F(PropertyTreeEditorTests, ClearWithEmptyAny)
- {
- AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- AZ::Data::AssetId mockAssetId = AZ::Data::AssetId::CreateString("{66CC8A20-DC4D-4856-95FE-5C75A47B6A21}:0");
- MockAssetData mockAssetData(mockAssetId);
- AZ::Data::Asset<MockAssetData> mockAsset(&mockAssetData, AZ::Data::AssetLoadBehavior::Default);
- AzFramework::SimpleAssetReference<TestSimpleAsset> mockSimpleAsset;
- mockSimpleAsset.SetAssetPath("path/to/42");
- PropertyTreeEditorTester propertyTreeEditorTester;
- propertyTreeEditorTester.Reflect(m_serializeContext);
- propertyTreeEditorTester.m_myInt = 42;
- propertyTreeEditorTester.m_mySubBlock.m_myNegativeShort = -42;
- propertyTreeEditorTester.m_myList.push_back({});
- propertyTreeEditorTester.m_myAssetData = AZStd::move(mockAsset);
- propertyTreeEditorTester.m_myTestSimpleAsset = mockSimpleAsset;
- PropertyTreeEditor propertyTree(&propertyTreeEditorTester, AZ::AzTypeInfo<PropertyTreeEditorTester>::Uuid());
- propertyTree.SetVisibleEnforcement(true);
- // use an empty any<> to set properties back to a default value
- {
- AZStd::any anEmpty;
- EXPECT_TRUE(propertyTree.SetProperty("My Int", anEmpty).IsSuccess());
- EXPECT_TRUE(propertyTree.SetProperty("My Negative Short", anEmpty).IsSuccess());
- EXPECT_TRUE(propertyTree.SetProperty("My New List", anEmpty).IsSuccess());
- AZ_TEST_START_TRACE_SUPPRESSION;
- EXPECT_TRUE(propertyTree.SetProperty("My Asset Data", anEmpty).IsSuccess());
- AZ_TEST_STOP_TRACE_SUPPRESSION(1);
- EXPECT_TRUE(propertyTree.SetProperty("My Test Simple Asset", anEmpty).IsSuccess());
- }
- // check that the properties went back to default values
- {
- EXPECT_EQ(0, propertyTreeEditorTester.m_myInt);
- EXPECT_EQ(0, propertyTreeEditorTester.m_mySubBlock.m_myNegativeShort);
- EXPECT_TRUE(propertyTreeEditorTester.m_myList.empty());
- EXPECT_FALSE(propertyTreeEditorTester.m_myAssetData.GetId().IsValid());
- EXPECT_TRUE(propertyTreeEditorTester.m_myTestSimpleAsset.GetAssetPath().empty());
- }
- }
- } // namespace UnitTest
|