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 72530325e0..b9f7576f1c 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 @@ -29,6 +29,11 @@ class EditorComponent: which also assigns self.id and self.type_id to the EditorComponent object. """ + def __init__(self, type_id): + self.type_id = type_id + self.id = None + self.property_tree = None + def get_component_name(self) -> str: """ Used to get name of component @@ -50,6 +55,9 @@ class EditorComponent: 7. prop_tree.get_container_item(path, key) :return: Property tree object of a component """ + if self.property_tree is not None: + return self.property_tree + build_prop_tree_outcome = editor.EditorComponentAPIBus( bus.Broadcast, "BuildComponentPropertyTreeEditor", self.id ) @@ -58,7 +66,114 @@ class EditorComponent: ), f"Failure: Could not build property tree of component: '{self.get_component_name()}'" prop_tree = build_prop_tree_outcome.GetValue() Report.info(prop_tree.build_paths_list()) - return prop_tree + self.property_tree = prop_tree + return self.property_tree + + def is_property_container(self, component_property_path: str) -> bool: + """ + + """ + if self.property_tree is None: + self.get_property_tree() + result = self.property_tree.is_container(component_property_path) + if not result: + Report.info(f"{self.get_component_name()}: '{component_property_path}' is not a container") + return result + + def get_container_count(self, component_property_path: str) -> int: + """ + Used to get the count of items in the container. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :return: Count of items in the container as unsigned integer + """ + if self.is_property_container(component_property_path): + container_count_outcome = self.property_tree.get_container_count(component_property_path) + assert ( + container_count_outcome.IsSuccess() + ), f"Failure: get_container_count did not return success for '{component_property_path}'" + return container_count_outcome.GetValue() + + def reset_container(self, component_property_path: str) -> bool: + """ + Used to rest a container to empty + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :return: Boolean success + """ + if self.is_property_container(component_property_path): + reset_outcome = self.property_tree.reset_container(component_property_path) + return reset_outcome.IsSuccess() + else: + return False + + def append_container_item(self, component_property_path: str, value: any) -> bool: + """ + Used to append a container item without providing an index key. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :param value: Value to be set + :return: Boolean success + """ + if self.is_property_container(component_property_path): + append_outcome = self.property_tree.append_container_item(component_property_path, value) + return append_outcome.IsSuccess() + else: + return False + + def add_container_item(self, component_property_path: str, key: any, value: any) -> bool: + """ + Used to add a container item at a specified key. In practice key should be an integer index. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :param key: Zero index integer key, although this could be any unique unused key value + :param value: Value to be set + :return: Boolean success + """ + if self.is_property_container(component_property_path): + add_outcome = self.property_tree.add_container_item(component_property_path, key, value) + return add_outcome.IsSuccess() + else: + return False + + def get_container_item(self, component_property_path: str, key: any) -> any: + """ + Used to retrieve a container item value at the specified key. In practice key should be an integer index. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :param key: Zero index integer key + :return: Value stored at the key specified + """ + if self.is_property_container(component_property_path): + get_outcome = self.property_tree.get_container_item(component_property_path, key) + assert ( + get_outcome.IsSuccess() + ), f"Failure: could not get a value for {self.get_component_name()}: '{component_property_path}' [{key}]" + return get_outcome.GetValue() + else: + return None + + def remove_container_item(self, component_property_path: str, key: any) -> bool: + """ + Used to remove a container item value at the specified key. In practice key should be an integer index. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :param key: Zero index integer key + :return: Boolean success + """ + if self.is_property_container(component_property_path): + remove_outcome = self.property_tree.remove_container_item(component_property_path, key) + return remove_outcome.IsSuccess() + else: + return False + + def update_container_item(self, component_property_path: str, key: any, value: any): + """ + Used to update a container item at a specified key. In practice key should be an integer index. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :param key: Zero index integer key + :param value: Value to be set + :return: Boolean success + """ + if self.is_property_container(component_property_path): + update_outcome = self.property_tree.update_container_item(component_property_path, key, value) + return update_outcome.IsSuccess() + else: + return False def get_component_property_value(self, component_property_path: str): """ @@ -101,16 +216,25 @@ class EditorComponent: """ editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [self.id]) + def enable_component(self): + """ + used to enable the componet using its id value + """ + editor.EditorComponentAPIBus(bus.Broadcast, "EnabledComponents", [self.id]) + @staticmethod - def get_type_ids(component_names: list) -> list: + def get_type_ids(component_names: list, entity_type: str ='Game') -> list: """ Used to get type ids of given components list :param: component_names: List of components to get type ids :return: List of type ids of given components. """ + if entity_type.lower() == 'level': + entity_type = azlmbr.entity.EntityType().Level + else: + entity_type = azlmbr.entity.EntityType().Game type_ids = editor.EditorComponentAPIBus( - bus.Broadcast, "FindComponentTypeIdsByEntityType", component_names, azlmbr.entity.EntityType().Game - ) + bus.Broadcast, "FindComponentTypeIdsByEntityType", component_names, entity_type) return type_ids @@ -278,8 +402,7 @@ class EditorEntity: components = [] type_ids = EditorComponent.get_type_ids(component_names) for type_id in type_ids: - new_comp = EditorComponent() - new_comp.type_id = type_id + new_comp = EditorComponent(type_id) add_component_outcome = editor.EditorComponentAPIBus( bus.Broadcast, "AddComponentsOfType", self.id, [type_id] ) @@ -291,6 +414,27 @@ class EditorEntity: self.components.append(new_comp) return components + def remove_component(self, component_name: str) -> None: + """ + Used to remove a component from Entity + :param component_name: String of component name to remove + :return: None + """ + self.remove_components([component_name]) + + def remove_components(self, component_names: list): + """ + Used to remove a list of components from Entity + :param component_names: List of component names to remove + :return: None + """ + type_ids = EditorComponent.get_type_ids(component_names) + for type_id in type_ids: + remove_outcome = editor.EditorComponentAPIBus(bus.Broadcast, "RemoveComponents", self.id, [type_id]) + assert ( + remove_outcome.IsSuccess() + ), f"Failure: could not remove component from '{self.get_name()}'" + def get_components_of_type(self, component_names: list) -> List[EditorComponent]: """ Used to get components of type component_name that already exists on Entity @@ -300,8 +444,7 @@ class EditorEntity: component_list = [] type_ids = EditorComponent.get_type_ids(component_names) for type_id in type_ids: - component = EditorComponent() - component.type_id = type_id + component = EditorComponent(type_id) get_component_of_type_outcome = editor.EditorComponentAPIBus( bus.Broadcast, "GetComponentOfType", self.id, type_id ) @@ -359,6 +502,21 @@ class EditorEntity: set_status = self.get_start_status() assert set_status == status_to_set, f"Failed to set start status of {desired_start_status} to {self.get_name}" + def is_locked(self) -> bool: + """ + Used to get the locked status of the entity + :return: Boolean True if locked False if not locked + """ + return editor.EditorEntityInfoRequestBus(bus.Event, "IsLocked", self.id) + + def set_lock_state(self, is_locked: bool) -> None: + """ + Sets the lock state on the object to locked or not locked. + :param is_locked: True for locking, False to unlock. + :return: None + """ + editor.EditorEntityAPIBus(bus.Event, "SetLockState", self.id, is_locked) + def delete(self) -> None: """ Used to delete the Entity. @@ -488,18 +646,6 @@ class EditorLevelEntity: 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: """ @@ -518,10 +664,9 @@ class EditorLevelEntity: :return: List of newly added components to the level """ components = [] - type_ids = EditorLevelEntity.get_type_ids(component_names) + type_ids = EditorComponent.get_type_ids(component_names, 'level') for type_id in type_ids: - new_comp = EditorComponent() - new_comp.type_id = type_id + new_comp = EditorComponent(type_id) add_component_outcome = editor.EditorLevelComponentAPIBus( bus.Broadcast, "AddComponentsOfType", [type_id] ) @@ -540,10 +685,9 @@ class EditorLevelEntity: :return: List of Level Component objects of given component name """ component_list = [] - type_ids = EditorLevelEntity.get_type_ids(component_names) + type_ids = EditorComponent.get_type_ids(component_names, 'level') for type_id in type_ids: - component = EditorComponent() - component.type_id = type_id + component = EditorComponent(type_id) get_component_of_type_outcome = editor.EditorLevelComponentAPIBus( bus.Broadcast, "GetComponentOfType", type_id ) @@ -562,7 +706,7 @@ class EditorLevelEntity: :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]) + type_ids = EditorComponent.get_type_ids([component_name], 'level') return editor.EditorLevelComponentAPIBus(bus.Broadcast, "HasComponentOfType", type_ids[0]) @staticmethod @@ -572,5 +716,5 @@ class EditorLevelEntity: :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]) + type_ids = EditorComponent.get_type_ids([component_name], 'level') return editor.EditorLevelComponentAPIBus(bus.Broadcast, "CountComponentsOfType", type_ids[0])