Files
o3de/Code/Framework/AzQtComponents/AzQtComponents/PropertyEditorStandalone/main.cpp
T

267 lines
11 KiB
C++

/*
* 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 <AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx>
#include <AzToolsFramework/Application/ToolsApplication.h>
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
#include <AzQtComponents/Components/O3DEStylesheet.h>
#include <AzQtComponents/Utilities/QtPluginPaths.h>
#include <AzQtComponents/Utilities/HandleDpiAwareness.h>
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/Component/EntityId.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/set.h>
#include <AzCore/std/containers/unordered_set.h>
#include <QDialog>
#include <QVBoxLayout>
#include <QApplication>
#include <QPushButton>
#include <QMessageBox>
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<AZStd::string, float> m_map;
AZStd::unordered_map<AZStd::pair<int, double>, int> m_unorderedMap;
AZStd::unordered_map<EnumType, int> m_simpleEnum;
AZStd::unordered_map<EnumType, double> m_immutableEnum;
AZStd::set<int> m_set;
AZStd::unordered_set<EnumType> m_unorderedSet;
AZStd::unordered_multimap<int, AZStd::string> m_multiMap;
AZStd::unordered_map<EnumType, AZStd::unordered_map<int, int>> m_nestedMap;
AZStd::unordered_map<AZ::EntityId, int> m_entityIdMap;
EnumType m_enumValue = EnumType::Value1;
AZ::EntityId m_entityId;
static void Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<TestContainer>()
->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>("EnumType", "")
->Value("Value1", EnumType::Value1)
->Value("Value2", EnumType::Value2)
->Value("ValueZ", EnumType::ValueZ);
editContext->Class<TestContainer>("TestContainer", "")
->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_map, "map<string, float>", "")
->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_unorderedMap, "unordered_map<pair<int, double>, int>", "")
->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_simpleEnum, "unordered_map<enum, int>", "")
->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_immutableEnum, "unordered_map<enum, double> (fixed contents)", "")
->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false)
->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_set, "set<int>", "")
->ElementAttribute(AZ::Edit::UIHandlers::Handler, AZ::Edit::UIHandlers::Slider)
->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_unorderedSet, "unordered_set<enum>", "")
->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_multiMap, "unordered_multimap<int, string>", "")
->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_nestedMap, "unordered_map<enum, unordered_map<int, int>>", "")
->DataElement(AZ::Edit::UIHandlers::Default, &TestContainer::m_entityIdMap, "unordered_map<EntityId, Number>", "")
->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<AZStd::pair<int, int>> m_map;
static void Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<SimpleKeyedContainer>()
->Field("map", &SimpleKeyedContainer::m_map);
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<SimpleKeyedContainer>("SimpleKeyContainer", "")
->DataElement(0, &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<StandaloneRPE::TestContainer> 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<StandaloneRPE::TestContainer>(), 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<StandaloneRPE::TestContainer>());
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();
}