From 6532c50c2769f74205dac207dce34f0f4f364447 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Tue, 7 Dec 2021 17:22:10 -0600 Subject: [PATCH 1/2] Some read-only prefab workflow updates. Signed-off-by: Chris Galvan --- .../SandboxIntegration.cpp | 36 +++++++++++++++---- .../SandboxIntegration.h | 2 ++ .../Prefab/PrefabPublicHandler.cpp | 32 ++++++++++++++++- .../UI/Prefab/PrefabIntegrationManager.cpp | 30 +++++++++++----- .../UI/Prefab/PrefabIntegrationManager.h | 3 ++ 5 files changed, 87 insertions(+), 16 deletions(-) diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 9342c17a37..d5b903585e 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -208,6 +209,9 @@ void SandboxIntegrationManager::Setup() m_editorEntityAPI = AZ::Interface::Get(); AZ_Assert(m_editorEntityAPI, "SandboxIntegrationManager requires an EditorEntityAPI instance to be present on Setup()."); + m_readOnlyEntityPublicInterface = AZ::Interface::Get(); + AZ_Assert(m_readOnlyEntityPublicInterface, "SandboxIntegrationManager requires an ReadOnlyEntityPublicInterface instance to be present on Setup()."); + AzToolsFramework::Layers::EditorLayerComponentNotificationBus::Handler::BusConnect(); } @@ -658,15 +662,17 @@ void SandboxIntegrationManager::PopulateEditorGlobalContextMenu(QMenu* menu, con // when a single entity is selected, entity is created as its child else if (selected.size() == 1) { + AZ::EntityId selectedEntityId = selected.front(); + bool selectedEntityIsReadOnly = m_readOnlyEntityPublicInterface->IsReadOnly(selectedEntityId); auto containerEntityInterface = AZ::Interface::Get(); - if (!prefabSystemEnabled || (containerEntityInterface && containerEntityInterface->IsContainerOpen(selected.front()))) + if (!prefabSystemEnabled || (containerEntityInterface && containerEntityInterface->IsContainerOpen(selectedEntityId) && !selectedEntityIsReadOnly)) { action = menu->addAction(QObject::tr("Create entity")); QObject::connect( action, &QAction::triggered, action, - [selected] + [selectedEntityId] { - AzToolsFramework::EditorRequestBus::Broadcast(&AzToolsFramework::EditorRequestBus::Handler::CreateNewEntityAsChild, selected.front()); + AzToolsFramework::EditorRequestBus::Broadcast(&AzToolsFramework::EditorRequestBus::Handler::CreateNewEntityAsChild, selectedEntityId); } ); } @@ -691,11 +697,27 @@ void SandboxIntegrationManager::PopulateEditorGlobalContextMenu(QMenu* menu, con SetupSliceContextMenu(menu); } - action = menu->addAction(QObject::tr("Duplicate")); - QObject::connect(action, &QAction::triggered, action, [this] { ContextMenu_Duplicate(); }); - if (selected.size() == 0) + if (!selected.empty()) { - action->setDisabled(true); + // Don't allow duplication if any of the selected entities are direct desendants of a read-only entity + bool selectionContainsDescendantOfReadOnlyEntity = false; + for (const auto& entityId : selected) + { + AZ::EntityId parentEntityId; + AZ::TransformBus::EventResult(parentEntityId, entityId, &AZ::TransformBus::Events::GetParentId); + + if (parentEntityId.IsValid() && m_readOnlyEntityPublicInterface->IsReadOnly(parentEntityId)) + { + selectionContainsDescendantOfReadOnlyEntity = true; + break; + } + } + + if (!selectionContainsDescendantOfReadOnlyEntity) + { + action = menu->addAction(QObject::tr("Duplicate")); + QObject::connect(action, &QAction::triggered, action, [this] { ContextMenu_Duplicate(); }); + } } if (!prefabSystemEnabled) diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h index 7fe2881b92..79e7a4334d 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h @@ -76,6 +76,7 @@ namespace AzToolsFramework { class EditorEntityAPI; class EditorEntityUiInterface; + class ReadOnlyEntityPublicInterface; namespace AssetBrowser { @@ -295,6 +296,7 @@ private: AzToolsFramework::EditorEntityUiInterface* m_editorEntityUiInterface = nullptr; AzToolsFramework::Prefab::PrefabIntegrationInterface* m_prefabIntegrationInterface = nullptr; AzToolsFramework::EditorEntityAPI* m_editorEntityAPI = nullptr; + AzToolsFramework::ReadOnlyEntityPublicInterface* m_readOnlyEntityPublicInterface = nullptr; // Overrides UI styling and behavior for Layer Entities AzToolsFramework::LayerUiHandler m_layerUiOverrideHandler; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index dfabd42cd1..aaf6141e12 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -581,7 +582,15 @@ namespace AzToolsFramework "Cannot add entity because the parent entity (id '%llu') is a closed container entity.", static_cast(parentId))); } - + + // If the parent entity is marked as read only, bail. + if (auto readOnlyEntityPublicInterface = AZ::Interface::Get(); readOnlyEntityPublicInterface->IsReadOnly(parentId)) + { + return AZ::Failure(AZStd::string::format( + "Cannot add entity because the parent entity (id '%llu') is marked as read only.", + static_cast(parentId))); + } + EntityAlias entityAlias = Instance::GenerateEntityAlias(); AliasPath absoluteEntityPath = owningInstanceOfParentEntity->get().GetAbsoluteInstanceAliasPath(); @@ -1210,6 +1219,27 @@ namespace AzToolsFramework return AZ::Failure(AZStd::string("Cannot delete entities belonging to an instance that is not being edited.")); } + // None of the specified entities can be marked as read only, otherwise this operation is invalid. + if (auto readOnlyEntityPublicInterface = AZ::Interface::Get()) + { + AZ::EntityId readOnlyEntityId; + for (const auto& entityId : entityIdsNoFocusContainer) + { + if (readOnlyEntityPublicInterface->IsReadOnly(entityId)) + { + readOnlyEntityId = entityId; + break; + } + } + + if (readOnlyEntityId.IsValid()) + { + return AZ::Failure(AZStd::string::format( + "Cannot delete entities because entity (id '%llu') is marked as read only.", + static_cast(readOnlyEntityId))); + } + } + // Retrieve entityList from entityIds EntityList inputEntityList = EntityIdListToEntityList(entityIdsNoFocusContainer); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 1c60b78322..d020391665 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -141,6 +142,9 @@ namespace AzToolsFramework return; } + m_readOnlyEntityPublicInterface = AZ::Interface::Get(); + AZ_Assert(m_readOnlyEntityPublicInterface, "Prefab - could not get ReadOnlyEntityPublicInterface on PrefabIntegrationManager construction."); + // Get EditorEntityContextId EditorEntityContextRequestBus::BroadcastResult(s_editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId); @@ -263,6 +267,16 @@ namespace AzToolsFramework AzFramework::ApplicationRequests::Bus::BroadcastResult( prefabWipFeaturesEnabled, &AzFramework::ApplicationRequests::ArePrefabWipFeaturesEnabled); + bool readOnlyEntityInSelection = false; + for (const auto& entityId : selectedEntities) + { + if (m_readOnlyEntityPublicInterface->IsReadOnly(entityId)) + { + readOnlyEntityInSelection = true; + break; + } + } + // Create Prefab { if (!selectedEntities.empty()) @@ -289,7 +303,8 @@ namespace AzToolsFramework } // Layers can't be in prefabs. - if (!layerInSelection) + // Also don't allow to create a prefab if any of the selected entities are read-only + if (!layerInSelection && !readOnlyEntityInSelection) { QAction* createAction = menu->addAction(QObject::tr("Create Prefab...")); createAction->setToolTip(QObject::tr("Creates a prefab out of the currently selected entities.")); @@ -383,14 +398,13 @@ namespace AzToolsFramework menu->addSeparator(); } - QAction* deleteAction = menu->addAction(QObject::tr("Delete")); - QObject::connect(deleteAction, &QAction::triggered, deleteAction, [] { ContextMenu_DeleteSelected(); }); - - if (selectedEntities.empty() || - (selectedEntities.size() == 1 && - selectedEntities[0] == s_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(s_editorEntityContextId))) + if (!selectedEntities.empty() && + (selectedEntities.size() != 1 || + selectedEntities[0] != s_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(s_editorEntityContextId)) && + !readOnlyEntityInSelection) { - deleteAction->setDisabled(true); + QAction* deleteAction = menu->addAction(QObject::tr("Delete")); + QObject::connect(deleteAction, &QAction::triggered, deleteAction, [] { ContextMenu_DeleteSelected(); }); } // Detach Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h index 8589bee942..12aa3f7c72 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h @@ -29,6 +29,7 @@ namespace AzToolsFramework { class ContainerEntityInterface; + class ReadOnlyEntityPublicInterface; namespace Prefab { @@ -169,6 +170,8 @@ namespace AzToolsFramework static PrefabLoaderInterface* s_prefabLoaderInterface; static PrefabPublicInterface* s_prefabPublicInterface; static PrefabSystemComponentInterface* s_prefabSystemComponentInterface; + + ReadOnlyEntityPublicInterface* m_readOnlyEntityPublicInterface = nullptr; }; } } From 3a7d9f9b3a463cf9566f2789a03440bb118026a4 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 7 Dec 2021 16:58:29 -0800 Subject: [PATCH 2/2] LYN-8633 | Read-Only Entities - Entity Outliner behavior changes (#6230) * Add invalid entityId check to IsReadOnly Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Ensure read-only entities editing is limited (no renaming, limited drag/drop, no asset drop on them) Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Removing redundant class definition in wrong namespace. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../ReadOnlyEntitySystemComponent.cpp | 5 ++ .../UI/Outliner/EntityOutlinerListModel.cpp | 62 ++++++++++++++++--- .../UI/Outliner/EntityOutlinerListModel.hxx | 1 + .../UI/Outliner/EntityOutlinerTreeView.cpp | 21 ++++++- .../UI/Outliner/EntityOutlinerTreeView.hxx | 4 +- .../UI/Outliner/EntityOutlinerWidget.cpp | 26 ++++++-- .../UI/Outliner/EntityOutlinerWidget.hxx | 2 + 7 files changed, 106 insertions(+), 15 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/ReadOnly/ReadOnlyEntitySystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/ReadOnly/ReadOnlyEntitySystemComponent.cpp index 7536e1e8a5..f3d6ec041c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/ReadOnly/ReadOnlyEntitySystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/ReadOnly/ReadOnlyEntitySystemComponent.cpp @@ -42,6 +42,11 @@ namespace AzToolsFramework bool ReadOnlyEntitySystemComponent::IsReadOnly(const AZ::EntityId& entityId) { + if (!entityId.IsValid()) + { + return false; + } + if (!m_readOnlystates.contains(entityId)) { QueryReadOnlyStateForEntity(entityId); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp index 284caaa7a2..0b882324b5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp @@ -117,8 +117,12 @@ namespace AzToolsFramework ContainerEntityNotificationBus::Handler::BusConnect(editorEntityContextId); m_editorEntityUiInterface = AZ::Interface::Get(); - AZ_Assert(m_editorEntityUiInterface != nullptr, - "EntityOutlinerListModel requires a EditorEntityUiInterface instance on Initialize."); + AZ_Assert(m_editorEntityUiInterface != nullptr, "EntityOutlinerListModel requires a EditorEntityUiInterface instance on Initialize."); + + m_readOnlyEntityPublicInterface = AZ::Interface::Get(); + AZ_Assert( + (m_readOnlyEntityPublicInterface != nullptr), + "EntityOutlinerListModel requires a ReadOnlyEntityPublicInterface instance on Initialize."); } int EntityOutlinerListModel::rowCount(const QModelIndex& parent) const @@ -451,9 +455,15 @@ namespace AzToolsFramework if (value.canConvert()) { const auto entityId = GetEntityFromIndex(index); - auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId); - if (!entityUiHandler || entityUiHandler->CanToggleLockVisibility(entityId)) + // Disable lock and visibility toggling if the UI Handler blocked it. + auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId); + bool canToggleLockVisibility = !entityUiHandler || entityUiHandler->CanToggleLockVisibility(entityId); + + // Disable lock and visibility toggling for read-only entities. + bool isReadOnly = m_readOnlyEntityPublicInterface->IsReadOnly(entityId); + + if (canToggleLockVisibility && !isReadOnly) { switch (index.column()) { @@ -535,6 +545,15 @@ namespace AzToolsFramework return Qt::ItemIsDropEnabled; } + AZ::EntityId entityId = GetEntityFromIndex(index); + + // Only allow renaming the entity if the UI Handler did not block it. + auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId); + bool canRename = !entityUiHandler || entityUiHandler->CanRename(entityId); + + // Disable renaming for read-only entities. + bool isReadOnly = m_readOnlyEntityPublicInterface->IsReadOnly(entityId); + Qt::ItemFlags itemFlags = QAbstractItemModel::flags(index); switch (index.column()) { @@ -544,7 +563,21 @@ namespace AzToolsFramework break; case ColumnName: - itemFlags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsEditable; + if (canRename && !isReadOnly) + { + itemFlags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsEditable; + } + else + { + if (isReadOnly) + { + itemFlags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; + } + else + { + itemFlags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled; + } + } break; default: @@ -552,7 +585,8 @@ namespace AzToolsFramework break; } - if (AZ::EntityId entityId = GetEntityFromIndex(index); !m_focusModeInterface->IsInFocusSubTree(entityId)) + // Disable entities outside the focus subtree. + if (!m_focusModeInterface->IsInFocusSubTree(entityId)) { itemFlags &= !Qt::ItemIsEnabled; } @@ -773,14 +807,21 @@ namespace AzToolsFramework [[maybe_unused]] int column, const QModelIndex& parent) const { - // Disable dropping assets on closed container entities. AZ::EntityId parentId = GetEntityFromIndex(parent); + + // Disable dropping assets on closed container entities. if (auto containerEntityInterface = AZ::Interface::Get(); !containerEntityInterface->IsContainerOpen(parentId)) { return false; } + // Disable dropping assets on read-only entities. + if (m_readOnlyEntityPublicInterface->IsReadOnly(parentId)) + { + return false; + } + if (data->hasFormat(AssetBrowser::AssetBrowserEntry::GetMimeType())) { return DecodeAssetMimeData(data); @@ -2211,6 +2252,13 @@ namespace AzToolsFramework QColor transparentColor(0, 0, 0, 0); checkboxPalette.setColor(QPalette::ColorRole::Window, transparentColor); + // Disable hover rendering for read-only entities + AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); + if (m_readOnlyEntityPublicInterface->IsReadOnly(entityId)) + { + isHovered = false; + } + // We're only using these check boxes as renderers so their actual state doesn't matter. // We can set it right before we draw using information from the model data. if (index.column() == EntityOutlinerListModel::ColumnVisibilityToggle) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx index b785dcb31e..f099ed504a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx @@ -290,6 +290,7 @@ namespace AzToolsFramework EditorEntityUiInterface* m_editorEntityUiInterface = nullptr; FocusModeInterface* m_focusModeInterface = nullptr; + ReadOnlyEntityPublicInterface* m_readOnlyEntityPublicInterface = nullptr; }; class EntityOutlinerCheckBox diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp index 0609f8113d..857fdb5f80 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -35,11 +36,14 @@ namespace AzToolsFramework setHeaderHidden(true); m_editorEntityFrameworkInterface = AZ::Interface::Get(); - AZ_Assert((m_editorEntityFrameworkInterface != nullptr), "EntityOutlinerTreeView requires a EditorEntityFrameworkInterface instance on Construction."); - + m_readOnlyEntityPublicInterface = AZ::Interface::Get(); + AZ_Assert( + (m_readOnlyEntityPublicInterface != nullptr), + "EntityOutlinerTreeView requires a ReadOnlyEntityPublicInterface instance on Construction."); + AzFramework::EntityContextId editorEntityContextId = AzFramework::EntityContextId::CreateNull(); AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult( editorEntityContextId, &AzToolsFramework::EditorEntityContextRequestBus::Events::GetEditorEntityContextId); @@ -157,11 +161,22 @@ namespace AzToolsFramework void EntityOutlinerTreeView::startDrag(Qt::DropActions supportedActions) { + QModelIndex index = indexAt(m_queuedMouseEvent->pos()); + AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); + + AZ::EntityId parentEntityId; + EditorEntityInfoRequestBus::EventResult(parentEntityId, entityId, &EditorEntityInfoRequestBus::Events::GetParent); + + // If the entity is parented to a read-only entity, cancel the drag operation. + if (m_readOnlyEntityPublicInterface->IsReadOnly(parentEntityId)) + { + return; + } + //if we are attempting to drag an unselected item then we must special case drag and drop logic //QAbstractItemView::startDrag only supports selected items if (m_queuedMouseEvent) { - QModelIndex index = indexAt(m_queuedMouseEvent->pos()); if (!index.isValid() || index.column() != 0) { return; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx index 42b42a59b4..9262da9a73 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx @@ -26,6 +26,7 @@ class QMouseEvent; namespace AzToolsFramework { class EditorEntityUiInterface; + class ReadOnlyEntityPublicInterface; //! This class largely exists to emit events for the OutlinerWidget to listen in on. //! The logic for these events is best off not happening within the tree itself, @@ -92,7 +93,8 @@ namespace AzToolsFramework QModelIndex m_currentHoveredIndex; - EditorEntityUiInterface* m_editorEntityFrameworkInterface; + EditorEntityUiInterface* m_editorEntityFrameworkInterface = nullptr; + ReadOnlyEntityPublicInterface* m_readOnlyEntityPublicInterface = nullptr; }; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp index d6e9cac754..2e3955bed7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -156,6 +157,11 @@ namespace AzToolsFramework m_editorEntityUiInterface = AZ::Interface::Get(); AZ_Assert(m_editorEntityUiInterface != nullptr, "EntityOutlinerWidget requires a EditorEntityUiInterface instance on Initialize."); + m_readOnlyEntityPublicInterface = AZ::Interface::Get(); + AZ_Assert( + (m_readOnlyEntityPublicInterface != nullptr), + "EntityOutlinerListModel requires a ReadOnlyEntityPublicInterface instance on Initialize."); + m_gui = new Ui::EntityOutlinerWidgetUI(); m_gui->setupUi(this); @@ -585,9 +591,15 @@ namespace AzToolsFramework if (m_selectedEntityIds.size() == 1) { auto entityId = m_selectedEntityIds.front(); - auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId); - if (!entityUiHandler || entityUiHandler->CanRename(entityId)) + // Only allow renaming the entity if the UI Handler did not block it. + auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId); + bool canRename = !entityUiHandler || entityUiHandler->CanRename(entityId); + + // Disable renaming for read-only entities. + bool isReadOnly = m_readOnlyEntityPublicInterface->IsReadOnly(entityId); + + if (canRename && !isReadOnly) { contextMenu->addAction(m_actionToRenameSelection); } @@ -717,9 +729,15 @@ namespace AzToolsFramework if (m_selectedEntityIds.size() == 1) { auto entityId = m_selectedEntityIds.front(); - auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId); - if (!entityUiHandler || entityUiHandler->CanRename(entityId)) + // Only allow renaming the entity if the UI Handler did not block it. + auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId); + bool canRename = !entityUiHandler || entityUiHandler->CanRename(entityId); + + // Disable renaming for read-only entities. + bool isReadOnly = m_readOnlyEntityPublicInterface->IsReadOnly(entityId); + + if (canRename && !isReadOnly) { const QModelIndex proxyIndex = GetIndexFromEntityId(entityId); if (proxyIndex.isValid()) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx index 431861ab67..b0925b5219 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx @@ -43,6 +43,7 @@ namespace AzToolsFramework class EntityOutlinerListModel; class EntityOutlinerContainerProxyModel; class EntityOutlinerSortFilterProxyModel; + class ReadOnlyEntityPublicInterface; namespace EntityOutliner { @@ -204,6 +205,7 @@ namespace AzToolsFramework bool m_sortContentQueued; EditorEntityUiInterface* m_editorEntityUiInterface = nullptr; + ReadOnlyEntityPublicInterface* m_readOnlyEntityPublicInterface = nullptr; }; }