Merge remote-tracking branch 'upstream/development' into Atom/santorac/RemixableMaterialTypes3

Signed-off-by: santorac <55155825+santorac@users.noreply.github.com>
This commit is contained in:
santorac
2022-01-25 20:54:34 -08:00
148 changed files with 2796 additions and 1145 deletions
@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<Component
Name="NetworkTestLevelEntityComponent"
Namespace="AutomatedTesting"
OverrideComponent="false"
OverrideController="false"
OverrideInclude=""
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ComponentRelation Constraint="Required" HasController="true" Name="NetworkTransformComponent" Namespace="Multiplayer" Include="Multiplayer/Components/NetworkTransformComponent.h" />
<RemoteProcedure Name="AuthorityToClientNoParams_PlayFx" InvokeFrom="Authority" HandleOn="Client" IsPublic="false" IsReliable="true" GenerateEventBindings="true" Description="" />
</Component>
@@ -29,8 +29,6 @@
<Param Type="float" Name="SomeFloat" />
</RemoteProcedure>
<RemoteProcedure Name="AuthorityToClientNoParams_PlayFx" InvokeFrom="Authority" HandleOn="Client" IsPublic="false" IsReliable="true" GenerateEventBindings="true" Description="" />
<RemoteProcedure Name="ServerToAuthority_DealDamage" InvokeFrom="Server" HandleOn="Authority" IsPublic="false" IsReliable="true" GenerateEventBindings="true" Description="" >
<Param Type="float" Name="damage" />
</RemoteProcedure>
@@ -12,4 +12,5 @@ set(FILES
Source/AutomatedTestingSystemComponent.cpp
Source/AutomatedTestingSystemComponent.h
Source/AutoGen/NetworkTestPlayerComponent.AutoComponent.xml
Source/AutoGen/NetworkTestLevelEntityComponent.AutoComponent.xml
)
@@ -23,6 +23,10 @@ class TestAutomation(EditorTestSuite):
enable_prefab_system = True
@pytest.mark.test_case_id("C36529679")
class AtomLevelLoadTest_Editor(EditorSharedTest):
from Atom.tests import hydra_Atom_LevelLoadTest as test_module
@pytest.mark.test_case_id("C36525657")
class AtomEditorComponents_BloomAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_BloomAdded as test_module
@@ -32,6 +32,8 @@ GLOBAL_ILLUMINATION_QUALITY = {
'High': 2,
}
# Level list used in Editor Level Load Test
LEVEL_LIST = ["hermanubis", "hermanubis_high", "macbeth_shaderballs", "PbrMaterialChart", "ShadowTest", "Sponza"]
class AtomComponentProperties:
"""
@@ -195,11 +197,13 @@ class AtomComponentProperties:
def entity_reference(property: str = 'name') -> str:
"""
Entity Reference component properties.
- 'EntityIdReferences' component container of entityId references. Initially empty.
: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': 'Entity Reference',
'EntityIdReferences': 'Controller|Configuration|EntityIdReferences',
}
return properties[property]
@@ -9,37 +9,58 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
class Tests:
creation_undo = (
"UNDO Entity creation success",
"UNDO Entity creation failed")
"P0: UNDO Entity creation failed")
creation_redo = (
"REDO Entity creation success",
"REDO Entity creation failed")
"P0: REDO Entity creation failed")
entity_reference_creation = (
"Entity Reference Entity successfully created",
"Entity Reference Entity failed to be created")
"P0: Entity Reference Entity failed to be created")
entity_reference_component = (
"Entity has an Entity Reference component",
"Entity failed to find Entity Reference component")
"P0: Entity failed to find Entity Reference component")
enter_game_mode = (
"Entered game mode",
"Failed to enter game mode")
"P0: Failed to enter game mode")
exit_game_mode = (
"Exited game mode",
"Couldn't exit game mode")
"P0: Couldn't exit game mode")
is_visible = (
"Entity is visible",
"Entity was not visible")
"P0: Entity was not visible")
is_hidden = (
"Entity is hidden",
"Entity was not hidden")
"P0: Entity was not hidden")
entity_deleted = (
"Entity deleted",
"Entity was not deleted")
"P0: Entity was not deleted")
deletion_undo = (
"UNDO deletion success",
"UNDO deletion failed")
"P0: UNDO deletion failed")
deletion_redo = (
"REDO deletion success",
"REDO deletion failed")
"P0: REDO deletion failed")
entity_id_references_is_container = (
"EntityIdReferences is a container property",
"P1: EntityIdReferences is NOT a container property")
container_append = (
"EntityIdReferences append succeeded",
"P1: EntityIdReferences append did not succeed")
container_add = (
"EntityIdReferences add succeeded",
"P1: EntityIdReferences add did not succeed")
container_update = (
"EntityIdReferences update succeeded",
"P1: EntityIdReferences update did not succeed")
container_remove = (
"EntityIdReferences remove succeeded",
"P1: EntityIdReferences remove did not succeed")
container_reset = (
"EntityIdReferences reset succeeded",
"P1: EntityIdReferences reset did not succeed")
entity_reference_component_removed = (
"Entity Reference component removed from entity",
"P1: Entity Reference component NOT removed from entity")
def AtomEditorComponents_EntityReference_AddedToEntity():
@@ -60,13 +81,21 @@ def AtomEditorComponents_EntityReference_AddedToEntity():
2) Add Entity Reference component to Entity Reference 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) Delete Entity Reference entity.
9) UNDO deletion.
10) REDO deletion.
11) Look for errors.
5) 'EntityIdReferences' is a container property
6) Append item to 'EntityIdReferences'
7) Add item to 'EntityIdReferences'
8) Update item in 'EntityIdReferences'
9) Remove item from 'EntityIdReferences'
10) Reset the container property then put one entity reference back for further tests
11) Remove component
12) UNDO component remove
13) Enter/Exit game mode.
14) Test IsHidden.
15) Test IsVisible.
16) Delete Entity Reference entity.
17) UNDO deletion.
18) REDO deletion.
19) Look for errors.
:return: None
"""
@@ -119,35 +148,107 @@ def AtomEditorComponents_EntityReference_AddedToEntity():
general.idle_wait_frames(1)
Report.result(Tests.creation_redo, entity_reference_entity.exists())
# 5. Enter/Exit game mode.
# Entities for EntityIdReferences tests
test_1 = EditorEntity.create_editor_entity('test_1')
test_2 = EditorEntity.create_editor_entity('test_2')
test_3 = EditorEntity.create_editor_entity('test_3')
# 5. 'EntityIdReferences' is a container property
Report.result(
Tests.entity_id_references_is_container,
entity_reference_component.is_property_container(
AtomComponentProperties.entity_reference('EntityIdReferences')))
# 6. Append item to 'EntityIdReferences'
entity_reference_component.append_container_item(
AtomComponentProperties.entity_reference('EntityIdReferences'), test_1.id)
Report.result(
Tests.container_append,
entity_reference_component.get_container_item(
AtomComponentProperties.entity_reference('EntityIdReferences'), 0) == test_1.id)
# 7. Add item to 'EntityIdReferences'
entity_reference_component.add_container_item(
AtomComponentProperties.entity_reference('EntityIdReferences'), 1, test_1.id)
Report.result(
Tests.container_add,
entity_reference_component.get_container_count(
AtomComponentProperties.entity_reference('EntityIdReferences')) == 2)
# 8. Update item in 'EntityIdReferences'
entity_reference_component.update_container_item(
AtomComponentProperties.entity_reference('EntityIdReferences'), 1, test_2.id)
Report.result(
Tests.container_update,
entity_reference_component.get_container_item(
AtomComponentProperties.entity_reference('EntityIdReferences'), 1) == test_2.id)
# 9. Remove item from 'EntityIdReferences'
entity_reference_component.append_container_item(
AtomComponentProperties.entity_reference('EntityIdReferences'), test_3.id)
count_before = entity_reference_component.get_container_count(
AtomComponentProperties.entity_reference('EntityIdReferences'))
entity_reference_component.remove_container_item(
AtomComponentProperties.entity_reference('EntityIdReferences'), 1)
count_after = entity_reference_component.get_container_count(
AtomComponentProperties.entity_reference('EntityIdReferences'))
Report.result(
Tests.container_remove,
((count_before == 3) and (count_after == 2) and
(entity_reference_component.get_container_item(
AtomComponentProperties.entity_reference('EntityIdReferences'), 1) == test_3.id)))
# 10. Reset the container property then put one entity reference back for further tests
entity_reference_component.reset_container(AtomComponentProperties.entity_reference('EntityIdReferences'))
general.idle_wait_frames(1)
Report.result(
Tests.container_reset,
entity_reference_component.get_container_count(
AtomComponentProperties.entity_reference('EntityIdReferences')) == 0)
entity_reference_component.append_container_item(
AtomComponentProperties.entity_reference('EntityIdReferences'), test_1.id)
# 11. Remove component
entity_reference_entity.remove_component(AtomComponentProperties.entity_reference())
general.idle_wait_frames(1)
Report.result(Tests.entity_reference_component_removed, not entity_reference_entity.has_component(
AtomComponentProperties.entity_reference()))
# 12. UNDO component remove
general.undo()
general.idle_wait_frames(1)
Report.result(Tests.entity_reference_component, entity_reference_entity.has_component(
AtomComponentProperties.entity_reference()))
# 13. 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.
# 14. Test IsHidden.
entity_reference_entity.set_visibility_state(False)
Report.result(Tests.is_hidden, entity_reference_entity.is_hidden() is True)
# 7. Test IsVisible.
# 15. Test IsVisible.
entity_reference_entity.set_visibility_state(True)
general.idle_wait_frames(1)
Report.result(Tests.is_visible, entity_reference_entity.is_visible() is True)
# 8. Delete Entity Reference entity.
# 16. Delete Entity Reference entity.
entity_reference_entity.delete()
Report.result(Tests.entity_deleted, not entity_reference_entity.exists())
# 9. UNDO deletion.
# 17. UNDO deletion.
general.undo()
general.idle_wait_frames(1)
Report.result(Tests.deletion_undo, entity_reference_entity.exists())
# 10. REDO deletion.
# 18. REDO deletion.
general.redo()
general.idle_wait_frames(1)
Report.result(Tests.deletion_redo, not entity_reference_entity.exists())
# 11. Look for errors and asserts.
# 19. 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}")
@@ -0,0 +1,72 @@
"""
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 Atom_LevelLoadTest():
"""
Summary:
Loads all graphics levels within the AutomatedTesting project in editor. For each level this script will verify that
the level loads, and can enter/exit gameplay without crashing the editor.
Test setup:
- Store all available levels in a list.
- Set up a for loop to run all checks for each level.
Expected Behavior:
Test verifies that each level loads, enters/exits game mode, and reports success for all test actions.
Test Steps for each level:
1) Create tuple with level load success and failure messages
2) Open the level using the python test tools command
3) Verify level is loaded using a separate command, and report success/failure
4) Enter gameplay and report result using a tuple
5) Exit Gameplay and report result using a tuple
6) Look for errors or asserts.
:return: None
"""
import azlmbr.legacy.general as general
from editor_python_test_tools.utils import Report, Tracer, TestHelper
from Atom.atom_utils.atom_constants import LEVEL_LIST
with Tracer() as error_tracer:
for level in LEVEL_LIST:
# 1. Create tuple with level load success and failure messages
level_check_tuple = (f"loaded {level}", f"failed to load {level}")
# 2. Open the level using the python test tools command
TestHelper.init_idle()
TestHelper.open_level("Graphics", level)
# 3. Verify level is loaded using a separate command, and report success/failure
Report.result(level_check_tuple, level == general.get_current_level_name())
# 4. Enter gameplay and report result using a tuple
enter_game_mode_tuple = (f"{level} entered gameplay successfully ", f"{level} failed to enter gameplay")
TestHelper.enter_game_mode(enter_game_mode_tuple)
general.idle_wait_frames(1)
# 5. Exit gameplay and report result using a tuple
exit_game_mode_tuple = (f"{level} exited gameplay successfully ", f"{level} failed to exit gameplay")
TestHelper.exit_game_mode(exit_game_mode_tuple)
# 6. Look for errors or 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(Atom_LevelLoadTest)
@@ -473,12 +473,11 @@ class EditorEntity:
:param component_names: List of component names to remove
:return: None
"""
type_ids = EditorComponent.get_type_ids(component_names, EditorEntityType.GAME)
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()}'"
component_ids = [component.id for component in self.get_components_of_type(component_names)]
remove_success = editor.EditorComponentAPIBus(bus.Broadcast, "RemoveComponents", component_ids)
assert (
remove_success
), f"Failure: could not remove component from entity '{self.get_name()}'"
def get_components_of_type(self, component_names: list) -> List[EditorComponent]:
"""
@@ -48,8 +48,8 @@ def wait_for_propagation():
# This is a helper class which contains some of the useful information about a prefab instance.
class PrefabInstance:
def __init__(self, prefab_file_name: str = None, container_entity: EditorEntity = None):
self.prefab_file_name: str = prefab_file_name
def __init__(self, prefab_file_path: str = None, container_entity: EditorEntity = None):
self.prefab_file_path: str = prefab_file_path
self.container_entity: EditorEntity = container_entity
def __eq__(self, other):
@@ -66,7 +66,7 @@ class PrefabInstance:
See if this instance is valid to be used with other prefab operations.
:return: Whether the target instance is valid or not.
"""
return self.container_entity.id.IsValid() and self.prefab_file_name in Prefab.existing_prefabs
return self.container_entity.id.IsValid() and self.prefab_file_path in Prefab.existing_prefabs
def has_editor_prefab_component(self) -> bool:
"""
@@ -131,7 +131,7 @@ class PrefabInstance:
has_correct_parent = reparented_container_entity_parent_id.ToString() == parent_entity_id.ToString()
assert has_correct_parent, "Prefab Instance reparented is *not* under the expected parent entity"
current_instance_prefab = Prefab.get_prefab(self.prefab_file_name)
current_instance_prefab = Prefab.get_prefab(self.prefab_file_path)
current_instance_prefab.instances.remove(self)
self.container_entity = reparented_container_entity
@@ -161,46 +161,48 @@ class Prefab:
:param file_path: A unique file path of the target prefab.
:return: Whether the target prefab is loaded or not.
"""
return file_path in Prefab.existing_prefabs
for entry in Prefab.existing_prefabs:
Report.info(f"PrefabPath: '{entry}'")
return get_prefab_file_path(file_path) in Prefab.existing_prefabs
@classmethod
def prefab_exists(cls, file_path: str) -> bool:
"""
Check if a prefab exists in the directory for files of prefab tests.
:param file_name: A unique file name of the target prefab.
:param file_path: A unique file path of the target prefab.
:return: Whether the target prefab exists or not.
"""
return path.exists(get_prefab_file_path(file_path))
@classmethod
def get_prefab(cls, file_name: str) -> Prefab:
def get_prefab(cls, file_path: str) -> Prefab:
"""
Return a prefab which can be used immediately.
:param file_name: A unique file name of the target prefab.
:param file_path: A unique file path of the target prefab.
:return: The prefab with given file name.
"""
assert file_name, "Received an empty file_name"
if Prefab.is_prefab_loaded(file_name):
return Prefab.existing_prefabs[file_name]
assert file_path, "Received an empty file_path"
if Prefab.is_prefab_loaded(file_path):
return Prefab.existing_prefabs[get_prefab_file_path(file_path)]
else:
assert Prefab.prefab_exists(file_name), f"Attempted to get a prefab \"{file_name}\" that doesn't exist"
new_prefab = Prefab(file_name)
Prefab.existing_prefabs[file_name] = Prefab(file_name)
assert Prefab.prefab_exists(file_path), f"Attempted to get a prefab \"{file_path}\" that doesn't exist"
new_prefab = Prefab(file_path)
Prefab.existing_prefabs[new_prefab.file_path] = new_prefab
return new_prefab
@classmethod
def create_prefab(cls, entities: list[EditorEntity], file_name: str, prefab_instance_name: str=None) -> tuple(Prefab, PrefabInstance):
def create_prefab(cls, entities: list[EditorEntity], file_path: str, prefab_instance_name: str=None) -> tuple(Prefab, PrefabInstance):
"""
Create a prefab in memory and return it. The very first instance of this prefab will also be created.
:param entities: The entities that should form the new prefab (along with their descendants).
:param file_name: A unique file name of new prefab.
:param prefab_instance_name: A name for the very first instance generated while prefab creation. The default instance name is the same as file_name.
:param file_path: A unique file path for new prefab.
:param prefab_instance_name: A name for the very first instance generated while prefab creation. The default instance name is the same as the file name in file_path.
:return: Created Prefab object and the very first PrefabInstance object owned by the prefab.
"""
assert not Prefab.is_prefab_loaded(file_name), f"Can't create Prefab '{file_name}' since the prefab already exists"
assert not Prefab.is_prefab_loaded(file_path), f"Can't create Prefab '{file_path}' since the prefab already exists"
new_prefab = Prefab(file_name)
new_prefab = Prefab(file_path)
entity_ids = [entity.id for entity in entities]
create_prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'CreatePrefabInMemory', entity_ids, new_prefab.file_path)
assert create_prefab_result.IsSuccess(), f"Prefab operation 'CreatePrefab' failed. Error: {create_prefab_result.GetError()}"
@@ -210,15 +212,14 @@ class Prefab:
children_entity_ids = container_entity.get_children_ids()
assert len(children_entity_ids) == len(entities), f"Entity count of created prefab instance does *not* match the count of given entities."
if prefab_instance_name:
container_entity.set_name(prefab_instance_name)
wait_for_propagation()
new_prefab_instance = PrefabInstance(file_name, EditorEntity(container_entity_id))
new_prefab_instance = PrefabInstance(new_prefab.file_path, EditorEntity(container_entity_id))
if prefab_instance_name:
new_prefab_instance.container_entity.set_name(prefab_instance_name)
new_prefab.instances.add(new_prefab_instance)
Prefab.existing_prefabs[file_name] = new_prefab
Prefab.existing_prefabs[new_prefab.file_path] = new_prefab
return new_prefab, new_prefab_instance
@classmethod
@@ -250,7 +251,7 @@ class Prefab:
assert False, "Not all entities and descendants in target prefabs are deleted."
for instance in prefab_instances:
instance_deleted_prefab = Prefab.get_prefab(instance.prefab_file_name)
instance_deleted_prefab = Prefab.get_prefab(instance.prefab_file_path)
instance_deleted_prefab.instances.remove(instance)
instance = PrefabInstance()
@@ -290,8 +291,7 @@ class Prefab:
prefab_file_path = prefab.PrefabPublicRequestBus(bus.Broadcast, 'GetOwningInstancePrefabPath', duplicate_container_entity_id)
assert prefab_file_path, "Returned file path should *not* be empty."
prefab_file_name = Path(prefab_file_path).stem
duplicate_instance_prefab = Prefab.get_prefab(prefab_file_name)
duplicate_instance_prefab = Prefab.get_prefab(prefab_file_path)
duplicate_instance = PrefabInstance(prefab_file_path, EditorEntity(duplicate_container_entity_id))
duplicate_instance_prefab.instances.add(duplicate_instance)
duplicate_instances.append(duplicate_instance)
@@ -324,7 +324,7 @@ class Prefab:
wait_for_propagation()
instance_owner_prefab = Prefab.get_prefab(prefab_instance.prefab_file_name)
instance_owner_prefab = Prefab.get_prefab(prefab_instance.prefab_file_path)
instance_owner_prefab.instances.remove(prefab_instance)
prefab_instance = PrefabInstance()
@@ -346,13 +346,13 @@ class Prefab:
container_entity_id = instantiate_prefab_result.GetValue()
container_entity = EditorEntity(container_entity_id)
if name:
container_entity.set_name(name)
wait_for_propagation()
new_prefab_instance = PrefabInstance(self.file_path, EditorEntity(container_entity_id))
assert not new_prefab_instance in self.instances, "This prefab instance is already existed before this instantiation."
assert not new_prefab_instance in self.instances, "This prefab instance already existed before this instantiation."
if name:
new_prefab_instance.container_entity.set_name(name)
self.instances.add(new_prefab_instance)
assert new_prefab_instance.is_at_position(prefab_position), "This prefab instance is *not* at expected position."
@@ -35,3 +35,7 @@ class TestAutomation(TestAutomationBase):
def test_Multiplayer_AutoComponent_RPC(self, request, workspace, editor, launcher_platform):
from .tests import Multiplayer_AutoComponent_RPC as test_module
self._run_prefab_test(request, workspace, editor, test_module)
def test_Multiplayer_SimpleNetworkLevelEntity(self, request, workspace, editor, launcher_platform):
from .tests import Multiplayer_SimpleNetworkLevelEntity as test_module
self._run_prefab_test(request, workspace, editor, test_module)
@@ -0,0 +1,76 @@
"""
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
"""
# Test Case Title : Check that level entities with network bindings are properly replicated.
# Note: This test should be ran on a fresh editor run; some bugs with spawnables occur only on the first editor play-mode.
# fmt: off
class TestSuccessFailTuples():
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
find_network_player = ("Found network player", "Couldn't find network player")
# fmt: on
def Multiplayer_SimpleNetworkLevelEntity():
r"""
Summary:
Test to make sure that network entities in a level function and are replicated to clients as expected
Level Description:
- Static
1. NetLevelEntity. This is a networked entity which has a script attached which prints logs to ensure it's replicated.
Expected Outcome:
We should see logs stating that the net-sync'd level entity exists on both server and client.
:return:
"""
import azlmbr.legacy.general as general
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import Tracer
from editor_python_test_tools.utils import TestHelper as helper
from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole
level_name = "SimpleNetworkLevelEntity"
player_prefab_name = "Player"
player_prefab_path = f"levels/multiplayer/{level_name}/{player_prefab_name}.network.spawnable"
helper.init_idle()
# 1) Open Level
helper.open_level("Multiplayer", level_name)
with Tracer() as section_tracer:
# 2) Enter game mode
helper.multiplayer_enter_game_mode(TestSuccessFailTuples.enter_game_mode, player_prefab_path.lower())
# 3) Make sure the network player was spawned
player_id = general.find_game_entity(player_prefab_name)
Report.critical_result(TestSuccessFailTuples.find_network_player, player_id.IsValid())
# 4) Check the editor logs for network spawnable errors
ATTEMPTING_INVALID_NETSPAWN_WAIT_TIME_SECONDS = 0.0 # The editor will try to net-spawn its networked level entity before it's even a client. Make sure this didn't happen.
helper.fail_if_log_line_found('NetworkEntityManager', "RequestNetSpawnableInstantiation: Requested spawnable Root.network.spawnable doesn't exist in the NetworkSpawnableLibrary. Please make sure it is a network spawnable", section_tracer.errors, ATTEMPTING_INVALID_NETSPAWN_WAIT_TIME_SECONDS)
# 5) Ensure the script graph attached to the level entity is running on the server
SCRIPTGRAPH_ENABLED_WAIT_TIME_SECONDS = 0.25
helper.succeed_if_log_line_found('EditorServer', "Script: SimpleNetworkLevelEntity: On Graph Start", section_tracer.prints, SCRIPTGRAPH_ENABLED_WAIT_TIME_SECONDS)
# Exit game mode
helper.exit_game_mode(TestSuccessFailTuples.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(Multiplayer_SimpleNetworkLevelEntity)
@@ -38,6 +38,10 @@ class TestAutomation(TestAutomationBase):
from Prefab.tests.instantiate_prefab import InstantiatePrefab_ContainingASingleEntity as test_module
self._run_prefab_test(request, workspace, editor, test_module)
def test_InstantiatePrefab_FromCreatedPrefabWithSingleEntity(self, request, workspace, editor, launcher_platform):
from Prefab.tests.instantiate_prefab import InstantiatePrefab_FromCreatedPrefabWithSingleEntity as test_module
self._run_prefab_test(request, workspace, editor, test_module)
def test_DeletePrefab_ContainingASingleEntity(self, request, workspace, editor, launcher_platform):
from Prefab.tests.delete_prefab import DeletePrefab_ContainingASingleEntity as test_module
self._run_prefab_test(request, workspace, editor, test_module)
@@ -45,8 +45,12 @@ class TestAutomationNoAutoTestMode(EditorTestSuite):
class test_InstantiatePrefab_ContainingASingleEntity(EditorSharedTest):
from .tests.instantiate_prefab import InstantiatePrefab_ContainingASingleEntity as test_module
class test_InstantiatePrefab_FromCreatedPrefabWithSingleEntity(EditorSharedTest):
from .tests.instantiate_prefab import InstantiatePrefab_FromCreatedPrefabWithSingleEntity as test_module
class test_DeletePrefab_ContainingASingleEntity(EditorSharedTest):
from .tests.delete_prefab import DeletePrefab_ContainingASingleEntity as test_module
class test_DuplicatePrefab_ContainingASingleEntity(EditorSharedTest):
from .tests.duplicate_prefab import DuplicatePrefab_ContainingASingleEntity as test_module
from .tests.duplicate_prefab import DuplicatePrefab_ContainingASingleEntity as test_module
@@ -13,7 +13,8 @@ def CreatePrefab_UnderAnEntity():
Test is successful if the new instanced prefab of the child has the parent entity id
"""
CAR_PREFAB_FILE_NAME = 'car_prefab'
from pathlib import Path
CAR_PREFAB_FILE_NAME = Path(__file__).stem + 'car_prefab'
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.prefab_utils import Prefab
@@ -7,7 +7,8 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
def CreatePrefab_WithSingleEntity():
CAR_PREFAB_FILE_NAME = 'car_prefab'
from pathlib import Path
CAR_PREFAB_FILE_NAME = Path(__file__).stem + 'car_prefab'
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.utils import Report
@@ -7,7 +7,8 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
def DeletePrefab_ContainingASingleEntity():
CAR_PREFAB_FILE_NAME = 'car_prefab'
from pathlib import Path
CAR_PREFAB_FILE_NAME = Path(__file__).stem + 'car_prefab'
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.prefab_utils import Prefab
@@ -7,8 +7,9 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
def DetachPrefab_UnderAnotherPrefab():
CAR_PREFAB_FILE_NAME = 'car_prefab2'
WHEEL_PREFAB_FILE_NAME = 'wheel_prefab2'
from pathlib import Path
CAR_PREFAB_FILE_NAME = Path(__file__).stem + 'car_prefab'
WHEEL_PREFAB_FILE_NAME = Path(__file__).stem + 'wheel_prefab'
import editor_python_test_tools.pyside_utils as pyside_utils
@@ -7,7 +7,8 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
def DuplicatePrefab_ContainingASingleEntity():
CAR_PREFAB_FILE_NAME = 'car_prefab'
from pathlib import Path
CAR_PREFAB_FILE_NAME = Path(__file__).stem + 'car_prefab'
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.prefab_utils import Prefab
@@ -0,0 +1,34 @@
"""
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 InstantiatePrefab_FromCreatedPrefabWithSingleEntity():
from pathlib import Path
CAR_PREFAB_FILE_NAME = Path(__file__).stem + 'car_prefab'
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.utils import Report
from editor_python_test_tools.prefab_utils import Prefab
import Prefab.tests.PrefabTestUtils as prefab_test_utils
prefab_test_utils.open_base_tests_level()
# Creates a new entity at the root level
car_entity = EditorEntity.create_editor_entity()
car_prefab_entities = [car_entity]
# Creates a prefab from the new entity
car_prefab, car_prefab_instance = Prefab.create_prefab(car_prefab_entities, CAR_PREFAB_FILE_NAME)
# Instantiate another instance and verify
car_prefab_instance_2 = car_prefab.instantiate()
assert car_prefab_instance_2.is_valid(), "Failed to instantiate prefab"
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(InstantiatePrefab_FromCreatedPrefabWithSingleEntity)
@@ -7,8 +7,9 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
def ReparentPrefab_UnderAnotherPrefab():
CAR_PREFAB_FILE_NAME = 'car_prefab'
WHEEL_PREFAB_FILE_NAME = 'wheel_prefab'
from pathlib import Path
CAR_PREFAB_FILE_NAME = Path(__file__).stem + 'car_prefab'
WHEEL_PREFAB_FILE_NAME = Path(__file__).stem + 'wheel_prefab'
import editor_python_test_tools.pyside_utils as pyside_utils
@@ -19,12 +19,16 @@ def find_nodes_matching_entity_component(component_name, entity_id):
:param entity_id: The entity ID to search for the given component node on
:return List of matching nodes
"""
component_type_id = hydra.get_component_type_id(component_name)
component = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', entity_id,
hydra.get_component_type_id(component_name))
component_type_id)
if component.IsSuccess():
component_id = component.GetValue()
component_node = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'GetAllNodesMatchingEntityComponent',
component_id)
if component_node:
print(f"{component_name} node found on entity {entity_id.ToString()}")
else:
print(f"Failed to find {component_name} node on entity {entity_id.ToString()}")
return component_node
@@ -43,7 +43,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
NAME AutomatedTesting::LandscapeCanvasTests_Main_Optimized
TEST_SERIAL
TEST_SUITE main
PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas/TestSuite_Main_Optimized.py
PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas/TestSuite_Main.py
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
@@ -68,8 +68,7 @@ def AreaNodes_DependentComponentsAdded():
newEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -58,7 +58,6 @@ def AreaNodes_EntityCreatedOnNodeAdd():
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -67,8 +66,7 @@ def AreaNodes_EntityCreatedOnNodeAdd():
newEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -59,8 +59,8 @@ def AreaNodes_EntityRemovedOnNodeDelete():
import azlmbr.math as math
import azlmbr.paths
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -73,8 +73,7 @@ def AreaNodes_EntityRemovedOnNodeDelete():
deletedEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -1,15 +1,14 @@
"""
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:
slice_instantiated = (
"Slice instantiated successfully",
"Failed to instantiate slice"
prefab_instantiated = (
"Prefab instantiated successfully",
"Failed to instantiate prefab"
)
lc_entity_found = (
"LandscapeCanvas entity found",
@@ -24,7 +23,7 @@ class Tests:
"Failed to find Distribution Filter component on BushSpawner entity"
)
existing_graph_opened = (
"Opened existing graph from slice",
"Opened existing graph from prefab",
"Failed to open existing graph"
)
dist_filter_node_found = (
@@ -66,10 +65,8 @@ def ComponentUpdates_UpdateGraph():
Summary:
This test verifies that the Landscape Canvas graphs update properly when components are added/removed outside of
Landscape Canvas.
Expected Behavior:
Graphs properly reflect component changes made to entities outside of Landscape Canvas.
Test Steps:
1. Open Level
2. Find LandscapeCanvas named entity
@@ -83,41 +80,36 @@ def ComponentUpdates_UpdateGraph():
9. Add a new entity with unique name as a child of the Landscape Canvas entity
10. Add a Box Shape component to the new child entity
11. Ensure Box Shape node is present on the open graph
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import azlmbr.asset as asset
import azlmbr.bus as bus
import azlmbr.editor as editor
import azlmbr.entity as entity
import azlmbr.legacy.general as general
import azlmbr.landscapecanvas as landscapecanvas
import azlmbr.math as math
import azlmbr.slice as slice
import azlmbr.prefab as prefab
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
# Open a simple level and instantiate LC_BushFlowerBlender.slice
helper.init_idle()
helper.open_level("Physics", "Base")
# Open a simple level and instantiate BushFlowerBlender.prefab
hydra.open_base_level()
transform = math.Transform_CreateIdentity()
position = math.Vector3(64.0, 64.0, 32.0)
transform.invoke('SetPosition', position)
test_slice_path = os.path.join("Slices", "LC_BushFlowerBlender.slice")
test_slice_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", test_slice_path, math.Uuid(),
False)
test_slice = slice.SliceRequestBus(bus.Broadcast, 'InstantiateSliceFromAssetId', test_slice_id, transform)
Report.critical_result(Tests.slice_instantiated, test_slice.IsValid())
test_prefab_path = os.path.join("Assets", "Prefabs", "BushFlowerBlender.prefab")
prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'InstantiatePrefab', test_prefab_path,
entity.EntityId(), position)
Report.critical_result(Tests.prefab_instantiated, prefab_result.IsSuccess())
# Find root entity in the loaded level
search_filter = entity.SearchFilter()
@@ -126,8 +118,8 @@ def ComponentUpdates_UpdateGraph():
# Allow a few seconds for matching entity to be found
helper.wait_for_condition(lambda: len(entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)) > 0, 5.0)
lc_matching_entities = entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)
slice_root_id = lc_matching_entities[0] #Entity with Landscape Canvas component
Report.critical_result(Tests.lc_entity_found, slice_root_id.IsValid())
prefab_root_id = lc_matching_entities[0] #Entity with Landscape Canvas component
Report.critical_result(Tests.lc_entity_found, prefab_root_id.IsValid())
# Find the BushSpawner entity
search_filter.names = ["BushSpawner"]
@@ -147,7 +139,7 @@ def ComponentUpdates_UpdateGraph():
# Open Landscape Canvas and the existing graph
general.open_pane('Landscape Canvas')
open_graph = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'OnGraphEntity', slice_root_id)
open_graph = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'OnGraphEntity', prefab_root_id)
Report.critical_result(Tests.existing_graph_opened, open_graph.IsValid())
# Verify that Distribution Filter node is present on the graph
@@ -45,11 +45,9 @@ def Component_AddedRemoved():
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Create an Entity at the root of the level
newEntityId = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', entity.EntityId())
@@ -59,8 +59,7 @@ def Edit_DisabledNodeDuplication():
newEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -1,15 +1,14 @@
"""
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:
slice_spawned = (
"Slice instantiated successfully",
"Failed to instantiate slice"
prefab_instantiated = (
"Prefab instantiated successfully",
"Failed to instantiate prefab"
)
lc_entity_found = (
"Landscape Canvas entity found",
@@ -31,31 +30,28 @@ class Tests:
"Vegetation Layer Spawner node was successfully removed",
"Failed to remove Vegetation Layer Spawner node"
)
def Edit_UndoNodeDelete_SliceEntity():
def Edit_UndoNodeDelete_PrefabEntity():
"""
Summary:
This test verifies Editor stability after undoing the deletion of nodes on a slice entity.
This test verifies Editor stability after undoing the deletion of nodes on a prefab entity.
Expected Behavior:
Editor remains stable and free of crashes.
Test Steps:
1) Open a simple level
2) Instantiate a slice with a Landscape Canvas setup
2) Instantiate a prefab with a Landscape Canvas setup
3) Find a specific node on the graph, and delete it
4) Restore the node with Undo
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import azlmbr.asset as asset
import azlmbr.bus as bus
import azlmbr.editor as editor
import azlmbr.entity as entity
@@ -63,25 +59,23 @@ def Edit_UndoNodeDelete_SliceEntity():
import azlmbr.editor.graph as graph
import azlmbr.landscapecanvas as landscapecanvas
import azlmbr.math as math
import azlmbr.slice as slice
import azlmbr.prefab as prefab
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Instantiate slice
transform = math.Transform_CreateIdentity()
position = math.Vector3(64.0, 64.0, 32.0)
transform.invoke('SetPosition', position)
test_slice_path = os.path.join("Slices", "LC_BushFlowerBlender.slice")
test_slice_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", test_slice_path, math.Uuid(),
False)
test_slice = slice.SliceRequestBus(bus.Broadcast, 'InstantiateSliceFromAssetId', test_slice_id, transform)
Report.result(Tests.slice_spawned, test_slice.IsValid())
test_prefab_path = os.path.join("Assets", "Prefabs", "BushFlowerBlender.prefab")
prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'InstantiatePrefab', test_prefab_path,
entity.EntityId(), position)
Report.critical_result(Tests.prefab_instantiated, prefab_result.IsSuccess())
# Find root entity in the loaded level
search_filter = entity.SearchFilter()
@@ -134,5 +128,4 @@ def Edit_UndoNodeDelete_SliceEntity():
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(Edit_UndoNodeDelete_SliceEntity)
Report.start_test(Edit_UndoNodeDelete_PrefabEntity)
@@ -76,7 +76,6 @@ def GradientMixer_NodeConstruction():
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -85,8 +84,7 @@ def GradientMixer_NodeConstruction():
newEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -58,7 +58,6 @@ def GradientModifierNodes_EntityCreatedOnNodeAdd():
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -67,8 +66,7 @@ def GradientModifierNodes_EntityCreatedOnNodeAdd():
newEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -58,8 +58,8 @@ def GradientModifierNodes_EntityRemovedOnNodeDelete():
import azlmbr.legacy.general as general
import azlmbr.math as math
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -72,8 +72,7 @@ def GradientModifierNodes_EntityRemovedOnNodeDelete():
deletedEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -60,7 +60,6 @@ def GradientNodes_DependentComponentsAdded():
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -69,8 +68,7 @@ def GradientNodes_DependentComponentsAdded():
newEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -58,7 +58,6 @@ def GradientNodes_EntityCreatedOnNodeAdd():
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -67,8 +66,7 @@ def GradientNodes_EntityCreatedOnNodeAdd():
newEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -58,8 +58,8 @@ def GradientNodes_EntityRemovedOnNodeDelete():
import azlmbr.legacy.general as general
import azlmbr.math as math
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -72,8 +72,7 @@ def GradientNodes_EntityRemovedOnNodeDelete():
deletedEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -51,8 +51,8 @@ def GraphClosed_OnEntityDelete():
import azlmbr.editor.graph as graph
import azlmbr.legacy.general as general
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -61,8 +61,7 @@ def GraphClosed_OnEntityDelete():
newRootEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -51,14 +51,13 @@ def GraphClosed_OnLevelChange():
import azlmbr.editor.graph as graph
import azlmbr.legacy.general as general
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -73,7 +72,7 @@ def GraphClosed_OnLevelChange():
Report.result(Tests.graph_registered, graph_registered)
# Open a different level, which should close any open Landscape Canvas graphs
general.open_level_no_prompt('WhiteBox/EmptyLevel')
general.open_level_no_prompt('Base')
# Make sure the graph we created is now closed
graphIsOpen = graph.AssetEditorRequestBus(bus.Event, 'ContainsGraph', editorId, newGraphId)
@@ -51,8 +51,8 @@ def GraphClosed_TabbedGraphClosesIndependently():
import azlmbr.editor.graph as graph
import azlmbr.legacy.general as general
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editor_id = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -65,8 +65,7 @@ def GraphClosed_TabbedGraphClosesIndependently():
return graph_open
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -1,18 +1,17 @@
"""
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:
slice_instantiated = (
"Slice instantiated successfully",
"Failed to instantiate slice"
prefab_instantiated = (
"Prefab instantiated successfully",
"Failed to instantiate prefab"
)
existing_graph_opened = (
"Opened existing graph from slice",
"Opened existing graph from prefab",
"Failed to open existing graph"
)
node_removed = (
@@ -37,13 +36,11 @@ def GraphUpdates_UpdateComponent():
"""
Summary:
This test verifies that components are properly updated as nodes are added/removed/updated.
Expected Behavior:
Landscape Canvas node CRUD properly updates component entities.
Test Steps:
1. Open Level.
2. Open the graph on LC_BushFlowerBlender.slice
2. Open the graph on BushFlowerBlender.prefab
3. Find the Rotation Modifier node on the BushSpawner entity
4. Delete the Rotation Modifier node
5. Ensure the Vegetation Rotation Modifier component is removed from the BushSpawner entity
@@ -51,18 +48,15 @@ def GraphUpdates_UpdateComponent():
7. Ensure BushSpawner entity is deleted
8. Change connection from second Rotation Modifier node to a different Gradient
9. Ensure Gradient reference on component is updated
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import azlmbr.asset as asset
import azlmbr.bus as bus
import azlmbr.editor as editor
import azlmbr.entity as entity
@@ -70,39 +64,37 @@ def GraphUpdates_UpdateComponent():
import azlmbr.editor.graph as graph
import azlmbr.landscapecanvas as landscapecanvas
import azlmbr.math as math
import azlmbr.slice as slice
import azlmbr.prefab as prefab
import automatedtesting_shared.landscape_canvas_utils as lc
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
# Open a simple level and instantiate LC_BushFlowerBlender.slice
helper.init_idle()
helper.open_level("Physics", "Base")
# Open a simple level and instantiate BushFlowerBlender.prefab
hydra.open_base_level()
transform = math.Transform_CreateIdentity()
position = math.Vector3(64.0, 64.0, 32.0)
transform.invoke('SetPosition', position)
test_slice_path = os.path.join("Slices", "LC_BushFlowerBlender.slice")
test_slice_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", test_slice_path, math.Uuid(),
False)
test_slice = slice.SliceRequestBus(bus.Broadcast, 'InstantiateSliceFromAssetId', test_slice_id, transform)
Report.critical_result(Tests.slice_instantiated, test_slice.IsValid())
test_prefab_path = os.path.join("Assets", "Prefabs", "BushFlowerBlender.prefab")
prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'InstantiatePrefab', test_prefab_path,
entity.EntityId(), position)
Report.critical_result(Tests.prefab_instantiated, prefab_result.IsSuccess())
# Search for root entity to ensure slice is loaded
# Search for root entity to ensure prefab is loaded
search_filter = entity.SearchFilter()
search_filter.names = ["LandscapeCanvas"]
helper.wait_for_condition(lambda: len(entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)) > 0, 5.0)
prefab_lc_root = entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)[0]
# Find needed entities in the loaded level
slice_root_id = hydra.find_entity_by_name('LandscapeCanvas')
bush_spawner_id = hydra.find_entity_by_name('BushSpawner')
flower_spawner_id = hydra.find_entity_by_name('FlowerSpawner')
inverted_perlin_noise_id = hydra.find_entity_by_name('Invert')
# Open Landscape Canvas and the existing graph
general.open_pane('Landscape Canvas')
open_graph_id = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'OnGraphEntity', slice_root_id)
open_graph_id = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'OnGraphEntity', prefab_lc_root)
Report.critical_result(Tests.existing_graph_opened, open_graph_id.IsValid())
# Find the Rotation Modifier node on the BushSpawner entity
@@ -110,6 +102,7 @@ def GraphUpdates_UpdateComponent():
# Remove the Rotation Modifier node
graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', open_graph_id, rotation_modifier_node[0])
general.idle_wait_frames(2)
# Verify node was removed
rotation_modifier_node = lc.find_nodes_matching_entity_component('Vegetation Rotation Modifier', bush_spawner_id)
@@ -121,14 +114,18 @@ def GraphUpdates_UpdateComponent():
Report.result(Tests.component_removed, not has_rotation_modifier)
# Find the Vegetation Layer Spawner node on the BushSpawner entity
open_graph_id = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'OnGraphEntity', prefab_lc_root)
layer_spawner_node = lc.find_nodes_matching_entity_component('Vegetation Layer Spawner', bush_spawner_id)
# Remove the Vegetation Layer Spawner node and verify the corresponding entity is deleted
graph.GraphControllerRequestBus(bus.Event, 'RemoveNode', open_graph_id, layer_spawner_node[0])
general.idle_wait_frames(2)
layer_spawner_node = lc.find_nodes_matching_entity_component('Vegetation Layer Spawner', bush_spawner_id)
bush_spawner_id = hydra.find_entity_by_name('BushSpawner')
Report.result(Tests.entity_deleted, not bush_spawner_id)
Report.result(Tests.entity_deleted, not layer_spawner_node and not bush_spawner_id)
# Connect the FlowerSpawner's Rotation Modifier node to the Invert Gradient Modifier node
open_graph_id = landscapecanvas.LandscapeCanvasRequestBus(bus.Broadcast, 'OnGraphEntity', prefab_lc_root)
rotation_modifier_node = lc.find_nodes_matching_entity_component('Vegetation Rotation Modifier', flower_spawner_id)
invert_node = lc.find_nodes_matching_entity_component('Invert Gradient Modifier', inverted_perlin_noise_id)
@@ -137,7 +134,7 @@ def GraphUpdates_UpdateComponent():
graph.GraphControllerRequestBus(bus.Event, 'AddConnectionBySlotId', open_graph_id, invert_node[0],
outbound_gradient_slot, rotation_modifier_node[0], inbound_gradient_z_slot)
general.idle_wait(1.0) # Add a small wait to ensure component property has time to update
general.idle_wait_frames(2) # Add a small wait to ensure component property has time to update
# Verify the Gradient Entity Id reference on the Rotation Modifier component was properly set
rotation_type_id = hydra.get_component_type_id('Vegetation Rotation Modifier')
@@ -64,7 +64,6 @@ def LayerBlender_NodeConstruction():
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -73,8 +72,7 @@ def LayerBlender_NodeConstruction():
newEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -63,7 +63,6 @@ def LayerExtenderNodes_ComponentEntitySync():
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -72,8 +71,7 @@ def LayerExtenderNodes_ComponentEntitySync():
newEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -60,7 +60,6 @@ def NewGraph_CreatedSuccessfully():
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -69,8 +68,7 @@ def NewGraph_CreatedSuccessfully():
new_root_entity_id = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Listen for entity creation notifications so we can check if the entity created
# with the new graph has our Landscape Canvas component automatically added
@@ -0,0 +1,69 @@
"""
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:
prefab_created = (
"Prefab created successfully",
"Failed to create prefab"
)
prefab_instantiated = (
"Prefab instantiated successfully",
"Failed to instantiate prefab"
)
def Prefab_CreateInstantiate():
"""
Summary:
A prefab containing the LandscapeCanvas component can be created/instantiated.
Expected Result:
Prefab is created/processed/instantiated successfully and free of errors/warnings.
Test Steps:
1) Open a simple level
2) Create a new entity with a Landscape Canvas component
3) Create a prefab of the new entity
4) Instantiate a new copy of the prefab
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import azlmbr.math as math
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.prefab_utils import Prefab
# Open an existing simple level
hydra.open_base_level()
# Create entity with Landscape Canvas component
position = math.Vector3(512.0, 512.0, 32.0)
landscape_canvas = hydra.Entity("landscape_canvas_entity")
landscape_canvas.create_entity(position, ["Landscape Canvas"])
# Create in-memory prefab from the created entity
lc_prefab_filename = "LC_PrefabTest"
lc_prefab, lc_prefab_instance = Prefab.create_prefab([landscape_canvas], lc_prefab_filename)
# Verify if prefab is created
helper.wait_for_condition(lambda: lc_prefab.is_prefab_loaded(lc_prefab_filename), 5.0)
Report.result(Tests.prefab_created, lc_prefab.is_prefab_loaded(lc_prefab_filename))
# Instantiate prefab
lc_prefab_instance2 = lc_prefab.instantiate()
helper.wait_for_condition(lambda: lc_prefab_instance2.has_editor_prefab_component(), 5.0)
Report.result(Tests.prefab_instantiated, lc_prefab_instance2.has_editor_prefab_component())
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(Prefab_CreateInstantiate)
@@ -58,7 +58,6 @@ def ShapeNodes_EntityCreatedOnNodeAdd():
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -66,10 +65,8 @@ def ShapeNodes_EntityCreatedOnNodeAdd():
global newEntityId
newEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
# Open an existing simple level
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -58,8 +58,8 @@ def ShapeNodes_EntityRemovedOnNodeDelete():
import azlmbr.legacy.general as general
import azlmbr.math as math
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -72,8 +72,7 @@ def ShapeNodes_EntityRemovedOnNodeDelete():
deletedEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -1,84 +0,0 @@
"""
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:
slice_created = (
"Slice created successfully",
"Failed to create slice"
)
slice_instantiated = (
"Slice instantiated successfully",
"Failed to instantiate slice"
)
def Slice_CreateInstantiate():
"""
Summary:
A slice containing the LandscapeCanvas component can be created/instantiated.
Expected Result:
Slice is created/processed/instantiated successfully and free of errors/warnings.
Test Steps:
1) Open a simple level
2) Create a new entity with a Landscape Canvas component
3) Create a slice of the new entity
4) Instantiate a new copy of the slice
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import azlmbr.math as math
import azlmbr.bus as bus
import azlmbr.asset as asset
import azlmbr.slice as slice
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
def path_is_valid_asset(asset_path):
asset_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", asset_path, math.Uuid(), False)
return asset_id.invoke("IsValid")
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
# Create entity with Landscape Canvas component
position = math.Vector3(512.0, 512.0, 32.0)
landscape_canvas = hydra.Entity("landscape_canvas_entity")
landscape_canvas.create_entity(position, ["Landscape Canvas"])
# Create slice from the created entity
slice_path = os.path.join("slices", "TestSlice.slice")
slice.SliceRequestBus(bus.Broadcast, "CreateNewSlice", landscape_canvas.id, slice_path)
# Verify if slice is created
helper.wait_for_condition(lambda: path_is_valid_asset(slice_path), 5.0)
Report.result(Tests.slice_created, path_is_valid_asset(slice_path))
# Instantiate slice
transform = math.Transform_CreateIdentity()
asset_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", slice_path, math.Uuid(), False)
test_slice = slice.SliceRequestBus(bus.Broadcast, "InstantiateSliceFromAssetId", asset_id, transform)
helper.wait_for_condition(lambda: test_slice.IsValid(), 5.0)
Report.result(Tests.slice_instantiated, test_slice.IsValid())
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(Slice_CreateInstantiate)
@@ -67,7 +67,6 @@ def SlotConnections_UpdateComponentReferences():
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID
@@ -101,8 +100,7 @@ def SlotConnections_UpdateComponentReferences():
newEntityId = parameters[0]
# Open an existing simple level
helper.init_idle()
helper.open_level("Physics", "Base")
hydra.open_base_level()
# Open Landscape Canvas tool and verify
general.open_pane('Landscape Canvas')
@@ -1,29 +1,88 @@
"""
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
"""
import os
import pytest
import sys
import ly_test_tools.environment.file_system as file_system
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../automatedtesting_shared')
from base import TestAutomationBase
from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorParallelTest, EditorTestSuite
@pytest.mark.SUITE_main
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(TestAutomationBase):
class TestAutomation(EditorTestSuite):
def test_LandscapeCanvas_SlotConnections_UpdateComponentReferences(self, request, workspace, editor, launcher_platform):
from .EditorScripts import SlotConnections_UpdateComponentReferences as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
class test_LandscapeCanvas_AreaNodes_DependentComponentsAdded(EditorSharedTest):
from .EditorScripts import AreaNodes_DependentComponentsAdded as test_module
def test_LandscapeCanvas_GradientMixer_NodeConstruction(self, request, workspace, editor, launcher_platform):
class test_LandscapeCanvas_AreaNodes_EntityCreatedOnNodeAdd(EditorSharedTest):
from .EditorScripts import AreaNodes_EntityCreatedOnNodeAdd as test_module
class test_LandscapeCanvas_AreaNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
from .EditorScripts import AreaNodes_EntityRemovedOnNodeDelete as test_module
class test_LandscapeCanvas_Component_AddedRemoved(EditorSharedTest):
from .EditorScripts import Component_AddedRemoved as test_module
class test_LandscapeCanvas_ComponentUpdates_UpdateGraph(EditorSharedTest):
from .EditorScripts import ComponentUpdates_UpdateGraph as test_module
class test_LandscapeCanvas_Edit_DisabledNodeDuplication(EditorSharedTest):
from .EditorScripts import Edit_DisabledNodeDuplication as test_module
class test_LandscapeCanvas_Edit_UndoNodeDelete_PrefabEntity(EditorSharedTest):
from .EditorScripts import Edit_UndoNodeDelete_PrefabEntity as test_module
class test_LandscapeCanvas_GradientMixer_NodeConstruction(EditorSharedTest):
from .EditorScripts import GradientMixer_NodeConstruction as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
class test_LandscapeCanvas_GradientModifierNodes_EntityCreatedOnNodeAdd(EditorSharedTest):
from .EditorScripts import GradientModifierNodes_EntityCreatedOnNodeAdd as test_module
class test_LandscapeCanvas_GradientModifierNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
from .EditorScripts import GradientModifierNodes_EntityRemovedOnNodeDelete as test_module
class test_LandscapeCanvas_GradientNodes_DependentComponentsAdded(EditorSharedTest):
from .EditorScripts import GradientNodes_DependentComponentsAdded as test_module
class test_LandscapeCanvas_GradientNodes_EntityCreatedOnNodeAdd(EditorSharedTest):
from .EditorScripts import GradientNodes_EntityCreatedOnNodeAdd as test_module
class test_LandscapeCanvas_GradientNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
from .EditorScripts import GradientNodes_EntityRemovedOnNodeDelete as test_module
@pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/2201")
class test_LandscapeCanvas_GraphClosed_OnEntityDelete(EditorSharedTest):
from .EditorScripts import GraphClosed_OnEntityDelete as test_module
class test_LandscapeCanvas_GraphClosed_OnLevelChange(EditorSharedTest):
from .EditorScripts import GraphClosed_OnLevelChange as test_module
class test_LandscapeCanvas_GraphClosed_TabbedGraphClosesIndependently(EditorSharedTest):
from .EditorScripts import GraphClosed_TabbedGraph as test_module
@pytest.mark.skip(reason="https://github.com/o3de/o3de/issues/7141" "https://github.com/o3de/o3de/issues/4872")
class test_LandscapeCanvas_GraphUpdates_UpdateComponents(EditorSharedTest):
from .EditorScripts import GraphUpdates_UpdateComponents as test_module
class test_LandscapeCanvas_LayerBlender_NodeConstruction(EditorSharedTest):
from .EditorScripts import LayerBlender_NodeConstruction as test_module
class test_LandscapeCanvas_LayerExtenderNodes_ComponentEntitySync(EditorSharedTest):
from .EditorScripts import LayerExtenderNodes_ComponentEntitySync as test_module
class test_LandscapeCanvas_NewGraph_CreatedSuccessfully(EditorSharedTest):
from .EditorScripts import NewGraph_CreatedSuccessfully as test_module
class test_LandscapeCanvas_Prefab_CreateInstantiate(EditorSharedTest):
from .EditorScripts import Prefab_CreateInstantiate as test_module
class test_LandscapeCanvas_ShapeNodes_EntityCreatedOnNodeAdd(EditorSharedTest):
from .EditorScripts import ShapeNodes_EntityCreatedOnNodeAdd as test_module
class test_LandscapeCanvas_ShapeNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
from .EditorScripts import ShapeNodes_EntityRemovedOnNodeDelete as test_module
class test_LandscapeCanvas_SlotConnections_UpdateComponentReferences(EditorSharedTest):
from .EditorScripts import SlotConnections_UpdateComponentReferences as test_module
@@ -1,104 +0,0 @@
"""
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
"""
import os
import pytest
import ly_test_tools.environment.file_system as file_system
import ly_test_tools._internal.pytest_plugin as internal_plugin
from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorParallelTest, EditorTestSuite
@pytest.mark.SUITE_periodic
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomationWithPrefabSystemEnabled(EditorTestSuite):
class test_LandscapeCanvas_AreaNodes_DependentComponentsAdded(EditorSharedTest):
from .EditorScripts import AreaNodes_DependentComponentsAdded as test_module
@pytest.mark.SUITE_periodic
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(EditorTestSuite):
enable_prefab_system = False
class test_LandscapeCanvas_SlotConnections_UpdateComponentReferences(EditorSharedTest):
from .EditorScripts import SlotConnections_UpdateComponentReferences as test_module
class test_LandscapeCanvas_GradientMixer_NodeConstruction(EditorSharedTest):
from .EditorScripts import GradientMixer_NodeConstruction as test_module
class test_LandscapeCanvas_AreaNodes_EntityCreatedOnNodeAdd(EditorSharedTest):
from .EditorScripts import AreaNodes_EntityCreatedOnNodeAdd as test_module
class test_LandscapeCanvas_AreaNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
from .EditorScripts import AreaNodes_EntityRemovedOnNodeDelete as test_module
class test_LandscapeCanvas_LayerExtenderNodes_ComponentEntitySync(EditorSharedTest):
from .EditorScripts import LayerExtenderNodes_ComponentEntitySync as test_module
class test_LandscapeCanvas_Edit_DisabledNodeDuplication(EditorSharedTest):
from .EditorScripts import Edit_DisabledNodeDuplication as test_module
class test_LandscapeCanvas_Edit_UndoNodeDelete_SliceEntity(EditorSharedTest):
from .EditorScripts import Edit_UndoNodeDelete_SliceEntity as test_module
class test_LandscapeCanvas_NewGraph_CreatedSuccessfully(EditorSharedTest):
from .EditorScripts import NewGraph_CreatedSuccessfully as test_module
class test_LandscapeCanvas_Component_AddedRemoved(EditorSharedTest):
from .EditorScripts import Component_AddedRemoved as test_module
class test_LandscapeCanvas_GraphClosed_OnLevelChange(EditorSharedTest):
from .EditorScripts import GraphClosed_OnLevelChange as test_module
@pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/2201")
class test_LandscapeCanvas_GraphClosed_OnEntityDelete(EditorSharedTest):
from .EditorScripts import GraphClosed_OnEntityDelete as test_module
class test_LandscapeCanvas_GraphClosed_TabbedGraphClosesIndependently(EditorSharedTest):
from .EditorScripts import GraphClosed_TabbedGraph as test_module
class test_LandscapeCanvas_Slice_CreateInstantiate(EditorSingleTest):
from .EditorScripts import Slice_CreateInstantiate as test_module
# Custom teardown to remove slice asset created during test
def teardown(self, request, workspace, editor, editor_test_results, launcher_platform):
file_system.delete([os.path.join(workspace.paths.engine_root(), "AutomatedTesting", "slices",
"TestSlice.slice")], True, True)
class test_LandscapeCanvas_GradientModifierNodes_EntityCreatedOnNodeAdd(EditorSharedTest):
from .EditorScripts import GradientModifierNodes_EntityCreatedOnNodeAdd as test_module
class test_LandscapeCanvas_GradientModifierNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
from .EditorScripts import GradientModifierNodes_EntityRemovedOnNodeDelete as test_module
class test_LandscapeCanvas_GradientNodes_DependentComponentsAdded(EditorSharedTest):
from .EditorScripts import GradientNodes_DependentComponentsAdded as test_module
class test_LandscapeCanvas_GradientNodes_EntityCreatedOnNodeAdd(EditorSharedTest):
from .EditorScripts import GradientNodes_EntityCreatedOnNodeAdd as test_module
class test_LandscapeCanvas_GradientNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
from .EditorScripts import GradientNodes_EntityRemovedOnNodeDelete as test_module
@pytest.mark.skipif("debug" == os.path.basename(internal_plugin.build_directory),
reason="https://github.com/o3de/o3de/issues/4872")
class test_LandscapeCanvas_GraphUpdates_UpdateComponents(EditorSharedTest):
from .EditorScripts import GraphUpdates_UpdateComponents as test_module
class test_LandscapeCanvas_ComponentUpdates_UpdateGraph(EditorSharedTest):
from .EditorScripts import ComponentUpdates_UpdateGraph as test_module
class test_LandscapeCanvas_LayerBlender_NodeConstruction(EditorSharedTest):
from .EditorScripts import LayerBlender_NodeConstruction as test_module
class test_LandscapeCanvas_ShapeNodes_EntityCreatedOnNodeAdd(EditorSharedTest):
from .EditorScripts import ShapeNodes_EntityCreatedOnNodeAdd as test_module
class test_LandscapeCanvas_ShapeNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
from .EditorScripts import ShapeNodes_EntityRemovedOnNodeDelete as test_module
@@ -1,121 +0,0 @@
"""
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
"""
import os
import pytest
import sys
import ly_test_tools.environment.file_system as file_system
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../automatedtesting_shared')
from base import TestAutomationBase
@pytest.fixture
def remove_test_slice(request, workspace, project):
file_system.delete([os.path.join(workspace.paths.engine_root(), project, "slices", "TestSlice.slice")], True, True)
def teardown():
file_system.delete([os.path.join(workspace.paths.engine_root(), project, "slices", "TestSlice.slice")], True,
True)
request.addfinalizer(teardown)
@pytest.mark.SUITE_periodic
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(TestAutomationBase):
def test_LandscapeCanvas_AreaNodes_DependentComponentsAdded(self, request, workspace, editor, launcher_platform):
from .EditorScripts import AreaNodes_DependentComponentsAdded as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_AreaNodes_EntityCreatedOnNodeAdd(self, request, workspace, editor, launcher_platform):
from .EditorScripts import AreaNodes_EntityCreatedOnNodeAdd as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_AreaNodes_EntityRemovedOnNodeDelete(self, request, workspace, editor, launcher_platform):
from .EditorScripts import AreaNodes_EntityRemovedOnNodeDelete as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_LayerExtenderNodes_ComponentEntitySync(self, request, workspace, editor, launcher_platform):
from .EditorScripts import LayerExtenderNodes_ComponentEntitySync as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_Edit_DisabledNodeDuplication(self, request, workspace, editor, launcher_platform):
from .EditorScripts import Edit_DisabledNodeDuplication as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_Edit_UndoNodeDelete_SliceEntity(self, request, workspace, editor, launcher_platform):
from .EditorScripts import Edit_UndoNodeDelete_SliceEntity as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_NewGraph_CreatedSuccessfully(self, request, workspace, editor, launcher_platform):
from .EditorScripts import NewGraph_CreatedSuccessfully as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_Component_AddedRemoved(self, request, workspace, editor, launcher_platform):
from .EditorScripts import Component_AddedRemoved as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_GraphClosed_OnLevelChange(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GraphClosed_OnLevelChange as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/2201")
def test_LandscapeCanvas_GraphClosed_OnEntityDelete(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GraphClosed_OnEntityDelete as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_GraphClosed_TabbedGraphClosesIndependently(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GraphClosed_TabbedGraph as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_Slice_CreateInstantiate(self, request, workspace, editor, remove_test_slice, launcher_platform):
from .EditorScripts import Slice_CreateInstantiate as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_GradientModifierNodes_EntityCreatedOnNodeAdd(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientModifierNodes_EntityCreatedOnNodeAdd as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_GradientModifierNodes_EntityRemovedOnNodeDelete(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientModifierNodes_EntityRemovedOnNodeDelete as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_GradientNodes_DependentComponentsAdded(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientNodes_DependentComponentsAdded as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_GradientNodes_EntityCreatedOnNodeAdd(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientNodes_EntityCreatedOnNodeAdd as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_GradientNodes_EntityRemovedOnNodeDelete(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientNodes_EntityRemovedOnNodeDelete as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_GraphUpdates_UpdateComponents(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GraphUpdates_UpdateComponents as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_ComponentUpdates_UpdateGraph(self, request, workspace, editor, launcher_platform):
from .EditorScripts import ComponentUpdates_UpdateGraph as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_LayerBlender_NodeConstruction(self, request, workspace, editor, launcher_platform):
from .EditorScripts import LayerBlender_NodeConstruction as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_ShapeNodes_EntityCreatedOnNodeAdd(self, request, workspace, editor, launcher_platform):
from .EditorScripts import ShapeNodes_EntityCreatedOnNodeAdd as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_ShapeNodes_EntityRemovedOnNodeDelete(self, request, workspace, editor, launcher_platform):
from .EditorScripts import ShapeNodes_EntityRemovedOnNodeDelete as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@@ -0,0 +1,151 @@
{
"ContainerEntity": {
"Id": "ContainerEntity",
"Name": "Player",
"Components": {
"Component_[10626669441604518614]": {
"$type": "EditorPrefabComponent",
"Id": 10626669441604518614
},
"Component_[15284109105474306026]": {
"$type": "EditorVisibilityComponent",
"Id": 15284109105474306026
},
"Component_[1884250773831675865]": {
"$type": "SelectionComponent",
"Id": 1884250773831675865
},
"Component_[3027124663594865592]": {
"$type": "EditorInspectorComponent",
"Id": 3027124663594865592
},
"Component_[3314300526416851038]": {
"$type": "EditorEntitySortComponent",
"Id": 3314300526416851038,
"Child Entity Order": [
"Entity_[1340484004600]"
]
},
"Component_[5583377204116393478]": {
"$type": "EditorEntityIconComponent",
"Id": 5583377204116393478
},
"Component_[5897955848881060165]": {
"$type": "EditorLockComponent",
"Id": 5897955848881060165
},
"Component_[6405389103180201977]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 6405389103180201977,
"Parent Entity": ""
},
"Component_[7695912346724202125]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 7695912346724202125
},
"Component_[775363990560391238]": {
"$type": "EditorOnlyEntityComponent",
"Id": 775363990560391238
},
"Component_[904355854135646057]": {
"$type": "EditorPendingCompositionComponent",
"Id": 904355854135646057
}
}
},
"Entities": {
"Entity_[1340484004600]": {
"Id": "Entity_[1340484004600]",
"Name": "Player",
"Components": {
"Component_[12294726333564087591]": {
"$type": "SelectionComponent",
"Id": 12294726333564087591
},
"Component_[13587084088242540786]": {
"$type": "EditorInspectorComponent",
"Id": 13587084088242540786,
"ComponentOrderEntryArray": [
{
"ComponentId": 6819443882832501114
},
{
"ComponentId": 4337571454344109612,
"SortIndex": 1
},
{
"ComponentId": 16457408099527309065,
"SortIndex": 2
},
{
"ComponentId": 5577505593558922067,
"SortIndex": 3
}
]
},
"Component_[14335168881008289852]": {
"$type": "EditorEntitySortComponent",
"Id": 14335168881008289852
},
"Component_[16308902899170829847]": {
"$type": "EditorVisibilityComponent",
"Id": 16308902899170829847
},
"Component_[16457408099527309065]": {
"$type": "GenericComponentWrapper",
"Id": 16457408099527309065,
"m_template": {
"$type": "Multiplayer::NetworkTransformComponent"
}
},
"Component_[16541569566865026527]": {
"$type": "EditorOnlyEntityComponent",
"Id": 16541569566865026527
},
"Component_[2002761223483048905]": {
"$type": "EditorPendingCompositionComponent",
"Id": 2002761223483048905
},
"Component_[4337571454344109612]": {
"$type": "GenericComponentWrapper",
"Id": 4337571454344109612,
"m_template": {
"$type": "NetBindComponent"
}
},
"Component_[477591477979440744]": {
"$type": "EditorLockComponent",
"Id": 477591477979440744
},
"Component_[5577505593558922067]": {
"$type": "AZ::Render::EditorMeshComponent",
"Id": 5577505593558922067,
"Controller": {
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{6DE0E9A8-A1C7-5D0F-9407-4E627C1F223C}",
"subId": 284780167
},
"assetHint": "models/sphere.azmodel"
}
}
}
},
"Component_[5828214869455694702]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 5828214869455694702
},
"Component_[6819443882832501114]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 6819443882832501114,
"Parent Entity": "ContainerEntity"
},
"Component_[8838623765985560328]": {
"$type": "EditorEntityIconComponent",
"Id": 8838623765985560328
}
}
}
}
}
@@ -0,0 +1,580 @@
{
"ContainerEntity": {
"Id": "Entity_[1146574390643]",
"Name": "Level",
"Components": {
"Component_[10641544592923449938]": {
"$type": "EditorInspectorComponent",
"Id": 10641544592923449938
},
"Component_[12039882709170782873]": {
"$type": "EditorOnlyEntityComponent",
"Id": 12039882709170782873
},
"Component_[12265484671603697631]": {
"$type": "EditorPendingCompositionComponent",
"Id": 12265484671603697631
},
"Component_[14126657869720434043]": {
"$type": "EditorEntitySortComponent",
"Id": 14126657869720434043,
"Child Entity Order": [
"Entity_[1176639161715]",
"Entity_[806656324666]"
]
},
"Component_[15230859088967841193]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 15230859088967841193,
"Parent Entity": ""
},
"Component_[16239496886950819870]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 16239496886950819870
},
"Component_[5688118765544765547]": {
"$type": "EditorEntityIconComponent",
"Id": 5688118765544765547
},
"Component_[6545738857812235305]": {
"$type": "SelectionComponent",
"Id": 6545738857812235305
},
"Component_[7247035804068349658]": {
"$type": "EditorPrefabComponent",
"Id": 7247035804068349658
},
"Component_[9307224322037797205]": {
"$type": "EditorLockComponent",
"Id": 9307224322037797205
},
"Component_[9562516168917670048]": {
"$type": "EditorVisibilityComponent",
"Id": 9562516168917670048
}
}
},
"Entities": {
"Entity_[1155164325235]": {
"Id": "Entity_[1155164325235]",
"Name": "Sun",
"Components": {
"Component_[10440557478882592717]": {
"$type": "SelectionComponent",
"Id": 10440557478882592717
},
"Component_[13620450453324765907]": {
"$type": "EditorLockComponent",
"Id": 13620450453324765907
},
"Component_[2134313378593666258]": {
"$type": "EditorInspectorComponent",
"Id": 2134313378593666258
},
"Component_[234010807770404186]": {
"$type": "EditorVisibilityComponent",
"Id": 234010807770404186
},
"Component_[2970359110423865725]": {
"$type": "EditorEntityIconComponent",
"Id": 2970359110423865725
},
"Component_[3722854130373041803]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3722854130373041803
},
"Component_[5992533738676323195]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 5992533738676323195
},
"Component_[7378860763541895402]": {
"$type": "AZ::Render::EditorDirectionalLightComponent",
"Id": 7378860763541895402,
"Controller": {
"Configuration": {
"Intensity": 1.0,
"CameraEntityId": "",
"ShadowFilterMethod": 1
}
}
},
"Component_[7892834440890947578]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 7892834440890947578,
"Parent Entity": "Entity_[1176639161715]",
"Transform Data": {
"Translate": [
0.0,
0.0,
13.487043380737305
],
"Rotate": [
-76.13099670410156,
-0.847000002861023,
-15.8100004196167
]
}
},
"Component_[8599729549570828259]": {
"$type": "EditorEntitySortComponent",
"Id": 8599729549570828259
},
"Component_[952797371922080273]": {
"$type": "EditorPendingCompositionComponent",
"Id": 952797371922080273
}
}
},
"Entity_[1159459292531]": {
"Id": "Entity_[1159459292531]",
"Name": "Ground",
"Components": {
"Component_[11701138785793981042]": {
"$type": "SelectionComponent",
"Id": 11701138785793981042
},
"Component_[12260880513256986252]": {
"$type": "EditorEntityIconComponent",
"Id": 12260880513256986252
},
"Component_[13711420870643673468]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 13711420870643673468
},
"Component_[138002849734991713]": {
"$type": "EditorOnlyEntityComponent",
"Id": 138002849734991713
},
"Component_[16578565737331764849]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 16578565737331764849,
"Parent Entity": "Entity_[1176639161715]"
},
"Component_[16919232076966545697]": {
"$type": "EditorInspectorComponent",
"Id": 16919232076966545697
},
"Component_[5182430712893438093]": {
"$type": "EditorMaterialComponent",
"Id": 5182430712893438093
},
"Component_[5675108321710651991]": {
"$type": "AZ::Render::EditorMeshComponent",
"Id": 5675108321710651991,
"Controller": {
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{0CD745C0-6AA8-569A-A68A-73A3270986C4}",
"subId": 277889906
},
"assetHint": "objects/groudplane/groundplane_512x512m.azmodel"
}
}
}
},
"Component_[5681893399601237518]": {
"$type": "EditorEntitySortComponent",
"Id": 5681893399601237518
},
"Component_[592692962543397545]": {
"$type": "EditorPendingCompositionComponent",
"Id": 592692962543397545
},
"Component_[7090012899106946164]": {
"$type": "EditorLockComponent",
"Id": 7090012899106946164
},
"Component_[9410832619875640998]": {
"$type": "EditorVisibilityComponent",
"Id": 9410832619875640998
}
}
},
"Entity_[1163754259827]": {
"Id": "Entity_[1163754259827]",
"Name": "Camera",
"Components": {
"Component_[11895140916889160460]": {
"$type": "EditorEntityIconComponent",
"Id": 11895140916889160460
},
"Component_[16880285896855930892]": {
"$type": "{CA11DA46-29FF-4083-B5F6-E02C3A8C3A3D} EditorCameraComponent",
"Id": 16880285896855930892,
"Controller": {
"Configuration": {
"Field of View": 55.0,
"EditorEntityId": 9021008456353177945
}
}
},
"Component_[17187464423780271193]": {
"$type": "EditorLockComponent",
"Id": 17187464423780271193
},
"Component_[17495696818315413311]": {
"$type": "EditorEntitySortComponent",
"Id": 17495696818315413311
},
"Component_[18086214374043522055]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 18086214374043522055,
"Parent Entity": "Entity_[1176639161715]",
"Transform Data": {
"Translate": [
-2.3000001907348633,
-3.9368600845336914,
1.0
],
"Rotate": [
-2.050307512283325,
1.9552897214889526,
-43.623355865478516
]
}
},
"Component_[18387556550380114975]": {
"$type": "SelectionComponent",
"Id": 18387556550380114975
},
"Component_[2654521436129313160]": {
"$type": "EditorVisibilityComponent",
"Id": 2654521436129313160
},
"Component_[5265045084611556958]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 5265045084611556958
},
"Component_[7169798125182238623]": {
"$type": "EditorPendingCompositionComponent",
"Id": 7169798125182238623
},
"Component_[7255796294953281766]": {
"$type": "GenericComponentWrapper",
"Id": 7255796294953281766,
"m_template": {
"$type": "FlyCameraInputComponent"
}
},
"Component_[8866210352157164042]": {
"$type": "EditorInspectorComponent",
"Id": 8866210352157164042
},
"Component_[9129253381063760879]": {
"$type": "EditorOnlyEntityComponent",
"Id": 9129253381063760879
}
}
},
"Entity_[1168049227123]": {
"Id": "Entity_[1168049227123]",
"Name": "Grid",
"Components": {
"Component_[11443347433215807130]": {
"$type": "EditorEntityIconComponent",
"Id": 11443347433215807130
},
"Component_[11779275529534764488]": {
"$type": "SelectionComponent",
"Id": 11779275529534764488
},
"Component_[14249419413039427459]": {
"$type": "EditorInspectorComponent",
"Id": 14249419413039427459
},
"Component_[15448581635946161318]": {
"$type": "AZ::Render::EditorGridComponent",
"Id": 15448581635946161318,
"Controller": {
"Configuration": {
"primarySpacing": 4.0,
"primaryColor": [
0.501960813999176,
0.501960813999176,
0.501960813999176
],
"secondarySpacing": 0.5,
"secondaryColor": [
0.250980406999588,
0.250980406999588,
0.250980406999588
]
}
}
},
"Component_[1843303322527297409]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 1843303322527297409
},
"Component_[380249072065273654]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 380249072065273654,
"Parent Entity": "Entity_[1176639161715]"
},
"Component_[7476660583684339787]": {
"$type": "EditorPendingCompositionComponent",
"Id": 7476660583684339787
},
"Component_[7557626501215118375]": {
"$type": "EditorEntitySortComponent",
"Id": 7557626501215118375
},
"Component_[7984048488947365511]": {
"$type": "EditorVisibilityComponent",
"Id": 7984048488947365511
},
"Component_[8118181039276487398]": {
"$type": "EditorOnlyEntityComponent",
"Id": 8118181039276487398
},
"Component_[9189909764215270515]": {
"$type": "EditorLockComponent",
"Id": 9189909764215270515
}
}
},
"Entity_[1176639161715]": {
"Id": "Entity_[1176639161715]",
"Name": "Atom Default Environment",
"Components": {
"Component_[10757302973393310045]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 10757302973393310045,
"Parent Entity": "Entity_[1146574390643]"
},
"Component_[14505817420424255464]": {
"$type": "EditorInspectorComponent",
"Id": 14505817420424255464,
"ComponentOrderEntryArray": [
{
"ComponentId": 10757302973393310045
}
]
},
"Component_[14988041764659020032]": {
"$type": "EditorLockComponent",
"Id": 14988041764659020032
},
"Component_[15808690248755038124]": {
"$type": "SelectionComponent",
"Id": 15808690248755038124
},
"Component_[15900837685796817138]": {
"$type": "EditorVisibilityComponent",
"Id": 15900837685796817138
},
"Component_[3298767348226484884]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3298767348226484884
},
"Component_[4076975109609220594]": {
"$type": "EditorPendingCompositionComponent",
"Id": 4076975109609220594
},
"Component_[5679760548946028854]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 5679760548946028854
},
"Component_[5855590796136709437]": {
"$type": "EditorEntitySortComponent",
"Id": 5855590796136709437,
"Child Entity Order": [
"Entity_[1155164325235]",
"Entity_[1180934129011]",
"Entity_[1168049227123]",
"Entity_[1163754259827]",
"Entity_[1159459292531]"
]
},
"Component_[9277695270015777859]": {
"$type": "EditorEntityIconComponent",
"Id": 9277695270015777859
}
}
},
"Entity_[1180934129011]": {
"Id": "Entity_[1180934129011]",
"Name": "Global Sky",
"Components": {
"Component_[11231930600558681245]": {
"$type": "AZ::Render::EditorHDRiSkyboxComponent",
"Id": 11231930600558681245,
"Controller": {
"Configuration": {
"CubemapAsset": {
"assetId": {
"guid": "{215E47FD-D181-5832-B1AB-91673ABF6399}",
"subId": 1000
},
"assetHint": "lightingpresets/highcontrast/goegap_4k_skyboxcm.exr.streamingimage"
}
}
}
},
"Component_[11980494120202836095]": {
"$type": "SelectionComponent",
"Id": 11980494120202836095
},
"Component_[1428633914413949476]": {
"$type": "EditorLockComponent",
"Id": 1428633914413949476
},
"Component_[14936200426671614999]": {
"$type": "AZ::Render::EditorImageBasedLightComponent",
"Id": 14936200426671614999,
"Controller": {
"Configuration": {
"diffuseImageAsset": {
"assetId": {
"guid": "{3FD09945-D0F2-55C8-B9AF-B2FD421FE3BE}",
"subId": 3000
},
"assetHint": "lightingpresets/highcontrast/goegap_4k_iblglobalcm_ibldiffuse.exr.streamingimage"
},
"specularImageAsset": {
"assetId": {
"guid": "{3FD09945-D0F2-55C8-B9AF-B2FD421FE3BE}",
"subId": 2000
},
"assetHint": "lightingpresets/highcontrast/goegap_4k_iblglobalcm_iblspecular.exr.streamingimage"
}
}
}
},
"Component_[14994774102579326069]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 14994774102579326069
},
"Component_[15417479889044493340]": {
"$type": "EditorPendingCompositionComponent",
"Id": 15417479889044493340
},
"Component_[15826613364991382688]": {
"$type": "EditorEntitySortComponent",
"Id": 15826613364991382688
},
"Component_[1665003113283562343]": {
"$type": "EditorOnlyEntityComponent",
"Id": 1665003113283562343
},
"Component_[3704934735944502280]": {
"$type": "EditorEntityIconComponent",
"Id": 3704934735944502280
},
"Component_[5698542331457326479]": {
"$type": "EditorVisibilityComponent",
"Id": 5698542331457326479
},
"Component_[6644513399057217122]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 6644513399057217122,
"Parent Entity": "Entity_[1176639161715]"
},
"Component_[931091830724002070]": {
"$type": "EditorInspectorComponent",
"Id": 931091830724002070
}
}
},
"Entity_[806656324666]": {
"Id": "Entity_[806656324666]",
"Name": "NetEntity",
"Components": {
"Component_[10272449525230713408]": {
"$type": "EditorScriptCanvasComponent",
"Id": 10272449525230713408,
"m_name": "SimpleNetworkLevelEntity.scriptcanvas",
"runtimeDataIsValid": true,
"runtimeDataOverrides": {
"source": {
"id": "{C8F17F94-1225-5FFB-A89F-7C5546FF9DD2}",
"path": "C:/prj/o3de/AutomatedTesting/Levels/Multiplayer/SimpleNetworkLevelEntity/SimpleNetworkLevelEntity.scriptcanvas"
}
},
"sourceHandle": {
"id": "{C8F17F94-1225-5FFB-A89F-7C5546FF9DD2}",
"path": "C:/prj/o3de/AutomatedTesting/Levels/Multiplayer/SimpleNetworkLevelEntity/SimpleNetworkLevelEntity.scriptcanvas"
}
},
"Component_[12604265186664827718]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 12604265186664827718
},
"Component_[12971088454284742740]": {
"$type": "EditorInspectorComponent",
"Id": 12971088454284742740
},
"Component_[13637345797899267673]": {
"$type": "EditorPendingCompositionComponent",
"Id": 13637345797899267673
},
"Component_[14691827217729577086]": {
"$type": "EditorVisibilityComponent",
"Id": 14691827217729577086
},
"Component_[17587769654029626028]": {
"$type": "AZ::Render::EditorMeshComponent",
"Id": 17587769654029626028,
"Controller": {
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{6DE0E9A8-A1C7-5D0F-9407-4E627C1F223C}",
"subId": 284780167
},
"assetHint": "models/sphere.azmodel"
}
}
}
},
"Component_[3583806849894952953]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3583806849894952953
},
"Component_[3992057042487734240]": {
"$type": "EditorLockComponent",
"Id": 3992057042487734240
},
"Component_[4205899043279271481]": {
"$type": "GenericComponentWrapper",
"Id": 4205899043279271481,
"m_template": {
"$type": "Multiplayer::NetworkTransformComponent"
}
},
"Component_[4416976521140638764]": {
"$type": "EditorEntityIconComponent",
"Id": 4416976521140638764
},
"Component_[4951162661196722987]": {
"$type": "EditorEntitySortComponent",
"Id": 4951162661196722987
},
"Component_[57491843687005111]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 57491843687005111,
"Parent Entity": "Entity_[1146574390643]",
"Transform Data": {
"Translate": [
-0.010266244411468506,
0.09999752044677734,
0.4922151565551758
]
}
},
"Component_[7427201282284088219]": {
"$type": "SelectionComponent",
"Id": 7427201282284088219
},
"Component_[9767802049284917261]": {
"$type": "GenericComponentWrapper",
"Id": 9767802049284917261,
"m_template": {
"$type": "NetBindComponent"
}
}
}
}
}
}
@@ -0,0 +1,228 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "ScriptCanvasData",
"ClassData": {
"m_scriptCanvas": {
"Id": {
"id": 5227099818161821361
},
"Name": "Script Canvas Graph",
"Components": {
"Component_[14745706451564425001]": {
"$type": "EditorGraphVariableManagerComponent",
"Id": 14745706451564425001
},
"Component_[6188351434280490877]": {
"$type": "EditorGraph",
"Id": 6188351434280490877,
"m_graphData": {
"m_nodes": [
{
"Id": {
"id": 1181151842701
},
"Name": "SC-Node(Print)",
"Components": {
"Component_[11204048151736284490]": {
"$type": "Print",
"Id": 11204048151736284490,
"Slots": [
{
"id": {
"m_id": "{A417FF98-493E-4DE6-AD3A-E7A1848661E4}"
},
"contracts": [
{
"$type": "SlotTypeContract"
}
],
"slotName": "In",
"toolTip": "Input signal",
"Descriptor": {
"ConnectionType": 1,
"SlotType": 1
}
},
{
"id": {
"m_id": "{38BC2AB1-7654-407E-9903-4B5D77EDB6F3}"
},
"contracts": [
{
"$type": "SlotTypeContract"
}
],
"slotName": "Out",
"Descriptor": {
"ConnectionType": 2,
"SlotType": 1
}
}
],
"m_format": "SimpleNetworkLevelEntity: On Graph Start\n",
"m_unresolvedString": [
"SimpleNetworkLevelEntity: On Graph Start\n"
]
}
}
},
{
"Id": {
"id": 811784655245
},
"Name": "SC-Node(Start)",
"Components": {
"Component_[2986280341871382503]": {
"$type": "Start",
"Id": 2986280341871382503,
"Slots": [
{
"id": {
"m_id": "{61FBEFC6-23BA-4A53-89BF-D0D0E834608C}"
},
"contracts": [
{
"$type": "SlotTypeContract"
}
],
"slotName": "Out",
"toolTip": "Signaled when the entity that owns this graph is fully activated.",
"Descriptor": {
"ConnectionType": 2,
"SlotType": 1
}
}
]
}
}
}
],
"m_connections": [
{
"Id": {
"id": 2521181639053
},
"Name": "srcEndpoint=(On Graph Start: Out), destEndpoint=(Print: In)",
"Components": {
"Component_[16295428600276205051]": {
"$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
"Id": 16295428600276205051,
"sourceEndpoint": {
"nodeId": {
"id": 811784655245
},
"slotId": {
"m_id": "{61FBEFC6-23BA-4A53-89BF-D0D0E834608C}"
}
},
"targetEndpoint": {
"nodeId": {
"id": 1181151842701
},
"slotId": {
"m_id": "{A417FF98-493E-4DE6-AD3A-E7A1848661E4}"
}
}
}
}
}
]
},
"m_assetType": "{00000000-0000-0000-D033-B2489A010000}",
"versionData": {
"_grammarVersion": 1,
"_runtimeVersion": 1,
"_fileVersion": 1
},
"GraphCanvasData": [
{
"Key": {
"id": 811784655245
},
"Value": {
"ComponentData": {
"{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
"$type": "NodeSaveData"
},
"{328FF15C-C302-458F-A43D-E1794DE0904E}": {
"$type": "GeneralNodeTitleComponentSaveData",
"PaletteOverride": "TimeNodeTitlePalette"
},
"{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
"$type": "GeometrySaveData",
"Position": [
340.0,
180.0
]
},
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
"$type": "StylingComponentSaveData"
},
"{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
"$type": "PersistentIdComponentSaveData",
"PersistentId": "{6045F7F7-02B0-442A-96C7-A0CBCEFF7275}"
}
}
}
},
{
"Key": {
"id": 1181151842701
},
"Value": {
"ComponentData": {
"{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
"$type": "NodeSaveData"
},
"{328FF15C-C302-458F-A43D-E1794DE0904E}": {
"$type": "GeneralNodeTitleComponentSaveData",
"PaletteOverride": "StringNodeTitlePalette"
},
"{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
"$type": "GeometrySaveData",
"Position": [
580.0,
180.0
]
},
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
"$type": "StylingComponentSaveData"
},
"{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
"$type": "PersistentIdComponentSaveData",
"PersistentId": "{589F773E-D82A-4EDD-AEBD-3ADC07FC67CE}"
}
}
}
},
{
"Key": {
"id": 5227099818161821361
},
"Value": {
"ComponentData": {
"{5F84B500-8C45-40D1-8EFC-A5306B241444}": {
"$type": "SceneComponentSaveData"
}
}
}
}
],
"StatisticsHelper": {
"InstanceCounter": [
{
"Key": 4199610336680704683,
"Value": 1
},
{
"Key": 10684225535275896474,
"Value": 1
}
]
}
}
}
}
}
}
@@ -0,0 +1,12 @@
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
+1 -1
View File
@@ -16,4 +16,4 @@
"external_subdirectories": [
"Gem"
]
}
}
+5 -50
View File
@@ -17,6 +17,7 @@
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
#include <AzToolsFramework/Viewport/ViewportInteractionHelpers.h>
#include <QApplication>
@@ -33,53 +34,6 @@ namespace SandboxEditor
ViewportManipulatorControllerInstance::~ViewportManipulatorControllerInstance() = default;
AzToolsFramework::ViewportInteraction::MouseButton ViewportManipulatorControllerInstance::GetMouseButton(
const AzFramework::InputChannel& inputChannel)
{
using AzToolsFramework::ViewportInteraction::MouseButton;
using InputButton = AzFramework::InputDeviceMouse::Button;
const auto& id = inputChannel.GetInputChannelId();
if (id == InputButton::Left)
{
return MouseButton::Left;
}
if (id == InputButton::Middle)
{
return MouseButton::Middle;
}
if (id == InputButton::Right)
{
return MouseButton::Right;
}
return MouseButton::None;
}
bool ViewportManipulatorControllerInstance::IsMouseMove(const AzFramework::InputChannel& inputChannel)
{
return inputChannel.GetInputChannelId() == AzFramework::InputDeviceMouse::SystemCursorPosition;
}
AzToolsFramework::ViewportInteraction::KeyboardModifier ViewportManipulatorControllerInstance::GetKeyboardModifier(
const AzFramework::InputChannel& inputChannel)
{
using AzToolsFramework::ViewportInteraction::KeyboardModifier;
using Key = AzFramework::InputDeviceKeyboard::Key;
const auto& id = inputChannel.GetInputChannelId();
if (id == Key::ModifierAltL || id == Key::ModifierAltR)
{
return KeyboardModifier::Alt;
}
if (id == Key::ModifierCtrlL || id == Key::ModifierCtrlR)
{
return KeyboardModifier::Ctrl;
}
if (id == Key::ModifierShiftL || id == Key::ModifierShiftR)
{
return KeyboardModifier::Shift;
}
return KeyboardModifier::None;
}
bool ViewportManipulatorControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
{
// We only care about manipulator and viewport interaction events
@@ -97,6 +51,7 @@ namespace SandboxEditor
using AzToolsFramework::ViewportInteraction::MouseInteractionEvent;
using AzToolsFramework::ViewportInteraction::ProjectedViewportRay;
using AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus;
using AzToolsFramework::ViewportInteraction::Helpers;
bool interactionHandled = false;
float wheelDelta = 0.0f;
@@ -109,7 +64,7 @@ namespace SandboxEditor
const bool finishedProcessingEvents = event.m_priority == InteractionPriority;
const auto state = event.m_inputChannel.GetState();
if (IsMouseMove(event.m_inputChannel))
if (Helpers::IsMouseMove(event.m_inputChannel))
{
// Cache the ray trace results when doing manipulator interaction checks, no need to recalculate after
if (event.m_priority == ManipulatorPriority)
@@ -136,7 +91,7 @@ namespace SandboxEditor
eventType = MouseEvent::Move;
}
else if (auto mouseButton = GetMouseButton(event.m_inputChannel); mouseButton != MouseButton::None)
else if (auto mouseButton = Helpers::GetMouseButton(event.m_inputChannel); mouseButton != MouseButton::None)
{
const AZ::u32 mouseButtonValue = static_cast<AZ::u32>(mouseButton);
overrideButton = mouseButton;
@@ -178,7 +133,7 @@ namespace SandboxEditor
}
}
}
else if (auto keyboardModifier = GetKeyboardModifier(event.m_inputChannel); keyboardModifier != KeyboardModifier::None)
else if (auto keyboardModifier = Helpers::GetKeyboardModifier(event.m_inputChannel); keyboardModifier != KeyboardModifier::None)
{
if (state == InputChannel::State::Began || state == InputChannel::State::Updated)
{
@@ -35,10 +35,6 @@ namespace SandboxEditor
private:
bool IsDoubleClick(AzToolsFramework::ViewportInteraction::MouseButton) const;
static AzToolsFramework::ViewportInteraction::MouseButton GetMouseButton(const AzFramework::InputChannel& inputChannel);
static bool IsMouseMove(const AzFramework::InputChannel& inputChannel);
static AzToolsFramework::ViewportInteraction::KeyboardModifier GetKeyboardModifier(const AzFramework::InputChannel& inputChannel);
//! Represents the time and location of a click.
struct ClickEvent
{
@@ -49,7 +49,7 @@ namespace AZ
return m_entity->GetId();
}
AZ_Warning("System", false, "Can't get component %p entity ID as it is not attached to an entity yet!", this);
AZ_Warning("System", false, "Can't get component (type: %s, addr: %p) entity ID as it is not attached to an entity yet!", RTTI_GetTypeName(), this);
return EntityId();
}
@@ -60,7 +60,7 @@ namespace AZ
return NamedEntityId(m_entity->GetId(), m_entity->GetName());
}
AZ_Warning("System", false, "Can't get component %p entity ID as it is not attached to an entity yet!", this);
AZ_Warning("System", false, "Can't get component (type: %s, addr: %p) entity ID as it is not attached to an entity yet!", RTTI_GetTypeName(), this);
return NamedEntityId();
}
@@ -230,7 +230,7 @@ namespace AZ
EBUS_EVENT_ID(m_id, EntityBus, OnEntityDeactivated, m_id);
EBUS_EVENT(EntitySystemBus, OnEntityDeactivated, m_id);
AZ_Assert(m_state == State::Active, "Component should be in Active state to br Deactivated!");
AZ_Assert(m_state == State::Active, "Component should be in Active state to be Deactivated!");
SetState(State::Deactivating);
for (ComponentArrayType::reverse_iterator it = m_components.rbegin(); it != m_components.rend(); ++it)
@@ -1668,9 +1668,23 @@ namespace AZ
SerializeContext::ENUM_ACCESS_FOR_READ,
&m_errorLogger
);
if (objectStreamWriteOverrideCB.Invoke<void>(callContext, objectPtr, *classData, classElement))
if (ObjectStreamWriteOverrideResponse writeResponse;
objectStreamWriteOverrideCB.Read<ObjectStreamWriteOverrideResponse>(writeResponse, callContext, objectPtr, *classData, classElement))
{
return false;
switch (writeResponse)
{
case ObjectStreamWriteOverrideResponse::FallbackToDefaultWrite:
break;
case ObjectStreamWriteOverrideResponse::AbortWrite:
m_errorLogger.ReportError(AZStd::string::format("ObjectStream Write Element Override callback has aborted the write for class data %s",
classData->m_name).c_str());
[[fallthrough]];
case ObjectStreamWriteOverrideResponse::CompletedWrite:
return false;
default:
AZ_Error("Serialize", false, "Invalid Response %d returned from the ObjectStream Write Element Override callback", static_cast<int>(writeResponse));
return false;
}
}
else
{
@@ -49,14 +49,24 @@ namespace AZ
static const AZ::Crc32 ObjectStreamWriteElementOverride = AZ_CRC("ObjectStreamWriteElementOverride", 0x35eb659f);
}
enum class ObjectStreamWriteOverrideResponse
{
CompletedWrite,
FallbackToDefaultWrite,
AbortWrite
};
AZ_TYPE_INFO_SPECIALIZE(ObjectStreamWriteOverrideResponse, "{BDF960A8-0F18-4E9D-96DA-F800A122C42D}");
///< Callback that the object stream invokes to override saving an instance of the registered class
///< @param callContext EnumerateInstanceCallContext which contains the WriteElement BeingElemCB and the CloseElement EndElemCB
///< the callContext parameter can be passed to the SerializeContext::EnumerateInstance to continue object stream writing
///< @param classPtr class type which is of pointer to the type represented by the m_typeId value
///< @param classData reference to this instance Class Data that will be supplied to the callback
///< @param classElement class element pointer which contains information about the element being serialized.
///< root elements do not not have a valid class element pointer
using ObjectStreamWriteOverrideCB = AZStd::function<void(SerializeContext::EnumerateInstanceCallContext& callContext,
///< root elements have a nullptr classElement
///< @return enum to indicate that the override has saved the registered class and that the default writing should be skipped.
///< Returning false will have the WriteElement code fallback to using the default logic
using ObjectStreamWriteOverrideCB = AZStd::function<ObjectStreamWriteOverrideResponse(SerializeContext::EnumerateInstanceCallContext& callContext,
const void* classPtr, const SerializeContext::ClassData& classData, const SerializeContext::ClassElement* classElement)>;
AZ_TYPE_INFO_SPECIALIZE(ObjectStreamWriteOverrideCB, "{87B1A36B-8C8A-42B6-A0B5-E770D9FDBAD4}");
@@ -12,6 +12,8 @@
namespace AZ
{
enum class ObjectStreamWriteOverrideResponse;
namespace VariantSerializationInternal
{
template <class ValueType>
@@ -480,7 +482,7 @@ namespace AZ
}
}
private:
static void ObjectStreamWriter(SerializeContext::EnumerateInstanceCallContext& callContext, const void* variantPtr,
static ObjectStreamWriteOverrideResponse ObjectStreamWriter(SerializeContext::EnumerateInstanceCallContext& callContext, const void* variantPtr,
[[maybe_unused]] const SerializeContext::ClassData& variantClassData, const SerializeContext::ClassElement* variantClassElement)
{
auto alternativeVisitor = [&callContext, variantClassElement](auto&& elementAlt)
@@ -503,6 +505,9 @@ namespace AZ
};
AZStd::visit(AZStd::move(alternativeVisitor), *reinterpret_cast<const VariantType*>(variantPtr));
// To avoid including ObjectStream.h into this file, we static cast the value of 0
// to an AZ::ObjectStreamWriteElemntResponse which corresponds to the CompletedWrite enum value
return static_cast<AZ::ObjectStreamWriteOverrideResponse>(0);
}
VariantSerializationInternal::AZStdVariantContainer<Types...> m_variantContainer;
@@ -62,25 +62,25 @@ set(FILES
../Common/UnixLike/AzCore/std/time_UnixLike.cpp
AzCore/Utils/Utils_Android.cpp
../Common/Unimplemented/AzCore/Utils/Utils_Unimplemented.cpp
../../AzCore/Android/AndroidEnv.cpp
../../AzCore/Android/AndroidEnv.h
../../AzCore/Android/APKFileHandler.cpp
../../AzCore/Android/APKFileHandler.h
../../AzCore/Android/ApiLevel.h
../../AzCore/Android/Utils.cpp
../../AzCore/Android/Utils.h
../../AzCore/Android/JNI/JNI.cpp
../../AzCore/Android/JNI/JNI.h
../../AzCore/Android/JNI/Object.h
../../AzCore/Android/JNI/Object_fwd.h
../../AzCore/Android/JNI/scoped_ref.h
../../AzCore/Android/JNI/shared_ref.h
../../AzCore/Android/JNI/Signature.h
../../AzCore/Android/JNI/Internal/ClassName.h
../../AzCore/Android/JNI/Internal/JStringUtils.h
../../AzCore/Android/JNI/Internal/JStringUtils_impl.h
../../AzCore/Android/JNI/Internal/Object_impl.h
../../AzCore/Android/JNI/Internal/Signature_impl.h
AzCore/Android/AndroidEnv.cpp
AzCore/Android/AndroidEnv.h
AzCore/Android/APKFileHandler.cpp
AzCore/Android/APKFileHandler.h
AzCore/Android/ApiLevel.h
AzCore/Android/Utils.cpp
AzCore/Android/Utils.h
AzCore/Android/JNI/JNI.cpp
AzCore/Android/JNI/JNI.h
AzCore/Android/JNI/Object.h
AzCore/Android/JNI/Object_fwd.h
AzCore/Android/JNI/scoped_ref.h
AzCore/Android/JNI/shared_ref.h
AzCore/Android/JNI/Signature.h
AzCore/Android/JNI/Internal/ClassName.h
AzCore/Android/JNI/Internal/JStringUtils.h
AzCore/Android/JNI/Internal/JStringUtils_impl.h
AzCore/Android/JNI/Internal/Object_impl.h
AzCore/Android/JNI/Internal/Signature_impl.h
AzCore/Debug/Profiler_Platform.inl
AzCore/Debug/Profiler_Android.inl
)
@@ -720,6 +720,49 @@ namespace SerializeTestClasses {
AZStd::intrusive_ptr<SmartPtrClass> m_intrusivePtr;
AZStd::unique_ptr<SmartPtrClass> m_uniquePtr;
};
struct ElementOverrideType
{
AZ_RTTI(ElementOverrideType, "{BAA18B6C-3CB3-476C-8B41-21EA7CE1F4CF}");
AZ_CLASS_ALLOCATOR(ElementOverrideType, AZ::SystemAllocator, 0);
virtual ~ElementOverrideType() = default;
static AZ::ObjectStreamWriteOverrideResponse Writer(
AZ::SerializeContext::EnumerateInstanceCallContext& callContext,
const void* object,
const AZ::SerializeContext::ClassData&,
const AZ::SerializeContext::ClassElement*)
{
auto ptr = static_cast<const ElementOverrideType*>(object);
if(ptr)
{
switch(ptr->m_field)
{
case 0:
{
float output{};
callContext.m_context->EnumerateInstanceConst(&callContext, &output, azrtti_typeid<decltype(output)>(), nullptr, nullptr);
return AZ::ObjectStreamWriteOverrideResponse::CompletedWrite;
}
case 1:
return AZ::ObjectStreamWriteOverrideResponse::FallbackToDefaultWrite;
}
}
return AZ::ObjectStreamWriteOverrideResponse::AbortWrite;
}
static void Reflect(AZ::SerializeContext& sc)
{
sc.Class<ElementOverrideType>()
->Attribute(AZ::SerializeContextAttributes::ObjectStreamWriteElementOverride, &ElementOverrideType::Writer)
->Field("field", &ElementOverrideType::m_field);
}
int m_field = 0;
};
} //SerializeTestClasses
namespace AZ
@@ -1698,6 +1741,66 @@ namespace UnitTest
}
}
TEST_F(Serialization, ElementOverrideTest_DefaultSerializationWorks)
{
ElementOverrideType::Reflect(*m_serializeContext);
ElementOverrideType testType;
testType.m_field = 1; // Our custom serializer will use the default output when this value is 1
AZStd::vector<char> buffer;
IO::ByteContainerStream<AZStd::vector<char>> stream(&buffer);
ASSERT_TRUE(Utils::SaveObjectToStream(stream, DataStream::ST_XML, &testType, m_serializeContext.get()));
constexpr const char* expectedValue =
R"(<ObjectStream version="3">)" "\n"
"\t" R"(<Class name="ElementOverrideType" type="{BAA18B6C-3CB3-476C-8B41-21EA7CE1F4CF}">)" "\n"
"\t\t" R"(<Class name="int" field="field" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>)" "\n"
"\t" R"(</Class>)" "\n"
R"(</ObjectStream>)";
AZStd::string result(buffer.data(), stream.GetLength());
AZ::StringFunc::TrimWhiteSpace(result, true, true);
EXPECT_STREQ(result.c_str(), expectedValue);
}
TEST_F(Serialization, ElementOverrideTest_CustomSerializationWorks)
{
ElementOverrideType::Reflect(*m_serializeContext);
ElementOverrideType testType;
testType.m_field = 0; // Our custom serializer will do its own output when this value is 0
AZStd::vector<char> buffer;
IO::ByteContainerStream<AZStd::vector<char>> stream(&buffer);
ASSERT_TRUE(Utils::SaveObjectToStream(stream, DataStream::ST_XML, &testType, m_serializeContext.get()));
constexpr const char* expectedValue =
R"(<ObjectStream version="3">)" "\n"
"\t" R"(<Class name="float" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>)" "\n"
R"(</ObjectStream>)";
AZStd::string result(buffer.data(), stream.GetLength());
AZ::StringFunc::TrimWhiteSpace(result, true, true);
EXPECT_STREQ(result.c_str(), expectedValue);
}
TEST_F(Serialization, ElementOverrideTest_FailureCase)
{
ElementOverrideType::Reflect(*m_serializeContext);
ElementOverrideType testType;
testType.m_field = 2; // Our custom serializer will report a failure when this value is not 0/1
AZStd::vector<char> buffer;
IO::ByteContainerStream<AZStd::vector<char>> stream(&buffer);
AZ_TEST_START_TRACE_SUPPRESSION;
ASSERT_FALSE(Utils::SaveObjectToStream(stream, DataStream::ST_XML, &testType, m_serializeContext.get()));
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
}
TEST_F(Serialization, ContainerTypeContainedTypeDiffersByPointer)
{
ContainersTest::ReflectVectorOfInts(m_serializeContext.get());
@@ -15,7 +15,7 @@ namespace AzFramework
{
// Redirects writing of the AssetBundleManifest to an older version if the bundle version
// is not set to the current version
static void OldBundleManifestWriter(AZ::SerializeContext::EnumerateInstanceCallContext& callContext, const void* bundleManifestPointer,
static AZ::ObjectStreamWriteOverrideResponse OldBundleManifestWriter(AZ::SerializeContext::EnumerateInstanceCallContext& callContext, const void* bundleManifestPointer,
const AZ::SerializeContext::ClassData&, const AZ::SerializeContext::ClassElement* assetBundleManifestClassElement);
static bool BundleManifestVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& rootElement);
@@ -67,7 +67,7 @@ namespace AzFramework
return true;
}
void OldBundleManifestWriter(AZ::SerializeContext::EnumerateInstanceCallContext& callContext, const void* bundleManifestPointer,
AZ::ObjectStreamWriteOverrideResponse OldBundleManifestWriter(AZ::SerializeContext::EnumerateInstanceCallContext& callContext, const void* bundleManifestPointer,
const AZ::SerializeContext::ClassData&, const AZ::SerializeContext::ClassElement* assetBundleManifestClassElement)
{
// Copy the AssetBundleManifest current version instance to the AssetBundleManifest V2 instance
@@ -145,7 +145,10 @@ namespace AzFramework
ReflectAssetBundleManifestV2(serializeContext);
serializeContext->DisableRemoveReflection();
AssetBundleManifest::ReflectSerialize(serializeContext);
return AZ::ObjectStreamWriteOverrideResponse::CompletedWrite;
}
return AZ::ObjectStreamWriteOverrideResponse::FallbackToDefaultWrite;
}
const AZStd::vector<AZ::IO::Path>& AssetBundleManifest::GetLevelDirectories() const
@@ -12,13 +12,12 @@
AZ_PUSH_DISABLE_WARNING(4244 4251, "-Wunknown-warning-option") // 4251: 'QLayoutItem::align': class 'QFlags<Qt::AlignmentFlag>' needs to have dll-interface to be used by clients of class 'QLayoutItem'
#include <QHBoxLayout>
#include <QToolButton>
#include <QToolBar>
#include <QLabel>
#include <QHBoxLayout>
#include <QSettings>
#include <QMenu>
#include <QResizeEvent>
#include <QSettings>
#include <QToolBar>
#include <QToolButton>
AZ_POP_DISABLE_WARNING
namespace AzQtComponents
@@ -46,7 +45,7 @@ namespace AzQtComponents
m_label = new QLabel(this);
m_label->setObjectName(g_labelName);
boxLayout->addWidget(m_label);
m_label->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
m_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
connect(m_label, &QLabel::linkActivated, this, &BreadCrumbs::onLinkActivated);
}
@@ -82,9 +81,38 @@ namespace AzQtComponents
// clean up the path to use all the first separator in the list of separators
m_currentPath.replace(g_windowsSeparator, g_separator);
// update internals
m_currentPathSize = m_currentPath.split(g_separator, Qt::SkipEmptyParts).size();
m_currentPathIcons.resize(m_currentPathSize);
fillLabel();
}
void BreadCrumbs::setDefaultIcon(const QString& icon)
{
m_defaultIcon = icon;
}
void BreadCrumbs::setIconAt(int index, const QString& icon)
{
if (index < 0 || index >= m_currentPathSize)
{
return;
}
m_currentPathIcons[index] = icon;
}
QIcon BreadCrumbs::iconAt(int index)
{
if (index < 0 || index >= m_currentPathSize || m_currentPathIcons[index].isNull())
{
return QIcon(m_defaultIcon);
}
return QIcon(m_currentPathIcons[index]);
}
bool BreadCrumbs::getPushPathOnLinkActivation() const
{
return m_pushPathOnLinkActivation;
@@ -220,6 +248,26 @@ namespace AzQtComponents
QWidget::resizeEvent(event);
}
QString BreadCrumbs::generateIconHtml(int index)
{
QString imagePath;
if (index >= 0 && index < m_currentPathIcons.size())
{
imagePath = m_currentPathIcons[index];
}
if (imagePath.isEmpty())
{
imagePath = m_defaultIcon;
}
return !imagePath.isEmpty() ? QStringLiteral("<img width=\"16\" height=\"16\" style=\"vertical-align: middle\" src=\"%1\">%2%2")
.arg(imagePath)
.arg("&nbsp;")
: "";
}
void BreadCrumbs::fillLabel()
{
QString htmlString = "";
@@ -247,7 +295,10 @@ namespace AzQtComponents
plainTextPath = m_truncatedPaths.takeLast();
}
htmlString.prepend(plainTextPath);
int index = m_currentPathSize - 1;
htmlString.prepend(generateIconHtml(index) + plainTextPath);
--index;
while (!m_truncatedPaths.isEmpty())
{
@@ -262,7 +313,7 @@ namespace AzQtComponents
const QString linkPath = buildPathFromList(fullPath, m_truncatedPaths.size());
const QString& part = m_truncatedPaths.takeLast();
htmlString.prepend(QString("%1").arg(formatLink(linkPath, part)));
htmlString.prepend(QString("%1%2").arg(generateIconHtml(index--)).arg(formatLink(linkPath, part)));
}
m_label->setText(htmlString);
@@ -78,6 +78,13 @@ namespace AzQtComponents
//! Sets the current breadcrumb path without updating the navigation stack.
void setCurrentPath(const QString& newPath);
//! Sets a default icon for path elements.
void setDefaultIcon(const QString& iconPath);
//! Sets an icon for the path element at index.
void setIconAt(int index, const QString& iconPath);
//! Gets the icon for the path element at index.
QIcon iconAt(int index);
//! Returns true if activating a link should automatically push a new path to the navigation stack.
bool getPushPathOnLinkActivation() const;
//! Sets whether activating a link should automatically push a new path to the navigation stack.
@@ -134,6 +141,7 @@ namespace AzQtComponents
void onLinkActivated(const QString& link);
private:
QString generateIconHtml(int index);
void fillLabel();
void changePath(const QString& newPath);
@@ -155,6 +163,14 @@ namespace AzQtComponents
QStringList m_truncatedPaths;
AZ_POP_DISABLE_WARNING
bool m_pushPathOnLinkActivation = true;
int m_currentPathSize = 0;
QString m_defaultIcon;
AZ_PUSH_DISABLE_WARNING(
4251, "-Wunknown-warning-option") // 4251: 'AzQtComponents::BreadCrumbs::m_currentPathIcons': class 'QVector<QIcon>' needs to have
// dll-interface to be used by clients of class 'AzQtComponents::BreadCrumbs'
QVector<QString> m_currentPathIcons;
AZ_POP_DISABLE_WARNING
friend class Style;
@@ -447,7 +447,7 @@ namespace AzToolsFramework
else
{
loadedSuccessfully = static_cast<PrefabEditorEntityOwnershipService*>(m_entityOwnershipService.get())->LoadFromStream(
stream, AZStd::string_view(levelPakFile.toUtf8(), levelPakFile.size()) );
stream, AZStd::string_view(levelPakFile.toUtf8().constData(), levelPakFile.size()) );
}
@@ -65,6 +65,9 @@ namespace AzToolsFramework
bool Connection::Open(const AZStd::string& filename, bool readOnly)
{
AZ_Assert(sqlite3_libversion_number() == SQLITE_VERSION_NUMBER, "Sqlite header version number does not match library");
AZ_Assert(strncmp(sqlite3_sourceid(), SQLITE_SOURCE_ID, 80) == 0, "Sqlite header source id does not match library");
AZ_Assert(strcmp(sqlite3_libversion(), SQLITE_VERSION) == 0, "Sqlite header version does not match library");
AZ_Assert(m_db == NULL, "You have to close the database prior to opening a new one.");
if (m_db)
{
@@ -44,6 +44,9 @@ namespace AzToolsFramework::Prefab
m_breadcrumbsWidget = breadcrumbsWidget;
m_backButton = backButton;
// Add icons to the widget
m_breadcrumbsWidget->setDefaultIcon(QString(":/Entity/prefab_edit.svg"));
// If a part of the path is clicked, focus on that instance
connect(m_breadcrumbsWidget, &AzQtComponents::BreadCrumbs::linkClicked, this,
[&](const QString&, int linkIndex)
@@ -74,6 +77,9 @@ namespace AzToolsFramework::Prefab
// Push new Path
m_breadcrumbsWidget->pushPath(m_prefabFocusPublicInterface->GetPrefabFocusPath(m_editorEntityContextId).c_str());
// Set root icon
m_breadcrumbsWidget->setIconAt(0, QString(":/Level/level.svg"));
// If root instance is focused, disable the back button; else enable it.
m_backButton->setEnabled(m_prefabFocusPublicInterface->GetPrefabFocusPathLength(m_editorEntityContextId) > 1);
}
@@ -0,0 +1,60 @@
/*
* 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
*
*/
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzToolsFramework/Viewport/ViewportInteractionHelpers.h>
namespace AzToolsFramework::ViewportInteraction
{
MouseButton Helpers::GetMouseButton(const AzFramework::InputChannel& inputChannel)
{
using AzToolsFramework::ViewportInteraction::MouseButton;
using InputButton = AzFramework::InputDeviceMouse::Button;
const AzFramework::InputChannelId& id = inputChannel.GetInputChannelId();
if (id == InputButton::Left)
{
return MouseButton::Left;
}
if (id == InputButton::Middle)
{
return MouseButton::Middle;
}
if (id == InputButton::Right)
{
return MouseButton::Right;
}
return MouseButton::None;
}
bool Helpers::IsMouseMove(const AzFramework::InputChannel& inputChannel)
{
return inputChannel.GetInputChannelId() == AzFramework::InputDeviceMouse::SystemCursorPosition;
}
KeyboardModifier Helpers::GetKeyboardModifier(const AzFramework::InputChannel& inputChannel)
{
using AzToolsFramework::ViewportInteraction::KeyboardModifier;
using Key = AzFramework::InputDeviceKeyboard::Key;
const auto& id = inputChannel.GetInputChannelId();
if (id == Key::ModifierAltL || id == Key::ModifierAltR)
{
return KeyboardModifier::Alt;
}
if (id == Key::ModifierCtrlL || id == Key::ModifierCtrlR)
{
return KeyboardModifier::Ctrl;
}
if (id == Key::ModifierShiftL || id == Key::ModifierShiftR)
{
return KeyboardModifier::Shift;
}
return KeyboardModifier::None;
}
} // namespace AzToolsFramework::ViewportInteraction
@@ -0,0 +1,23 @@
/*
* 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
*
*/
#pragma once
#include <AzFramework/Input/Channels/InputChannel.h>
#include <AzToolsFramework/Viewport/ViewportTypes.h>
namespace AzToolsFramework::ViewportInteraction
{
class Helpers
{
public:
static MouseButton GetMouseButton(const AzFramework::InputChannel& inputChannel);
static bool IsMouseMove(const AzFramework::InputChannel& inputChannel);
static KeyboardModifier GetKeyboardModifier(const AzFramework::InputChannel& inputChannel);
};
} // namespace AzToolsFramework::ViewportInteraction
@@ -150,6 +150,9 @@ namespace AzToolsFramework
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
};
//! A bus to listen to just the MouseViewportRequests.
using ViewportMouseRequestBus = AZ::EBus<MouseViewportRequests, ViewportEBusTraits>;
//! Requests that can be made to the viewport to query and modify its state.
class ViewportInteractionRequests
{
@@ -504,6 +504,8 @@ set(FILES
Viewport/EditorContextMenu.cpp
Viewport/VertexContainerDisplay.h
Viewport/VertexContainerDisplay.cpp
Viewport/ViewportInteractionHelpers.h
Viewport/ViewportInteractionHelpers.cpp
Viewport/ViewportMessages.h
Viewport/ViewportMessages.cpp
Viewport/ViewportTypes.h
-1
View File
@@ -27,7 +27,6 @@ if(PAL_TRAIT_AZTESTRUNNER_SUPPORTED AND NOT LY_MONOLITHIC_GAME)
PRIVATE
AZ::AzCore
AZ::AzTest
AZ::AzFramework
)
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
@@ -10,3 +10,8 @@ set(LY_INCLUDE_DIRECTORIES
PRIVATE
${LY_NDK_NATIVE_APP_GLUE_SRC_DIR}
)
set(LY_BUILD_DEPENDENCIES
PRIVATE
AZ::AzFramework
)
@@ -19,7 +19,7 @@
"UUID": "{08A95286-ADB2-41E4-96EB-DB48F4726D6A}",
"Name": "Albedo",
"RGB_Weight": "CIEXYZ",
"PixelFormat": "ASTC_6x6",
"PixelFormat": "ASTC_4x4",
"MaxTextureSize": 2048,
"DiscardAlpha": true,
"IsPowerOf2": true,
@@ -18,7 +18,7 @@
"UUID": "{57ED16B1-407B-4E29-BCFC-D3BAE60F2C85}",
"Name": "AlbedoWithCoverage",
"RGB_Weight": "CIEXYZ",
"PixelFormat": "ASTC_6x6",
"PixelFormat": "ASTC_4x4",
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
@@ -17,7 +17,7 @@
"UUID": "{5D9ECB52-4CD9-4CB8-80E3-10CAE5EFB8A2}",
"Name": "AlbedoWithGenericAlpha",
"RGB_Weight": "CIEXYZ",
"PixelFormat": "ASTC_6x6",
"PixelFormat": "ASTC_4x4",
"MaxTextureSize": 2048,
"MipMapSetting": {
"MipGenType": "Box"

Some files were not shown because too many files have changed in this diff Show More