Selaa lähdekoodia

Atom Level component test support in editor_entity_utils.py and tests for level components (#6082)

* Level component helper and test cases for Atom Level components which currently crash

Signed-off-by: Scott Murray <[email protected]>

* moved a close paren to end of previous line to match existing style

Signed-off-by: Scott Murray <[email protected]>

* adding a forgotten import

Signed-off-by: Scott Murray <[email protected]>

* minor refactor and prep for adding back the Display Mapper Game component test

Signed-off-by: Scott Murray <[email protected]>

* putting Game compoenent Display Mapper test back with addition of setting property Enabled to true

Signed-off-by: Scott Murray <[email protected]>

* typo in line fixed Test. bocomes Tests.

Signed-off-by: Scott Murray <[email protected]>
smurly 3 vuotta sitten
vanhempi
commit
e3306f948f

+ 15 - 0
AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py

@@ -12,6 +12,7 @@ import pytest
 import ly_test_tools.environment.file_system as file_system
 import editor_python_test_tools.hydra_test_utils as hydra
 
+from ly_test_tools.o3de.editor_test import EditorSharedTest, EditorTestSuite
 from Atom.atom_utils.atom_constants import LIGHT_TYPES
 
 logger = logging.getLogger(__name__)
@@ -159,3 +160,17 @@ class TestMaterialEditorBasicTests(object):
             enable_prefab_system=False,
         )
 
+
[email protected]("project", ["AutomatedTesting"])
[email protected]("launcher_platform", ['windows_editor'])
+class TestAutomation(EditorTestSuite):
+
+    enable_prefab_system = False
+
+    @pytest.mark.test_case_id("C36529666")
+    class AtomEditorComponentsLevel_DiffuseGlobalIlluminationAdded(EditorSharedTest):
+        from Atom.tests import hydra_AtomEditorComponentsLevel_DiffuseGlobalIlluminationAdded as test_module
+
+    @pytest.mark.test_case_id("C36525660")
+    class AtomEditorComponentsLevel_DisplayMapperAdded(EditorSharedTest):
+        from Atom.tests import hydra_AtomEditorComponentsLevel_DisplayMapperAdded as test_module

+ 25 - 1
AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py

@@ -18,6 +18,13 @@ LIGHT_TYPES = {
     'simple_spot': 7,
 }
 
+# Qualiity Level settings for Diffuse Global Illumination level component
+GLOBAL_ILLUMINATION_QUALITY = {
+    'Low': 0,
+    'Medium': 1,
+    'High': 2,
+}
+
 
 class AtomComponentProperties:
     """
@@ -116,6 +123,21 @@ class AtomComponentProperties:
         }
         return properties[property]
 
+    @staticmethod
+    def diffuse_global_illumination(property: str = 'name') -> str:
+        """
+        Diffuse Global Illumination level component properties.
+        Controls global settings for Diffuse Probe Grid components.
+          - 'Quality Level' from atom_constants.py GLOBAL_ILLUMINATION_QUALITY
+        :param property: From the last element of the property tree path. Default 'name' for component name string.
+        :return: Full property path OR component name if no property specified.
+        """
+        properties = {
+            'name': 'Diffuse Global Illumination',
+            'Quality Level': 'Controller|Configuration|Quality Level'
+        }
+        return properties[property]
+
     @staticmethod
     def diffuse_probe_grid(property: str = 'name') -> str:
         """
@@ -148,7 +170,8 @@ class AtomComponentProperties:
     @staticmethod
     def display_mapper(property: str = 'name') -> str:
         """
-        Display Mapper component properties.
+        Display Mapper level component properties.
+          - 'Enable LDR color grading LUT' toggles the use of LDR color grading LUT
           - 'LDR color Grading LUT' is the Low Definition Range (LDR) color grading for Look-up Textures (LUT) which is
             an Asset.id value corresponding to a lighting asset file.
         :param property: From the last element of the property tree path. Default 'name' for component name string.
@@ -156,6 +179,7 @@ class AtomComponentProperties:
         """
         properties = {
             'name': 'Display Mapper',
+            'Enable LDR color grading LUT': 'Controller|Configuration|Enable LDR color grading LUT',
             'LDR color Grading LUT': 'Controller|Configuration|LDR color Grading LUT',
         }
         return properties[property]

+ 109 - 0
AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponentsLevel_DiffuseGlobalIlluminationAdded.py

@@ -0,0 +1,109 @@
+"""
+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
+"""
+
+class Tests:
+    creation_undo = (
+        "UNDO Level component addition success",
+        "UNDO Level component addition failed")
+    creation_redo = (
+        "REDO Level component addition success",
+        "REDO Level component addition failed")
+    diffuse_global_illumination_component = (
+        "Level has a Diffuse Global Illumination component",
+        "Level failed to find Diffuse Global Illumination component")
+    diffuse_global_illumination_quality = (
+        "Quality Level set",
+        "Quality Level could not be set")
+    enter_game_mode = (
+        "Entered game mode",
+        "Failed to enter game mode")
+    exit_game_mode = (
+        "Exited game mode",
+        "Couldn't exit game mode")
+
+
+def AtomEditorComponentsLevel_DiffuseGlobalIllumination_AddedToEntity():
+    """
+    Summary:
+    Tests the Diffuse Global Illumination level component can be added to the level entity and is stable.
+
+    Test setup:
+    - Wait for Editor idle loop.
+    - Open the "Base" level.
+
+    Expected Behavior:
+    The component can be added, used in game mode, and has accurate required components.
+    Creation and deletion undo/redo should also work.
+
+    Test Steps:
+    1) Add Diffuse Global Illumination level component to the level entity.
+    2) UNDO the level component addition.
+    3) REDO the level component addition.
+    4) Set Quality Level property to Low
+    5) Enter/Exit game mode.
+    6) Look for errors and asserts.
+
+    :return: None
+    """
+
+    import azlmbr.legacy.general as general
+
+    from editor_python_test_tools.editor_entity_utils import EditorLevelEntity
+    from editor_python_test_tools.utils import Report, Tracer, TestHelper
+    from Atom.atom_utils.atom_constants import AtomComponentProperties, GLOBAL_ILLUMINATION_QUALITY
+
+    with Tracer() as error_tracer:
+        # Test setup begins.
+        # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
+        TestHelper.init_idle()
+        TestHelper.open_level("", "Base")
+
+        # Test steps begin.
+        # 1. Add Diffuse Global Illumination level component to the level entity.
+        diffuse_global_illumination_component = EditorLevelEntity.add_component(
+            AtomComponentProperties.diffuse_global_illumination())
+        Report.critical_result(
+            Tests.diffuse_global_illumination_component,
+            EditorLevelEntity.has_component(AtomComponentProperties.diffuse_global_illumination()))
+
+        # 2. UNDO the level component addition.
+        # -> UNDO component addition.
+        general.undo()
+        general.idle_wait_frames(1)
+        Report.result(Tests.creation_undo,
+                      not EditorLevelEntity.has_component(AtomComponentProperties.diffuse_global_illumination()))
+
+        # 3. REDO the level component addition.
+        # -> REDO component addition.
+        general.redo()
+        general.idle_wait_frames(1)
+        Report.result(Tests.creation_redo,
+                      EditorLevelEntity.has_component(AtomComponentProperties.diffuse_global_illumination()))
+
+        # 4. Set Quality Level property to Low
+        diffuse_global_illumination_component.set_component_property_value(
+            AtomComponentProperties.diffuse_global_illumination('Quality Level', GLOBAL_ILLUMINATION_QUALITY['Low']))
+        quality = diffuse_global_illumination_component.get_component_property_value(
+            AtomComponentProperties.diffuse_global_illumination('Quality Level'))
+        Report.result(diffuse_global_illumination_quality, quality == GLOBAL_ILLUMINATION_QUALITY['Low'])
+
+        # 5. Enter/Exit game mode.
+        TestHelper.enter_game_mode(Tests.enter_game_mode)
+        general.idle_wait_frames(1)
+        TestHelper.exit_game_mode(Tests.exit_game_mode)
+
+        # 6. Look for errors and asserts.
+        TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
+        for error_info in error_tracer.errors:
+            Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
+        for assert_info in error_tracer.asserts:
+            Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
+
+
+if __name__ == "__main__":
+    from editor_python_test_tools.utils import Report
+    Report.start_test(AtomEditorComponentsLevel_DiffuseGlobalIllumination_AddedToEntity)

+ 124 - 0
AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponentsLevel_DisplayMapperAdded.py

@@ -0,0 +1,124 @@
+"""
+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
+"""
+
+
+class Tests:
+    creation_undo = (
+        "UNDO level component addition success",
+        "UNDO level component addition failed")
+    creation_redo = (
+        "REDO Level component addition success",
+        "REDO Level component addition failed")
+    display_mapper_component = (
+        "Level has a Display Mapper component",
+        "Level failed to find Display Mapper component")
+    ldr_color_grading_lut = (
+        "LDR color Grading LUT asset set",
+        "LDR color Grading LUT asset could not be set")
+    enable_ldr_color_grading_lut = (
+        "Enable LDR color grading LUT set",
+        "Enable LDR color grading LUT could not be set")
+    enter_game_mode = (
+        "Entered game mode",
+        "Failed to enter game mode")
+    exit_game_mode = (
+        "Exited game mode",
+        "Couldn't exit game mode")
+
+
+def AtomEditorComponentsLevel_DisplayMapper_AddedToEntity():
+    """
+    Summary:
+    Tests the Display Mapper level component can be added to the level entity and has the expected functionality.
+
+    Test setup:
+    - Wait for Editor idle loop.
+    - Open the "Base" level.
+
+    Expected Behavior:
+    The component can be added, used in game mode, and has accurate required components.
+    Creation and deletion undo/redo should also work.
+
+    Test Steps:
+    1) Add Display Mapper level component to the level entity.
+    2) UNDO the level component addition.
+    3) REDO the level component addition.
+    4) Set LDR color Grading LUT asset.
+    5) Set Enable LDR color grading LUT property True
+    6) Enter/Exit game mode.
+    7) Look for errors and asserts.
+
+    :return: None
+    """
+    import os
+
+    import azlmbr.legacy.general as general
+
+    from editor_python_test_tools.asset_utils import Asset
+    from editor_python_test_tools.editor_entity_utils import EditorLevelEntity
+    from editor_python_test_tools.utils import Report, Tracer, TestHelper
+    from Atom.atom_utils.atom_constants import AtomComponentProperties
+
+    with Tracer() as error_tracer:
+        # Test setup begins.
+        # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
+        TestHelper.init_idle()
+        TestHelper.open_level("", "Base")
+
+        # Test steps begin.
+        # 1. Add Display Mapper level component to the level entity.
+        display_mapper_component = EditorLevelEntity.add_component(AtomComponentProperties.display_mapper())
+        Report.critical_result(
+            Tests.display_mapper_component,
+            EditorLevelEntity.has_component(AtomComponentProperties.display_mapper()))
+
+        # 2. UNDO the level component addition.
+        # -> UNDO component addition.
+        general.undo()
+        general.idle_wait_frames(1)
+        Report.result(Tests.creation_undo, not EditorLevelEntity.has_component(AtomComponentProperties.display_mapper()))
+
+        # 3. REDO the level component addition.
+        # -> REDO component addition.
+        general.redo()
+        general.idle_wait_frames(1)
+        Report.result(Tests.creation_redo, EditorLevelEntity.has_component(AtomComponentProperties.display_mapper()))
+
+        # 4. Set LDR color Grading LUT asset.
+        display_mapper_asset_path = os.path.join("TestData", "test.lightingpreset.azasset")
+        display_mapper_asset = Asset.find_asset_by_path(display_mapper_asset_path, False)
+        display_mapper_component.set_component_property_value(
+            AtomComponentProperties.display_mapper('LDR color Grading LUT'), display_mapper_asset.id)
+        Report.result(
+            Tests.ldr_color_grading_lut,
+            display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('LDR color Grading LUT')) == display_mapper_asset.id)
+
+        # 5. Set Enable LDR color grading LUT property True
+        display_mapper_component.set_component_property_value(
+            AtomComponentProperties.display_mapper('Enable LDR color grading LUT'), True)
+        Report.result(
+            Test.enable_ldr_color_grading_lut,
+            display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Enable LDR color grading LUT')) is True)
+
+        # 6. Enter/Exit game mode.
+        TestHelper.enter_game_mode(Tests.enter_game_mode)
+        general.idle_wait_frames(1)
+        TestHelper.exit_game_mode(Tests.exit_game_mode)
+
+        # 7. Look for errors and asserts.
+        TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
+        for error_info in error_tracer.errors:
+            Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
+        for assert_info in error_tracer.asserts:
+            Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
+
+
+if __name__ == "__main__":
+    from editor_python_test_tools.utils import Report
+    Report.start_test(AtomEditorComponentsLevel_DisplayMapper_AddedToEntity)

+ 37 - 34
AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DisplayMapperAdded.py

@@ -7,15 +7,6 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
 
 
 class Tests:
-    camera_creation = (
-        "Camera Entity successfully created",
-        "Camera Entity failed to be created")
-    camera_component_added = (
-        "Camera component was added to entity",
-        "Camera component failed to be added to entity")
-    camera_component_check = (
-        "Entity has a Camera component",
-        "Entity failed to find Camera component")
     creation_undo = (
         "UNDO Entity creation success",
         "UNDO Entity creation failed")
@@ -43,6 +34,9 @@ class Tests:
     ldr_color_grading_lut = (
         "LDR color Grading LUT asset set",
         "LDR color Grading LUT asset could not be set")
+    enable_ldr_color_grading_lut = (
+        "Enable LDR color grading LUT set",
+        "Enable LDR color grading LUT could not be set")
     entity_deleted = (
         "Entity deleted",
         "Entity was not deleted")
@@ -72,14 +66,15 @@ def AtomEditorComponents_DisplayMapper_AddedToEntity():
     2) Add Display Mapper component to Display Mapper entity.
     3) UNDO the entity creation and component addition.
     4) REDO the entity creation and component addition.
-    5) Enter/Exit game mode.
-    6) Test IsHidden.
-    7) Test IsVisible.
-    8) Set LDR color Grading LUT asset.
-    9) Delete Display Mapper entity.
-    10) UNDO deletion.
-    11) REDO deletion.
-    12) Look for errors and asserts.
+    5) Set LDR color Grading LUT asset.
+    6) Set Enable LDR color grading LUT property True
+    7) Enter/Exit game mode.
+    8) Test IsHidden.
+    9) Test IsVisible.
+    10) Delete Display Mapper entity.
+    11) UNDO deletion.
+    12) REDO deletion.
+    13) Look for errors and asserts.
 
     :return: None
     """
@@ -133,43 +128,51 @@ def AtomEditorComponents_DisplayMapper_AddedToEntity():
         general.idle_wait_frames(1)
         Report.result(Tests.creation_redo, display_mapper_entity.exists())
 
-        # 5. Enter/Exit game mode.
+        # 5. Set LDR color Grading LUT asset.
+        display_mapper_asset_path = os.path.join("TestData", "test.lightingpreset.azasset")
+        display_mapper_asset = Asset.find_asset_by_path(display_mapper_asset_path, False)
+        display_mapper_component.set_component_property_value(
+            AtomComponentProperties.display_mapper("LDR color Grading LUT"), display_mapper_asset.id)
+        Report.result(
+            Tests.ldr_color_grading_lut,
+            display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper("LDR color Grading LUT")) == display_mapper_asset.id)
+
+        # 6. Set Enable LDR color grading LUT property True
+        display_mapper_component.set_component_property_value(
+            AtomComponentProperties.display_mapper('Enable LDR color grading LUT'), True)
+        Report.result(
+            Tests.enable_ldr_color_grading_lut,
+            display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Enable LDR color grading LUT')) is True)
+
+        # 7. Enter/Exit game mode.
         TestHelper.enter_game_mode(Tests.enter_game_mode)
         general.idle_wait_frames(1)
         TestHelper.exit_game_mode(Tests.exit_game_mode)
 
-        # 6. Test IsHidden.
+        # 8. Test IsHidden.
         display_mapper_entity.set_visibility_state(False)
         Report.result(Tests.is_hidden, display_mapper_entity.is_hidden() is True)
 
-        # 7. Test IsVisible.
+        # 9. Test IsVisible.
         display_mapper_entity.set_visibility_state(True)
         general.idle_wait_frames(1)
         Report.result(Tests.is_visible, display_mapper_entity.is_visible() is True)
 
-        # 8. Set LDR color Grading LUT asset.
-        display_mapper_asset_path = os.path.join("TestData", "test.lightingpreset.azasset")
-        display_mapper_asset = Asset.find_asset_by_path(display_mapper_asset_path, False)
-        display_mapper_component.set_component_property_value(
-            AtomComponentProperties.display_mapper("LDR color Grading LUT"), display_mapper_asset.id)
-        Report.result(
-            Tests.ldr_color_grading_lut,
-            display_mapper_component.get_component_property_value(
-                AtomComponentProperties.display_mapper("LDR color Grading LUT")) == display_mapper_asset.id)
-
-        # 9. Delete Display Mapper entity.
+        # 10. Delete Display Mapper entity.
         display_mapper_entity.delete()
         Report.result(Tests.entity_deleted, not display_mapper_entity.exists())
 
-        # 10. UNDO deletion.
+        # 11. UNDO deletion.
         general.undo()
         Report.result(Tests.deletion_undo, display_mapper_entity.exists())
 
-        # 11. REDO deletion.
+        # 12. REDO deletion.
         general.redo()
         Report.result(Tests.deletion_redo, not display_mapper_entity.exists())
 
-        # 12. Look for errors and asserts.
+        # 13. Look for errors and asserts.
         TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
         for error_info in error_tracer.errors:
             Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")

+ 97 - 1
AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py

@@ -107,7 +107,6 @@ class EditorComponent:
         return type_ids
 
 
-
 def convert_to_azvector3(xyz) -> azlmbr.math.Vector3:
     """
     Converts a vector3-like element into a azlmbr.math.Vector3
@@ -120,6 +119,7 @@ def convert_to_azvector3(xyz) -> azlmbr.math.Vector3:
     else:
         raise ValueError("vector must be a 3 element list/tuple or azlmbr.math.Vector3")
 
+
 class EditorEntity:
     """
     Entity class is used to create and interact with Editor Entities.
@@ -470,3 +470,99 @@ class EditorEntity:
         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()}"
+
+
+class EditorLevelEntity:
+    """
+    EditorLevel class used to add and fetch level components.
+    Level entity is a special entity that you do not create/destroy independently of larger systems of level creation.
+    This collects a number of staticmethods that do not rely on entityId since Level entity is found internally by
+    EditorLevelComponentAPIBus requests.
+    """
+
+    @staticmethod
+    def get_type_ids(component_names: list) -> list:
+        """
+        Used to get type ids of given components list for EntityType Level
+        :param: component_names: List of components to get type ids
+        :return: List of type ids of given components.
+        """
+        type_ids = editor.EditorComponentAPIBus(
+            bus.Broadcast, "FindComponentTypeIdsByEntityType", component_names, azlmbr.entity.EntityType().Level
+        )
+        return type_ids
+
+    @staticmethod
+    def add_component(component_name: str) -> EditorComponent:
+        """
+        Used to add new component to Level.
+        :param component_name: String of component name to add.
+        :return: Component object of newly added component.
+        """
+        component = EditorLevelEntity.add_components([component_name])[0]
+        return component
+
+    @staticmethod
+    def add_components(component_names: list) -> List[EditorComponent]:
+        """
+        Used to add multiple components
+        :param: component_names: List of components to add to level
+        :return: List of newly added components to the level
+        """
+        components = []
+        type_ids = EditorLevelEntity.get_type_ids(component_names)
+        for type_id in type_ids:
+            new_comp = EditorComponent()
+            new_comp.type_id = type_id
+            add_component_outcome = editor.EditorLevelComponentAPIBus(
+                bus.Broadcast, "AddComponentsOfType", [type_id]
+            )
+            assert (
+                add_component_outcome.IsSuccess()
+            ), f"Failure: Could not add component: '{new_comp.get_component_name()}' to level"
+            new_comp.id = add_component_outcome.GetValue()[0]
+            components.append(new_comp)
+        return components
+
+    @staticmethod
+    def get_components_of_type(component_names: list) -> List[EditorComponent]:
+        """
+        Used to get components of type component_name that already exists on the level
+        :param component_names: List of names of components to check
+        :return: List of Level Component objects of given component name
+        """
+        component_list = []
+        type_ids = EditorLevelEntity.get_type_ids(component_names)
+        for type_id in type_ids:
+            component = EditorComponent()
+            component.type_id = type_id
+            get_component_of_type_outcome = editor.EditorLevelComponentAPIBus(
+                bus.Broadcast, "GetComponentOfType", type_id
+            )
+            assert (
+                get_component_of_type_outcome.IsSuccess()
+            ), f"Failure: Level does not have component:'{component.get_component_name()}'"
+            component.id = get_component_of_type_outcome.GetValue()
+            component_list.append(component)
+
+        return component_list
+
+    @staticmethod
+    def has_component(component_name: str) -> bool:
+        """
+        Used to verify if the level has the specified component
+        :param component_name: Name of component to check for
+        :return: True, if level has specified component. Else, False
+        """
+        type_ids = EditorLevelEntity.get_type_ids([component_name])
+        return editor.EditorLevelComponentAPIBus(bus.Broadcast, "HasComponentOfType", type_ids[0])
+
+    @staticmethod
+    def count_components_of_type(component_name: str) -> int:
+        """
+        Used to get a count of the specified level component attached to the level
+        :param component_name: Name of component to check for
+        :return: integer count of occurences of level component attached to level or zero if none are present
+        """
+        type_ids = EditorLevelEntity.get_type_ids([component_name])
+        return editor.EditorLevelComponentAPIBus(bus.Broadcast, "CountComponentsOfType", type_ids[0])