Prevent read-only entities from being duplicated via prefab workflows (#7076)
* Refactor the sanitation of the selection for prefab operations to prevent read-only entities from being deleted or duplicated. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Fix comment. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com>
This commit is contained in:
@@ -1063,7 +1063,7 @@ namespace AzToolsFramework
|
||||
return AZ::Failure(AZStd::string("No entities to duplicate."));
|
||||
}
|
||||
|
||||
const EntityIdList entityIdsNoFocusContainer = GenerateEntityIdListWithoutFocusedInstanceContainer(entityIds);
|
||||
const EntityIdList entityIdsNoFocusContainer = SanitizeEntityIdList(entityIds);
|
||||
if (entityIdsNoFocusContainer.empty())
|
||||
{
|
||||
return AZ::Failure(AZStd::string("No entities to duplicate because only instance selected is the container entity of the focused instance."));
|
||||
@@ -1202,7 +1202,7 @@ namespace AzToolsFramework
|
||||
PrefabOperationResult PrefabPublicHandler::DeleteFromInstance(const EntityIdList& entityIds, bool deleteDescendants)
|
||||
{
|
||||
// Remove the container entity of the focused prefab from the list, if it is included.
|
||||
const EntityIdList entityIdsNoFocusContainer = GenerateEntityIdListWithoutFocusedInstanceContainer(entityIds);
|
||||
const EntityIdList entityIdsNoFocusContainer = SanitizeEntityIdList(entityIds);
|
||||
|
||||
if (entityIdsNoFocusContainer.empty())
|
||||
{
|
||||
@@ -1236,27 +1236,6 @@ 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);
|
||||
|
||||
@@ -1680,10 +1659,24 @@ namespace AzToolsFramework
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
EntityIdList PrefabPublicHandler::GenerateEntityIdListWithoutFocusedInstanceContainer(
|
||||
const EntityIdList& entityIds) const
|
||||
EntityIdList PrefabPublicHandler::SanitizeEntityIdList(const EntityIdList& entityIds) const
|
||||
{
|
||||
EntityIdList outEntityIds(entityIds);
|
||||
EntityIdList outEntityIds;
|
||||
|
||||
if (auto readOnlyEntityPublicInterface = AZ::Interface<ReadOnlyEntityPublicInterface>::Get())
|
||||
{
|
||||
std::copy_if(
|
||||
entityIds.begin(), entityIds.end(), AZStd::back_inserter(outEntityIds),
|
||||
[readOnlyEntityPublicInterface](const AZ::EntityId& entityId)
|
||||
{
|
||||
return !readOnlyEntityPublicInterface->IsReadOnly(entityId);
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
outEntityIds = entityIds;
|
||||
}
|
||||
|
||||
AzFramework::EntityContextId editorEntityContextId = AzToolsFramework::GetEntityContextId();
|
||||
AZ::EntityId focusedInstanceContainerEntityId = m_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId);
|
||||
|
||||
@@ -75,7 +75,10 @@ namespace AzToolsFramework
|
||||
Instance& commonRootEntityOwningInstance,
|
||||
EntityList& outEntities,
|
||||
AZStd::vector<Instance*>& outInstances) const;
|
||||
EntityIdList GenerateEntityIdListWithoutFocusedInstanceContainer(const EntityIdList& entityIds) const;
|
||||
|
||||
//! Sanitizes an EntityIdList to remove entities that should not be affected by prefab operations.
|
||||
//! It will identify and exclude the container entity of the root prefab instance, and all read-only entities.
|
||||
EntityIdList SanitizeEntityIdList(const EntityIdList& entityIds) const;
|
||||
|
||||
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const;
|
||||
bool EntitiesBelongToSameInstance(const EntityIdList& entityIds) const;
|
||||
|
||||
Reference in New Issue
Block a user