/* * 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 namespace StandaloneRPE { void Button1() { QMessageBox::information(nullptr, "Button", "Button1 pressed"); } void Button2() { QMessageBox::information(nullptr, "Button", "Button2 pressed"); } class TestContainer { public: AZ_TYPE_INFO(TestContainer, "{86586583-A58F-45FD-BB6E-C3E9C76DDA38}"); AZ_CLASS_ALLOCATOR(TestContainer, AZ::SystemAllocator, 0); enum class EnumType : AZ::u8 { Value1 = 1, Value2 = 2, ValueZ = 10, NotReflected = 0xFF }; AZStd::map m_map; AZStd::unordered_map, int> m_unorderedMap; AZStd::unordered_map m_simpleEnum; AZStd::unordered_map m_immutableEnum; AZStd::set m_set; AZStd::unordered_set m_unorderedSet; AZStd::unordered_multimap m_multiMap; AZStd::unordered_map> m_nestedMap; AZStd::unordered_map m_entityIdMap; EnumType m_enumValue = EnumType::Value1; AZ::EntityId m_entityId; static void Reflect(AZ::ReflectContext* context) { if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() ->Field("map", &TestContainer::m_map) ->Field("unorderedMap", &TestContainer::m_unorderedMap) ->Field("simpleEnum", &TestContainer::m_simpleEnum) ->Field("immutableEnum", &TestContainer::m_immutableEnum) ->Field("set", &TestContainer::m_set) ->Field("unorderedSet", &TestContainer::m_unorderedSet) ->Field("multiMap", &TestContainer::m_multiMap) ->Field("nestedMap", &TestContainer::m_nestedMap) ->Field("entityIdMap", &TestContainer::m_entityIdMap) ->Field("enumValue", &TestContainer::m_enumValue) ->Field("entityId", &TestContainer::m_entityId); if (auto editContext = serializeContext->GetEditContext()) { editContext->Enum("EnumType", "") ->Value("Value1", EnumType::Value1) ->Value("Value2", EnumType::Value2) ->Value("ValueZ", EnumType::ValueZ); editContext->Class("TestContainer", "") ->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_map, "map", "") ->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_unorderedMap, "unordered_map, int>", "") ->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_simpleEnum, "unordered_map", "") ->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_immutableEnum, "unordered_map (fixed contents)", "") ->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false) ->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_set, "set", "") ->ElementAttribute(AZ::Edit::UIHandlers::Handler, AZ::Edit::UIHandlers::Slider) ->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_unorderedSet, "unordered_set", "") ->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_multiMap, "unordered_multimap", "") ->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_nestedMap, "unordered_map>", "") ->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_entityIdMap, "unordered_map", "") ->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_enumValue, "enum (no multi-edit)", "") ->Attribute(AZ::Edit::Attributes::AcceptsMultiEdit, false) ->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_entityId, "entityId", "") ->UIElement(AZ::Edit::UIHandlers::Button, "") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &Button1) ->Attribute(AZ::Edit::Attributes::ButtonText, "Button1 (no multi-edit)") ->UIElement(AZ::Edit::UIHandlers::Button, "") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &Button2) ->Attribute(AZ::Edit::Attributes::ButtonText, "Button2 (multi-edit)") ->Attribute(AZ::Edit::Attributes::AcceptsMultiEdit, true); } } } }; class SimpleKeyedContainer { public: AZ_TYPE_INFO(SimpleKeyedContainer, "{54E1AA90-1C09-47F4-8836-91600F225A34}"); AZ_CLASS_ALLOCATOR(SimpleKeyedContainer, AZ::SystemAllocator, 0); AZStd::vector> m_map; static void Reflect(AZ::ReflectContext* context) { if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() ->Field("map", &SimpleKeyedContainer::m_map); if (auto editContext = serializeContext->GetEditContext()) { editContext->Class("SimpleKeyContainer", "") ->DataElement(nullptr, &SimpleKeyedContainer::m_map, "map", "") ->ElementAttribute(AZ::Edit::Attributes::ShowAsKeyValuePairs, true); } } } }; } // StandaloneRPE namespace AZ { AZ_TYPE_INFO_SPECIALIZE(StandaloneRPE::TestContainer::EnumType, "{14B71D68-2CEE-445C-A359-CAA16FB647DF}"); } namespace StandaloneRPE { class RPEApplication : public AzToolsFramework::ToolsApplication { public: RPEApplication(int* argc = nullptr, char*** argv = nullptr) : AzToolsFramework::ToolsApplication(argc, argv) {} void Reflect(AZ::ReflectContext* context) override { AzToolsFramework::ToolsApplication::Reflect(context); TestContainer::Reflect(context); SimpleKeyedContainer::Reflect(context); } }; } // StandaloneRPE int main(int argc, char** argv) { AZ::IO::FixedMaxPath engineRootPath; { AZ::ComponentApplication componentApplication(argc, argv); auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder); } AzQtComponents::PrepareQtPaths(); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); QApplication qtApp(argc, argv); AzQtComponents::StyleManager styleManager(&qtApp); styleManager.initialize(&qtApp, engineRootPath); StandaloneRPE::RPEApplication app(&argc, &argv); app.Start(AzFramework::Application::Descriptor()); auto serializeContext = app.GetSerializeContext(); AZStd::list testContainers; AzToolsFramework::ReflectedPropertyEditor* editor = new AzToolsFramework::ReflectedPropertyEditor(nullptr); editor->setAttribute(Qt::WA_DeleteOnClose); editor->Setup(serializeContext, nullptr, true); float newValue = 0.f; QPushButton* addInstanceButton = new QPushButton("Add Multi-Edit Instance"); QPushButton* clearInstancesButton = new QPushButton("Clear Multi-Edit Instances"); auto addInstance = [&]() { testContainers.emplace_back(); StandaloneRPE::TestContainer& tc = testContainers.back(); auto& m = tc.m_nestedMap[StandaloneRPE::TestContainer::EnumType::Value1]; m[1] = 2; m[2] = 3; tc.m_immutableEnum[StandaloneRPE::TestContainer::EnumType::Value1] = 1.0; tc.m_immutableEnum[StandaloneRPE::TestContainer::EnumType::Value2] = 2.0; tc.m_immutableEnum[StandaloneRPE::TestContainer::EnumType::ValueZ] = 999.0; tc.m_map["A"] = 2.f + newValue; tc.m_map["B"] = 1.f; tc.m_map["C"] = -1.f; newValue += 1.f; void* aggregateInstance = nullptr; void* compareInstance = nullptr; if (testContainers.size() > 1) { aggregateInstance = &testContainers.front(); } editor->AddInstance(&tc, azrtti_typeid(), aggregateInstance, compareInstance); editor->InvalidateAll(); editor->ExpandAll(); clearInstancesButton->setEnabled(testContainers.size() > 1); }; addInstance(); auto clearInstances = [&]() { auto& tc = testContainers.back(); editor->ClearInstances(); editor->AddInstance(&tc, azrtti_typeid()); editor->InvalidateAll(); editor->ExpandAll(); while (testContainers.size() > 1) { testContainers.pop_front(); } clearInstancesButton->setEnabled(false); }; QObject::connect(addInstanceButton, &QPushButton::clicked, addInstance); QObject::connect(clearInstancesButton, &QPushButton::clicked, clearInstances); QWidget* containerWidget = new QWidget; QVBoxLayout* containerLayout = new QVBoxLayout(containerWidget); containerLayout->addWidget(editor); containerLayout->addWidget(addInstanceButton); containerLayout->addWidget(clearInstancesButton); containerWidget->resize(800, 600); containerWidget->show(); return qtApp.exec(); }