PropertiesContainer.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #if !defined(Q_MOC_RUN)
  10. #include <QScrollArea>
  11. #include <AzToolsFramework/UI/PropertyEditor/ComponentEditor.hxx>
  12. #include "EditorCommon.h"
  13. #endif
  14. class PropertiesWidget;
  15. class EditorWindow;
  16. class PropertiesContainer
  17. : public QScrollArea
  18. {
  19. Q_OBJECT
  20. public:
  21. PropertiesContainer(PropertiesWidget* propertiesWidget,
  22. EditorWindow* editorWindow);
  23. void Refresh(AzToolsFramework::PropertyModificationRefreshLevel refreshLevel = AzToolsFramework::PropertyModificationRefreshLevel::Refresh_EntireTree, const AZ::Uuid* componentType = nullptr);
  24. void SelectionChanged(HierarchyItemRawPtrList* items);
  25. void SelectedEntityPointersChanged();
  26. bool IsCanvasSelected() { return m_isCanvasSelected; }
  27. AZ::Entity::ComponentArrayType GetSelectedComponents();
  28. void RequestPropertyContextMenu(AzToolsFramework::InstanceDataNode* node, const QPoint& globalPos);
  29. void SetSelectedEntityDisplayNameWidget(QLineEdit* selectedEntityDisplayNameWidget);
  30. void SetEditorOnlyCheckbox(QCheckBox* editorOnlyCheckbox);
  31. private:
  32. // A SharedComponentInfo represents one component
  33. // which all selected entities have in common.
  34. // If entities have multiple of the same component-type
  35. // then there will be a SharedComponentInfo for each.
  36. // Example: Say 3 entities are selected and each entity has 2 MeshComponents.
  37. // There will be 2 SharedComponentInfo, one for each MeshComponent.
  38. // Each SharedComponentInfo::m_instances has 3 entries,
  39. // one for the Nth MeshComponent in each entity.
  40. struct SharedComponentInfo
  41. {
  42. SharedComponentInfo()
  43. : m_classData(nullptr)
  44. , m_compareInstance(nullptr)
  45. {}
  46. const AZ::SerializeContext::ClassData* m_classData;
  47. /// Components instanced (one from each entity).
  48. AZ::Entity::ComponentArrayType m_instances;
  49. /// Canonical instance to compare others against
  50. AZ::Component* m_compareInstance;
  51. };
  52. // Widget overrides
  53. void resizeEvent(QResizeEvent* event) override;
  54. void contextMenuEvent(QContextMenuEvent* event) override;
  55. bool eventFilter(QObject* object, QEvent* event) override;
  56. bool HandleSelectionEvents(QObject* object, QEvent* event);
  57. bool m_selectionEventAccepted; // ensure selection logic executes only once per click since eventFilter may execute multiple times for a single click
  58. // A collection of SharedComponentInfo.
  59. // The map is keyed on the component-type.
  60. // In the case of /ref GenericComponentWrapper,
  61. // the type corresponds to the component-type being wrapped,
  62. // though SharedComponentInfo::m_instances still point to the
  63. // GenericComponentWrapper*.
  64. using ComponentTypeMap = AZStd::unordered_map<AZ::Uuid, AZStd::vector<SharedComponentInfo>>;
  65. void BuildSharedComponentList(ComponentTypeMap&, const AzToolsFramework::EntityIdList& entitiesShown);
  66. void BuildSharedComponentUI(ComponentTypeMap&, const AzToolsFramework::EntityIdList& entitiesShown);
  67. AzToolsFramework::ComponentEditor* CreateComponentEditor(const AZ::Component& componentInstance);
  68. // Helper functions for selecting components
  69. bool DoesOwnFocus() const;
  70. QRect GetWidgetGlobalRect(const QWidget* widget) const;
  71. bool DoesIntersectWidget(const QRect& globalRect, const QWidget* widget) const;
  72. bool DoesIntersectSelectedComponentEditor(const QRect& globalRect) const;
  73. bool DoesIntersectNonSelectedComponentEditor(const QRect& globalRect) const;
  74. void ClearComponentEditorSelection();
  75. void SelectRangeOfComponentEditors(const AZ::s32 index1, const AZ::s32 index2, bool selected = true);
  76. void SelectIntersectingComponentEditors(const QRect& globalRect, bool selected = true);
  77. void ToggleIntersectingComponentEditors(const QRect& globalRect);
  78. AZ::s32 GetComponentEditorIndex(const AzToolsFramework::ComponentEditor* componentEditor) const;
  79. AZStd::vector<AzToolsFramework::ComponentEditor*> GetIntersectingComponentEditors(const QRect& globalRect) const;
  80. // Create actions to add/remove/cut/copy/paste components
  81. void CreateActions();
  82. // Update states
  83. void UpdateActions();
  84. void UpdateOverlay();
  85. void UpdateInternalState();
  86. // Called when an action to add a component was triggered
  87. void OnAddComponent();
  88. // Context menu helpers
  89. void OnDisplayUiComponentEditorMenu(const QPoint& position);
  90. void ShowContextMenu(const QPoint& position);
  91. void Update();
  92. void UpdateEditorOnlyCheckbox();
  93. PropertiesWidget* m_propertiesWidget;
  94. EditorWindow* m_editorWindow;
  95. QWidget* m_componentListContents;
  96. QVBoxLayout* m_rowLayout;
  97. QLineEdit* m_selectedEntityDisplayNameWidget;
  98. QCheckBox* m_editorOnlyCheckbox; //!< Checkbox associated with the value of the selected entities' "editor only component" value
  99. QAction* m_actionToAddComponents;
  100. QAction* m_actionToDeleteComponents;
  101. QAction* m_actionToCutComponents;
  102. QAction* m_actionToCopyComponents;
  103. QAction* m_actionToPasteComponents;
  104. // We require an overlay widget to act as a canvas to draw on top of everything in the properties pane
  105. // so that we can draw outside of the component editors' bounds
  106. friend class PropertyContainerOverlay;
  107. class PropertyContainerOverlay* m_overlay = nullptr;
  108. using ComponentPropertyEditorMap = AZStd::unordered_map<AZ::Uuid, AZStd::vector<AzToolsFramework::ComponentEditor*>>;
  109. ComponentPropertyEditorMap m_componentEditorsByType;
  110. using ComponentEditorVector = AZStd::vector<AzToolsFramework::ComponentEditor*>;
  111. ComponentEditorVector m_componentEditors; // list of component editors in order shown
  112. AZ::s32 m_componentEditorLastSelectedIndex;
  113. bool m_selectionHasChanged;
  114. AZStd::vector<AZ::EntityId> m_selectedEntities;
  115. bool m_isCanvasSelected;
  116. // Pointer to entity that first entity is compared against for the purpose of rendering deltas vs. slice in the property grid.
  117. AZStd::unique_ptr<AZ::Entity> m_compareToEntity;
  118. // Global app serialization context, cached for internal usage during the life of the control.
  119. AZ::SerializeContext* m_serializeContext;
  120. };