Merge pull request #6232 from aws-lumberyard-dev/cgalvan/ReadOnlyPrefabWorkflowChanges

Some read-only prefab workflow updates.
This commit is contained in:
Chris Galvan
2021-12-07 19:38:54 -06:00
committed by GitHub
5 changed files with 87 additions and 16 deletions
@@ -41,6 +41,7 @@
#include <AzToolsFramework/Editor/EditorContextMenuBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
#include <AzToolsFramework/Entity/SliceEditorEntityOwnershipServiceBus.h>
#include <AzToolsFramework/Slice/SliceRequestBus.h>
#include <AzToolsFramework/Slice/SliceUtilities.h>
@@ -208,6 +209,9 @@ void SandboxIntegrationManager::Setup()
m_editorEntityAPI = AZ::Interface<AzToolsFramework::EditorEntityAPI>::Get();
AZ_Assert(m_editorEntityAPI, "SandboxIntegrationManager requires an EditorEntityAPI instance to be present on Setup().");
m_readOnlyEntityPublicInterface = AZ::Interface<AzToolsFramework::ReadOnlyEntityPublicInterface>::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<AzToolsFramework::ContainerEntityInterface>::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)
@@ -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;
@@ -18,6 +18,7 @@
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
#include <AzToolsFramework/Prefab/Instance/InstanceEntityIdMapper.h>
@@ -581,7 +582,15 @@ namespace AzToolsFramework
"Cannot add entity because the parent entity (id '%llu') is a closed container entity.",
static_cast<AZ::u64>(parentId)));
}
// If the parent entity is marked as read only, bail.
if (auto readOnlyEntityPublicInterface = AZ::Interface<ReadOnlyEntityPublicInterface>::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<AZ::u64>(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<ReadOnlyEntityPublicInterface>::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<AZ::u64>(readOnlyEntityId)));
}
}
// Retrieve entityList from entityIds
EntityList inputEntityList = EntityIdListToEntityList(entityIdsNoFocusContainer);
@@ -25,6 +25,7 @@
#include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
#include <AzToolsFramework/Prefab/Instance/InstanceToTemplateInterface.h>
@@ -141,6 +142,9 @@ namespace AzToolsFramework
return;
}
m_readOnlyEntityPublicInterface = AZ::Interface<ReadOnlyEntityPublicInterface>::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
@@ -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;
};
}
}