From 4dd9e94bc34c3108bad5b8203eebae8ec181b94a Mon Sep 17 00:00:00 2001 From: srikappa-amzn <82230713+srikappa-amzn@users.noreply.github.com> Date: Tue, 30 Nov 2021 21:50:25 +0530 Subject: [PATCH] Add tests for deleting an entity from the level and from another prefab (#5839) * Added tests for deleting entity under level and other prefabs Signed-off-by: srikappa-amzn <82230713+srikappa-amzn@users.noreply.github.com> * Added class comments and improved variable names Signed-off-by: srikappa-amzn <82230713+srikappa-amzn@users.noreply.github.com> * Called the reflect function of PrefabFocusHandler from PrefabSystemComponent Signed-off-by: srikappa-amzn <82230713+srikappa-amzn@users.noreply.github.com> * Added function comments and made an if statement to be one line Signed-off-by: srikappa-amzn <82230713+srikappa-amzn@users.noreply.github.com> --- .../editor_entity_utils.py | 11 ++++ .../Gem/PythonTests/Prefab/TestSuite_Main.py | 8 +++ .../DeleteEntity_UnderAnotherPrefab.py | 52 +++++++++++++++++++ .../DeleteEntity_UnderLevelPrefab.py | 37 +++++++++++++ .../Prefab/PrefabFocusHandler.cpp | 14 +++++ .../Prefab/PrefabFocusHandler.h | 8 +-- .../Prefab/PrefabFocusPublicInterface.h | 14 +++++ .../Prefab/PrefabSystemComponent.cpp | 1 + 8 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 AutomatedTesting/Gem/PythonTests/Prefab/tests/delete_entity/DeleteEntity_UnderAnotherPrefab.py create mode 100644 AutomatedTesting/Gem/PythonTests/Prefab/tests/delete_entity/DeleteEntity_UnderLevelPrefab.py diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py index 59e454479c..309601b0ba 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py @@ -459,3 +459,14 @@ class EditorEntity: """ new_translation = convert_to_azvector3(new_translation) azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalTranslation", self.id, new_translation) + + # Use this only when prefab system is enabled as it will fail otherwise. + def focus_on_owning_prefab(self) -> None: + """ + Focuses on the owning prefab instance of the given entity. + :param entity: The entity used to fetch the owning prefab to focus on. + """ + + assert self.id.isValid(), "A valid entity id is required to focus on its owning prefab." + focus_prefab_result = azlmbr.prefab.PrefabFocusPublicRequestBus(bus.Broadcast, "FocusOnOwningPrefab", self.id) + assert focus_prefab_result.IsSuccess(), f"Prefab operation 'FocusOnOwningPrefab' failed. Error: {focus_prefab_result.GetError()}" diff --git a/AutomatedTesting/Gem/PythonTests/Prefab/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/Prefab/TestSuite_Main.py index c1d4836342..6e1f94d358 100644 --- a/AutomatedTesting/Gem/PythonTests/Prefab/TestSuite_Main.py +++ b/AutomatedTesting/Gem/PythonTests/Prefab/TestSuite_Main.py @@ -61,3 +61,11 @@ class TestAutomation(TestAutomationBase): def test_CreatePrefab_UnderAnotherPrefab(self, request, workspace, editor, launcher_platform): from Prefab.tests.create_prefab import CreatePrefab_UnderAnotherPrefab as test_module self._run_prefab_test(request, workspace, editor, test_module, autotest_mode=False) + + def test_DeleteEntity_UnderAnotherPrefab(self, request, workspace, editor, launcher_platform): + from Prefab.tests.delete_entity import DeleteEntity_UnderAnotherPrefab as test_module + self._run_prefab_test(request, workspace, editor, test_module, autotest_mode=False) + + def test_DeleteEntity_UnderLevelPrefab(self, request, workspace, editor, launcher_platform): + from Prefab.tests.delete_entity import DeleteEntity_UnderLevelPrefab as test_module + self._run_prefab_test(request, workspace, editor, test_module, autotest_mode=False) diff --git a/AutomatedTesting/Gem/PythonTests/Prefab/tests/delete_entity/DeleteEntity_UnderAnotherPrefab.py b/AutomatedTesting/Gem/PythonTests/Prefab/tests/delete_entity/DeleteEntity_UnderAnotherPrefab.py new file mode 100644 index 0000000000..deaaaedf30 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/Prefab/tests/delete_entity/DeleteEntity_UnderAnotherPrefab.py @@ -0,0 +1,52 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +def DeleteEntity_UnderAnotherPrefab(): + """ + Test description: + - Creates an entity. + - Creates a prefab out of the above entity. + - Focuses on the created prefab and destroys the entity within. + Checks that the entity is correctly destroyed. + """ + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.prefab_utils import Prefab + + import Prefab.tests.PrefabTestUtils as prefab_test_utils + + prefab_test_utils.open_base_tests_level() + + PREFAB_FILE_NAME = 'some_prefab' + + # Creates a new entity at the root level + entity = EditorEntity.create_editor_entity() + assert entity.id.IsValid(), "Couldn't create entity." + + # Asserts if prefab creation doesn't succeed + child_prefab, child_instance = Prefab.create_prefab([entity], PREFAB_FILE_NAME) + child_entity_ids_inside_prefab = child_instance.get_direct_child_entities() + assert len( + child_entity_ids_inside_prefab) == 1, f"{len(child_entity_ids_inside_prefab)} entities found inside prefab" \ + f" when there should have been just 1 entity" + + child_entity_inside_prefab = child_entity_ids_inside_prefab[0] + child_entity_inside_prefab.focus_on_owning_prefab() + + child_entity_inside_prefab.delete() + + # Wait till prefab propagation finishes before validating entity deletion. + azlmbr.legacy.general.idle_wait_frames(1) + + child_entity_ids_inside_prefab = child_instance.get_direct_child_entities() + assert len( + child_entity_ids_inside_prefab) == 0, f"{len(child_entity_ids_inside_prefab)} entities found inside prefab" \ + f" when there should have been 0 entities" + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(DeleteEntity_UnderAnotherPrefab) diff --git a/AutomatedTesting/Gem/PythonTests/Prefab/tests/delete_entity/DeleteEntity_UnderLevelPrefab.py b/AutomatedTesting/Gem/PythonTests/Prefab/tests/delete_entity/DeleteEntity_UnderLevelPrefab.py new file mode 100644 index 0000000000..807427718c --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/Prefab/tests/delete_entity/DeleteEntity_UnderLevelPrefab.py @@ -0,0 +1,37 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +def DeleteEntity_UnderLevelPrefab(): + """ + Test description: + - Creates an entity. + - Destroys the created entity. + Checks that the entity is correctly destroyed. + """ + + from editor_python_test_tools.editor_entity_utils import EditorEntity + import Prefab.tests.PrefabTestUtils as prefab_test_utils + + prefab_test_utils.open_base_tests_level() + + # Creates a new Entity at the root level + # Asserts if creation didn't succeed + entity = EditorEntity.create_editor_entity_at((100.0, 100.0, 100.0), name = "TestEntity") + assert entity.id.IsValid(), "Couldn't create entity" + + level_container_entity = EditorEntity(entity.get_parent_id()) + entity.delete() + + # Wait till prefab propagation finishes before validating entity deletion. + azlmbr.legacy.general.idle_wait_frames(1) + level_container_child_entities_count = len(level_container_entity.get_children_ids()) + assert level_container_child_entities_count == 0, f"The level still has {level_container_child_entities_count}" \ + f" children when it should have 0." + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(DeleteEntity_UnderLevelPrefab) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index f20c11a1d8..2ab68bfc10 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -34,10 +34,12 @@ namespace AzToolsFramework::Prefab PrefabPublicNotificationBus::Handler::BusConnect(); AZ::Interface::Register(this); AZ::Interface::Register(this); + PrefabFocusPublicRequestBus::Handler::BusConnect(); } PrefabFocusHandler::~PrefabFocusHandler() { + PrefabFocusPublicRequestBus::Handler::BusDisconnect(); AZ::Interface::Unregister(this); AZ::Interface::Unregister(this); PrefabPublicNotificationBus::Handler::BusDisconnect(); @@ -45,6 +47,18 @@ namespace AzToolsFramework::Prefab EditorEntityInfoNotificationBus::Handler::BusDisconnect(); } + void PrefabFocusHandler::Reflect(AZ::ReflectContext* context) + { + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context); behaviorContext) + { + behaviorContext->EBus("PrefabFocusPublicRequestBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) + ->Attribute(AZ::Script::Attributes::Category, "Prefab") + ->Attribute(AZ::Script::Attributes::Module, "prefab") + ->Event("FocusOnOwningPrefab", &PrefabFocusPublicInterface::FocusOnOwningPrefab); + } + } + void PrefabFocusHandler::InitializeEditorInterfaces() { m_containerEntityInterface = AZ::Interface::Get(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h index 2e23059a01..b02106d69d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h @@ -30,8 +30,8 @@ namespace AzToolsFramework::Prefab //! Handles Prefab Focus mode, determining which prefab file entity changes will target. class PrefabFocusHandler final - : private PrefabFocusInterface - , private PrefabFocusPublicInterface + : public PrefabFocusPublicRequestBus::Handler + , private PrefabFocusInterface , private PrefabPublicNotificationBus::Handler , private EditorEntityContextNotificationBus::Handler , private EditorEntityInfoNotificationBus::Handler @@ -42,13 +42,15 @@ namespace AzToolsFramework::Prefab PrefabFocusHandler(); ~PrefabFocusHandler(); + static void Reflect(AZ::ReflectContext* context); + // PrefabFocusInterface overrides ... void InitializeEditorInterfaces() override; PrefabFocusOperationResult FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId) override; TemplateId GetFocusedPrefabTemplateId(AzFramework::EntityContextId entityContextId) const override; InstanceOptionalReference GetFocusedPrefabInstance(AzFramework::EntityContextId entityContextId) const override; - // PrefabFocusPublicInterface overrides ... + // PrefabFocusPublicInterface and PrefabFocusPublicRequestBus overrides ... PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) override; PrefabFocusOperationResult FocusOnParentOfFocusedPrefab(AzFramework::EntityContextId entityContextId) override; PrefabFocusOperationResult FocusOnPathIndex(AzFramework::EntityContextId entityContextId, int index) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h index 2fc9ef6b9a..2c0e95f1cc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h @@ -58,4 +58,18 @@ namespace AzToolsFramework::Prefab virtual const int GetPrefabFocusPathLength(AzFramework::EntityContextId entityContextId) const = 0; }; + /** + * The primary purpose of this bus is to facilitate writing automated tests for prefab focus mode. + * If you would like to integrate prefabs focus mode into your system, please call PrefabFocusPublicInterface + * for better performance. + */ + class PrefabFocusPublicRequests + : public AZ::EBusTraits + { + public: + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + }; + + using PrefabFocusPublicRequestBus = AZ::EBus; + } // namespace AzToolsFramework::Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 62d7a6ac1d..ed16606413 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -60,6 +60,7 @@ namespace AzToolsFramework AzToolsFramework::Prefab::PrefabConversionUtils::PrefabCatchmentProcessor::Reflect(context); AzToolsFramework::Prefab::PrefabConversionUtils::EditorInfoRemover::Reflect(context); PrefabPublicRequestHandler::Reflect(context); + PrefabFocusHandler::Reflect(context); PrefabLoader::Reflect(context); PrefabSystemScriptingHandler::Reflect(context);