diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index 6e96511507..336b56653b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -159,12 +159,23 @@ namespace AzToolsFramework void PrefabEditorEntityOwnershipService::GetNonPrefabEntities(EntityList& entities) { - m_rootInstance->GetEntities(entities, false); + m_rootInstance->GetEntities( + [&entities](const AZStd::unique_ptr& entity) + { + entities.emplace_back(entity.get()); + return true; + }); } bool PrefabEditorEntityOwnershipService::GetAllEntities(EntityList& entities) { - m_rootInstance->GetEntities(entities, true); + m_rootInstance->GetAllEntitiesInHierarchy( + [&entities](const AZStd::unique_ptr& entity) + { + entities.emplace_back(entity.get()); + return true; + }); + return true; } @@ -551,7 +562,7 @@ namespace AzToolsFramework return; } - m_rootInstance->GetNestedEntities([this](AZStd::unique_ptr& entity) + m_rootInstance->GetAllEntitiesInHierarchy([this](AZStd::unique_ptr& entity) { AZ_Assert(entity, "Invalid entity found in root instance while starting play in editor."); if (entity->GetState() == AZ::Entity::State::Active) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp index 83a76aeb01..e5179f4229 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp @@ -373,17 +373,25 @@ namespace AzToolsFramework } } - void Instance::GetConstNestedEntities(const AZStd::function& callback) + bool Instance::GetEntities_Impl(const AZStd::function&)>& callback) { - GetConstEntities(callback); - - for (const auto& [instanceAlias, instance] : m_nestedInstances) + for (auto& [entityAlias, entity] : m_entities) { - instance->GetConstNestedEntities(callback); + if (!entity) + { + continue; + } + + if (!callback(entity)) + { + return false; + } } + + return true; } - void Instance::GetConstEntities(const AZStd::function& callback) + bool Instance::GetConstEntities_Impl(const AZStd::function& callback) const { for (const auto& [entityAlias, entity] : m_entities) { @@ -394,65 +402,91 @@ namespace AzToolsFramework if (!callback(*entity)) { - break; + return false; } } + + return true; } - void Instance::GetNestedEntities(const AZStd::function&)>& callback) + bool Instance::GetAllEntitiesInHierarchy_Impl(const AZStd::function&)>& callback) { - GetEntities(callback); - - for (auto& [instanceAlias, instance] : m_nestedInstances) + if (HasContainerEntity()) { - instance->GetNestedEntities(callback); + if (!callback(m_containerEntity)) + { + return false; + } } - } - void Instance::GetNestedInstances(const AZStd::function&)>& callback) - { - for (auto& [instanceAlias, instance] : m_nestedInstances) + if (!GetEntities_Impl(callback)) { - callback(instance); + return false; } - } - void Instance::GetEntities(const AZStd::function&)>& callback) - { - for (auto& [entityAlias, entity] : m_entities) + for (auto& [instanceAlias, instance] : m_nestedInstances) { - if (!callback(entity)) + if (!instance->GetAllEntitiesInHierarchy_Impl(callback)) { - break; + return false; } } + + return true; } - void Instance::GetEntities(EntityList& entities, bool includeNestedEntities) + bool Instance::GetAllEntitiesInHierarchyConst_Impl(const AZStd::function& callback) const { - // Non-recursive traversal of instances - AZStd::vector instancesToTraverse = { this }; - while (!instancesToTraverse.empty()) + if (HasContainerEntity()) { - Instance* currentInstance = instancesToTraverse.back(); - instancesToTraverse.pop_back(); - if (includeNestedEntities) + if (!callback(*m_containerEntity)) { - instancesToTraverse.reserve(instancesToTraverse.size() + currentInstance->m_nestedInstances.size()); - for (const auto& instanceByAlias : currentInstance->m_nestedInstances) - { - instancesToTraverse.push_back(instanceByAlias.second.get()); - } + return false; } + } - // Size increases by 1 for each instance because we have to count the container entity also. - entities.reserve(entities.size() + currentInstance->m_entities.size() + 1); - entities.push_back(m_containerEntity.get()); - for (const auto& entityByAlias : currentInstance->m_entities) + if (!GetConstEntities_Impl(callback)) + { + return false; + } + + for (const auto& [instanceAlias, instance] : m_nestedInstances) + { + if (!instance->GetAllEntitiesInHierarchyConst_Impl(callback)) { - entities.push_back(entityByAlias.second.get()); + return false; } } + + return true; + } + + void Instance::GetEntities(const AZStd::function&)>& callback) + { + GetEntities_Impl(callback); + } + + void Instance::GetConstEntities(const AZStd::function& callback) const + { + GetConstEntities_Impl(callback); + } + + void Instance::GetAllEntitiesInHierarchy(const AZStd::function&)>& callback) + { + GetAllEntitiesInHierarchy_Impl(callback); + } + + void Instance::GetAllEntitiesInHierarchyConst(const AZStd::function& callback) const + { + GetAllEntitiesInHierarchyConst_Impl(callback); + } + + void Instance::GetNestedInstances(const AZStd::function&)>& callback) + { + for (auto& [instanceAlias, instance] : m_nestedInstances) + { + callback(instance); + } } EntityAliasOptionalReference Instance::GetEntityAlias(const AZ::EntityId& id) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h index 5f36ac10dc..9d3ae31796 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h @@ -121,10 +121,10 @@ namespace AzToolsFramework /** * Gets the entities in the Instance DOM. Can recursively trace all nested instances. */ - void GetConstNestedEntities(const AZStd::function& callback); - void GetConstEntities(const AZStd::function& callback); - void GetNestedEntities(const AZStd::function&)>& callback); void GetEntities(const AZStd::function&)>& callback); + void GetConstEntities(const AZStd::function& callback) const; + void GetAllEntitiesInHierarchy(const AZStd::function&)>& callback); + void GetAllEntitiesInHierarchyConst(const AZStd::function& callback) const; void GetNestedInstances(const AZStd::function&)>& callback); /** @@ -184,12 +184,6 @@ namespace AzToolsFramework static InstanceAlias GenerateInstanceAlias(); - protected: - /** - * Gets the entities owned by this instance - */ - void GetEntities(EntityList& entities, bool includeNestedEntities = false); - private: static constexpr const char s_aliasPathSeparator = '/'; @@ -197,6 +191,11 @@ namespace AzToolsFramework void RemoveEntities(const AZStd::function&)>& filter); + bool GetEntities_Impl(const AZStd::function&)>& callback); + bool GetConstEntities_Impl(const AZStd::function& callback) const; + bool GetAllEntitiesInHierarchy_Impl(const AZStd::function&)>& callback); + bool GetAllEntitiesInHierarchyConst_Impl(const AZStd::function& callback) const; + bool RegisterEntity(const AZ::EntityId& entityId, const EntityAlias& entityAlias); AZStd::unique_ptr DetachEntity(const EntityAlias& entityAlias); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp index 6480ac37d7..cc04fe24c1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.cpp @@ -62,25 +62,16 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils } } - AZStd::vector EditorInfoRemover::GetEntitiesFromInstance(AZStd::unique_ptr& instance) + void EditorInfoRemover::GetEntitiesFromInstance( + AZStd::unique_ptr& instance, EntityList& hierarchyEntities) { - AZStd::vector result; - - instance->GetNestedEntities( - [&result](const AZStd::unique_ptr& entity) + instance->GetAllEntitiesInHierarchy( + [&hierarchyEntities](const AZStd::unique_ptr& entity) { - result.emplace_back(entity.get()); + hierarchyEntities.emplace_back(entity.get()); return true; } ); - - if (instance->HasContainerEntity()) - { - auto containerEntityReference = instance->GetContainerEntity(); - result.emplace_back(&containerEntityReference->get()); - } - - return result; } void EditorInfoRemover::SetEditorOnlyEntityHandlerFromCandidates(const EntityList& entities) @@ -543,7 +534,9 @@ exportComponent, prefabProcessorContext); } // grab all nested entities from the Instance as source entities. - EntityList sourceEntities = GetEntitiesFromInstance(instance); + EntityList sourceEntities; + GetEntitiesFromInstance(instance, sourceEntities); + EntityList exportEntities; // prepare for validation of component requirements. @@ -616,7 +609,7 @@ exportComponent, prefabProcessorContext); ); // replace entities of instance with exported ones. - instance->GetNestedEntities( + instance->GetAllEntitiesInHierarchy( [&exportEntitiesMap](AZStd::unique_ptr& entity) { auto entityId = entity->GetId(); @@ -625,14 +618,6 @@ exportComponent, prefabProcessorContext); } ); - if (instance->HasContainerEntity()) - { - if (auto found = exportEntitiesMap.find(instance->GetContainerEntityId()); found != exportEntitiesMap.end()) - { - instance->SetContainerEntity(*found->second); - } - } - // save the final result in the target Prefab DOM. PrefabDom filteredPrefab; if (!PrefabDomUtils::StoreInstanceInPrefabDom(*instance, filteredPrefab)) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h index 1e00485e42..5de5c516f8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/EditorInfoRemover.h @@ -55,8 +55,8 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils protected: using EntityList = AZStd::vector; - static EntityList GetEntitiesFromInstance( - AZStd::unique_ptr& instance); + static void GetEntitiesFromInstance( + AZStd::unique_ptr& instance, EntityList& hierarchyEntities); static bool ReadComponentAttribute( AZ::Component* component, diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUpdateWithPatchesTests.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUpdateWithPatchesTests.cpp index aef3cad5f3..e3460c307f 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUpdateWithPatchesTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabUpdateWithPatchesTests.cpp @@ -93,7 +93,7 @@ namespace UnitTest // Retrieve the entity pointer from the component application bus. AZ::Entity* wheelEntityUnderAxle = nullptr; - axleInstance->GetNestedEntities([&wheelEntityUnderAxle, wheelEntityIdUnderAxle](AZStd::unique_ptr& entity) + axleInstance->GetAllEntitiesInHierarchy([&wheelEntityUnderAxle, wheelEntityIdUnderAxle](AZStd::unique_ptr& entity) { if (entity->GetId() == wheelEntityIdUnderAxle) {