Переглянути джерело

ComponentAdapter PR (#12130)

* valueHashed attribute to identify property changes in pointer/opaque types

Signed-off-by: Daniel Tamkin <[email protected]>

* Removed external refresh logic

Signed-off-by: Daniel Tamkin <[email protected]>

* ComponentAdapter

Signed-off-by: Daniel Tamkin <[email protected]>

* Fixed Refresh Attributes and bus disconnects

Signed-off-by: Daniel Tamkin <[email protected]>

* Address comments, renamed file

Signed-off-by: Daniel Tamkin <[email protected]>

* Default value for m_valueSize

Signed-off-by: Daniel Tamkin <[email protected]>

Signed-off-by: Daniel Tamkin <[email protected]>
Daniel Tamkin 2 роки тому
батько
коміт
40e23c52b4

+ 3 - 0
Code/Framework/AzCore/AzCore/std/any.h

@@ -83,6 +83,8 @@ namespace AZStd
             bool m_isPointer = false;
             // Should the object be stored on the heap? (never true for pointers)
             bool m_useHeap = false;
+            // The size of the value stored by this type
+            size_t m_valueSize = 0;
         };
 
         /// Constructs an empty object.
@@ -374,6 +376,7 @@ namespace AZStd
             ti.m_id = azrtti_typeid<ValueType>();
             ti.m_isPointer = is_pointer<ValueType>::value;
             ti.m_useHeap = AZStd::GetMax(sizeof(ValueType), AZStd::alignment_of<ValueType>::value) > Internal::ANY_SBO_BUF_SIZE;
+            ti.m_valueSize = sizeof(AZStd::decay_t<AZStd::remove_pointer_t<ValueType>>);
             ti.m_handler = type_info::HandleFnT(&action_handler<ValueType>);
             return ti;
         }

+ 1 - 0
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/PropertyEditorNodes.cpp

@@ -62,6 +62,7 @@ namespace AZ::DocumentPropertyEditor::Nodes
         system->RegisterNodeAttribute<PropertyEditor>(PropertyEditor::AddNotify);
         system->RegisterNodeAttribute<PropertyEditor>(PropertyEditor::RemoveNotify);
         system->RegisterNodeAttribute<PropertyEditor>(PropertyEditor::ClearNotify);
+        system->RegisterNodeAttribute<PropertyEditor>(PropertyEditor::ValueHashed);
 
         system->RegisterPropertyEditor<UIElement>();
         system->RegisterNodeAttribute<UIElement>(UIElement::Handler);

+ 1 - 0
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/PropertyEditorNodes.h

@@ -104,6 +104,7 @@ namespace AZ::DocumentPropertyEditor::Nodes
         static constexpr auto Value = AttributeDefinition<AZ::Dom::Value>("Value");
         static constexpr auto ValueType = TypeIdAttributeDefinition("ValueType");
         static constexpr auto Disabled = AttributeDefinition<bool>("Disabled");
+        static constexpr auto ValueHashed = AttributeDefinition<AZ::Uuid>("ValueHashed");
 
         //! If set to true, specifies that this PropertyEditor shouldn't be allocated its own column, but instead appended
         //! to the previous column in the layout, creating a SharedColumn that can hold many PropertyEditors.

+ 19 - 4
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/ReflectionAdapter.cpp

@@ -213,7 +213,8 @@ namespace AZ::DocumentPropertyEditor
             void* instance,
             const Reflection::IAttributes& attributes,
             AZStd::function<Dom::Value(const Dom::Value&)> onChanged,
-            bool createRow)
+            bool createRow,
+            bool hashValue)
         {
             if (createRow)
             {
@@ -226,6 +227,14 @@ namespace AZ::DocumentPropertyEditor
             m_onChangedCallbacks.SetValue(m_builder.GetCurrentPath(), AZStd::move(onChanged));
             m_builder.AddMessageHandler(m_adapter, Nodes::PropertyEditor::OnChanged);
             m_builder.AddMessageHandler(m_adapter, Nodes::PropertyEditor::RequestTreeUpdate);
+
+            if (hashValue)
+            {
+                AZStd::any anyVal(&instance);
+                m_builder.Attribute(
+                    Nodes::PropertyEditor::ValueHashed,
+                    AZ::Uuid::CreateData(reinterpret_cast<AZStd::byte*>(AZStd::any_cast<void>(&anyVal)), anyVal.get_type_info().m_valueSize));
+            }
             m_builder.EndPropertyEditor();
 
             CheckContainerElement(instance, attributes);
@@ -253,7 +262,7 @@ namespace AZ::DocumentPropertyEditor
                     }
                     return Dom::Utils::ValueFromType(value);
                 },
-                true);
+                true, false);
         }
 
         void Visit(bool& value, const Reflection::IAttributes& attributes) override
@@ -378,7 +387,7 @@ namespace AZ::DocumentPropertyEditor
                         value = newValue.GetString();
                         return newValue;
                     },
-                    false);
+                    false, false);
                 return;
             }
             else
@@ -435,6 +444,12 @@ namespace AZ::DocumentPropertyEditor
                 }
 
                 AZ::Dom::Value instancePointerValue = AZ::Dom::Utils::MarshalTypedPointerToValue(access.Get(), access.GetType());
+                bool hashValue = false;
+                const AZ::Name PointerTypeFieldName = AZ::Dom::Utils::PointerTypeFieldName;
+                if (instancePointerValue.IsOpaqueValue() || instancePointerValue.FindMember(PointerTypeFieldName))
+                {
+                    hashValue = true;
+                }
                 VisitValue(
                     instancePointerValue,
                     access.Get(),
@@ -468,7 +483,7 @@ namespace AZ::DocumentPropertyEditor
                         // advantages would have to be measured against the size changes in the DOM and the time taken to populate and parse them.
                         return newValue;
                     },
-                    false);
+                    false, hashValue);
             }
         }
 

+ 75 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/UI/DocumentPropertyEditor/DPEComponentAdapter.cpp

@@ -0,0 +1,75 @@
+/*
+ * 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 <AzToolsFramework/UI/DocumentPropertyEditor/DPEComponentAdapter.h>
+#include <QtCore/QTimer>
+
+namespace AZ::DocumentPropertyEditor
+{
+    ComponentAdapter::ComponentAdapter() = default;
+
+    ComponentAdapter::ComponentAdapter(AZ::Component* componentInstace)
+    {
+        SetComponent(componentInstace);
+    }
+
+    ComponentAdapter::~ComponentAdapter()
+    {
+        AzToolsFramework::ToolsApplicationEvents::Bus::Handler::BusDisconnect();
+        AzToolsFramework::PropertyEditorEntityChangeNotificationBus::MultiHandler::BusDisconnect(m_componentInstance->GetEntityId());
+        delete m_componentInstance;
+    }
+
+    void ComponentAdapter::OnEntityComponentPropertyChanged(AZ::ComponentId componentId)
+    {
+        if (m_componentInstance->GetId() == componentId)
+        {
+            m_queuedRefreshLevel = AzToolsFramework::PropertyModificationRefreshLevel::Refresh_Values;
+            QTimer::singleShot(
+                0,
+                [this]()
+                {
+                    DoRefresh();
+                });
+        }
+    }
+
+    void ComponentAdapter::InvalidatePropertyDisplay(AzToolsFramework::PropertyModificationRefreshLevel level)
+    {
+        if (level > m_queuedRefreshLevel)
+        {
+            m_queuedRefreshLevel = level;
+            QTimer::singleShot(
+                0,
+                [this]()
+                {
+                    DoRefresh();
+                });
+        }
+    }
+
+    void ComponentAdapter::SetComponent(AZ::Component* componentInstance)
+    {
+        m_componentInstance = componentInstance;
+        AzToolsFramework::PropertyEditorEntityChangeNotificationBus::MultiHandler::BusConnect(m_componentInstance->GetEntityId());
+        AzToolsFramework::ToolsApplicationEvents::Bus::Handler::BusConnect();
+        AZ::Uuid instanceTypeId = azrtti_typeid(m_componentInstance);
+        SetValue(m_componentInstance, instanceTypeId);
+    }
+
+    void ComponentAdapter::DoRefresh()
+    {
+        if (m_queuedRefreshLevel == AzToolsFramework::PropertyModificationRefreshLevel::Refresh_None)
+        {
+            return;
+        }
+        m_queuedRefreshLevel = AzToolsFramework::PropertyModificationRefreshLevel::Refresh_None;
+        NotifyResetDocument();
+    }
+
+} // namespace AZ::DocumentPropertyEditor

+ 47 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/UI/DocumentPropertyEditor/DPEComponentAdapter.h

@@ -0,0 +1,47 @@
+/*
+ * 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
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Component/Component.h>
+#include <AzFramework/DocumentPropertyEditor/ReflectionAdapter.h>
+#include <AzToolsFramework/API/ToolsApplicationAPI.h>
+#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
+
+namespace AZ::DocumentPropertyEditor
+{
+    //! ComponentAdapter is responsible to listening for signals that affect each component in the Entity Inspector
+    class ComponentAdapter
+        : public ReflectionAdapter
+        , private AzToolsFramework::PropertyEditorEntityChangeNotificationBus::MultiHandler
+        , private AzToolsFramework::ToolsApplicationEvents::Bus::Handler
+    {
+    public:
+        //! Creates an uninitialized (empty) ComponentAdapter.
+        ComponentAdapter();
+        //! Creates a ComponentAdapter with a specific component instance, see SetComponent
+        ComponentAdapter(AZ::Component* componentInstance);
+        ~ComponentAdapter();
+
+        void OnEntityComponentPropertyChanged(AZ::ComponentId componentId) override;
+
+        void InvalidatePropertyDisplay(AzToolsFramework::PropertyModificationRefreshLevel level) override;
+
+        //! Sets the component, connects the appropriate Bus Handlers and sets the reflect data for this instance
+        void SetComponent(AZ::Component* componentInstance);
+
+        //! Trigger a refresh based on messages from the listeners
+        void DoRefresh();
+
+    protected:
+        AZ::Component* m_componentInstance = nullptr;
+        enum AzToolsFramework::PropertyModificationRefreshLevel m_queuedRefreshLevel =
+            AzToolsFramework::PropertyModificationRefreshLevel::Refresh_None;
+    };
+
+} // namespace AZ::DocumentPropertyEditor

+ 2 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ComponentEditor.cpp

@@ -150,7 +150,7 @@ namespace AzToolsFramework
         if (DocumentPropertyEditor::ShouldReplaceRPE())
         {
             // Instantiate the DPE without the RPE
-            m_adapter = AZStd::make_shared<AZ::DocumentPropertyEditor::ReflectionAdapter>();
+            m_adapter = AZStd::make_shared<AZ::DocumentPropertyEditor::ComponentAdapter>();
             m_dpe = new DocumentPropertyEditor(this);
             m_dpe->SetAdapter(m_adapter);
             setContentWidget(m_dpe);
@@ -198,7 +198,7 @@ namespace AzToolsFramework
 
         if (DocumentPropertyEditor::ShouldReplaceRPE())
         {
-            m_adapter->SetValue(componentInstance, instanceTypeId);
+            m_adapter->SetComponent(componentInstance);
         }
         else
         {

+ 3 - 2
Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ComponentEditor.hxx

@@ -15,6 +15,7 @@
 #include <AzToolsFramework/API/EntityCompositionRequestBus.h>
 #include <AzQtComponents/Components/Widgets/Card.h>
 #include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
+#include <AzToolsFramework/UI/DocumentPropertyEditor/DPEComponentAdapter.h>
 
 #include <QFrame>
 #include <QIcon>
@@ -35,7 +36,7 @@ namespace AZ
 
     namespace DocumentPropertyEditor
     {
-        class ReflectionAdapter;
+        class ComponentAdapter;
     }
 }
 
@@ -142,7 +143,7 @@ namespace AzToolsFramework
 
         ReflectedPropertyEditor* m_propertyEditor = nullptr;
 
-        AZStd::shared_ptr<AZ::DocumentPropertyEditor::ReflectionAdapter> m_adapter;
+        AZStd::shared_ptr<AZ::DocumentPropertyEditor::ComponentAdapter> m_adapter;
         DocumentPropertyEditor* m_dpe = nullptr;
 
         AZ::SerializeContext* m_serializeContext = nullptr;

+ 2 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake

@@ -376,6 +376,8 @@ set(FILES
     UI/Docking/DockWidgetUtils.h
     UI/DocumentPropertyEditor/ContainerActionButtonHandler.cpp
     UI/DocumentPropertyEditor/ContainerActionButtonHandler.h
+    UI/DocumentPropertyEditor/DPEComponentAdapter.h
+    UI/DocumentPropertyEditor/DPEComponentAdapter.cpp
     UI/DocumentPropertyEditor/FilterAdapter.cpp
     UI/DocumentPropertyEditor/FilterAdapter.h
     UI/DocumentPropertyEditor/FilteredDPE.cpp