merging latest dev

Signed-off-by: Gene Walters <genewalt@amazon.com>
This commit is contained in:
Gene Walters
2021-11-23 16:16:55 -08:00
1512 changed files with 22942 additions and 13282 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
---
name: ar_bug_report.md
name: Automated Review bug report
about: Create a bug for a an issue found in the Automated Review
title: 'AR Bug Report'
labels: 'needs-triage,kind/bug,kind/automation'
@@ -13,6 +13,8 @@ from ly_test_tools.o3de.editor_test import EditorSharedTest, EditorTestSuite
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
class TestAutomation(EditorTestSuite):
enable_prefab_system = False
@pytest.mark.test_case_id("C36525657")
class AtomEditorComponents_BloomAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_BloomAdded as test_module
@@ -104,6 +104,7 @@ class TestAllComponentsIndepthTests(object):
halt_on_unexpected=True,
cfg_args=[level],
null_renderer=False,
enable_prefab_system=False,
)
similarity_threshold = 0.99
@@ -158,6 +159,7 @@ class TestAllComponentsIndepthTests(object):
halt_on_unexpected=True,
cfg_args=[level],
null_renderer=False,
enable_prefab_system=False,
)
similarity_threshold = 0.99
@@ -205,6 +207,7 @@ class TestPerformanceBenchmarkSuite(object):
halt_on_unexpected=True,
cfg_args=[level],
null_renderer=False,
enable_prefab_system=False,
)
aggregator = BenchmarkDataAggregator(workspace, logger, 'periodic')
@@ -242,5 +245,6 @@ class TestMaterialEditor(object):
halt_on_unexpected=False,
null_renderer=False,
cfg_args=[cfg_args],
log_file_name="MaterialEditor.log"
log_file_name="MaterialEditor.log",
enable_prefab_system=False,
)
@@ -23,6 +23,8 @@ class TestAutomation(EditorTestSuite):
# Remove -autotest_mode from global_extra_cmdline_args since we need rendering for these tests.
global_extra_cmdline_args = ["-BatchMode"] # Default is ["-BatchMode", "-autotest_mode"]
enable_prefab_system = False
@pytest.mark.test_case_id("C34603773")
class AtomGPU_BasicLevelSetup_SetsUpLevel(EditorSharedTest):
use_null_renderer = False # Default is True
@@ -85,6 +85,7 @@ class TestAtomEditorComponentsMain(object):
halt_on_unexpected=True,
null_renderer=True,
cfg_args=cfg_args,
enable_prefab_system=False,
)
@@ -155,5 +156,6 @@ class TestMaterialEditorBasicTests(object):
halt_on_unexpected=True,
null_renderer=True,
log_file_name="MaterialEditor.log",
enable_prefab_system=False,
)
@@ -23,28 +23,28 @@ from base import TestAutomationBase
class TestAutomation(TestAutomationBase):
def test_ActorSplitsAfterCollision(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterCollision as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ActorSplitsAfterRadialDamage(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterRadialDamage as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ActorSplitsAfterCapsuleDamage(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterCapsuleDamage as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ActorSplitsAfterImpactSpreadDamage(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterImpactSpreadDamage as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ActorSplitsAfterShearDamage(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterShearDamage as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ActorSplitsAfterTriangleDamage(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterTriangleDamage as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ActorSplitsAfterStressDamage(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterStressDamage as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@@ -51,5 +51,6 @@ class TestComponentAssetListAutomation(object):
editor,
"ComponentUpdateListProperty_test_case.py",
expected_lines=expected_lines,
cfg_args=[level]
cfg_args=[level],
enable_prefab_system=False,
)
@@ -28,7 +28,7 @@ Assuming CMake is already setup on your operating system, below are some sample
cd /path/to/od3e/
mkdir windows_vs2019
cd windows_vs2019
cmake .. -G "Visual Studio 16 2019" -A x64 -T host=x64 -DLY_3RDPARTY_PATH="%3RDPARTYPATH%" -DLY_PROJECTS=AutomatedTesting
cmake .. -G "Visual Studio 16 2019" -DLY_PROJECTS=AutomatedTesting
To manually install the project in development mode using your own installed Python interpreter:
cd /path/to/od3e/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools
@@ -29,7 +29,7 @@ def teardown_editor(editor):
def launch_and_validate_results(request, test_directory, editor, editor_script, expected_lines, unexpected_lines=[],
halt_on_unexpected=False, run_python="--runpythontest", auto_test_mode=True, null_renderer=True, cfg_args=[],
timeout=300, log_file_name="Editor.log"):
timeout=300, log_file_name="Editor.log", enable_prefab_system=True):
"""
Runs the Editor with the specified script, and monitors for expected log lines.
:param request: Special fixture providing information of the requesting test function.
@@ -45,17 +45,22 @@ def launch_and_validate_results(request, test_directory, editor, editor_script,
:param cfg_args: Additional arguments for CFG, such as LevelName.
:param timeout: Length of time for test to run. Default is 60.
:param log_file_name: Name of the log file created by the editor. Defaults to 'Editor.log'
:param enable_prefab_system: Flag to determine whether to use new prefab system or use deprecated slice system. Defaults to True.
"""
test_case = os.path.join(test_directory, editor_script)
request.addfinalizer(lambda: teardown_editor(editor))
logger.debug("Running automated test: {}".format(editor_script))
editor.args.extend(["--skipWelcomeScreenDialog", "--regset=/Amazon/Settings/EnableSourceControl=false",
"--regset=/Amazon/Preferences/EnablePrefabSystem=false", run_python, test_case,
run_python, test_case,
f"--pythontestcase={request.node.name}", "--runpythonargs", " ".join(cfg_args)])
if auto_test_mode:
editor.args.extend(["--autotest_mode"])
if null_renderer:
editor.args.extend(["-rhi=Null"])
if enable_prefab_system:
editor.args.extend(["--regset=/Amazon/Preferences/EnablePrefabSystem=true"])
else:
editor.args.extend(["--regset=/Amazon/Preferences/EnablePrefabSystem=false"])
with editor.start():
@@ -23,7 +23,6 @@ from base import TestAutomationBase
class TestAutomation(TestAutomationBase):
def _run_prefab_test(self, request, workspace, editor, test_module, batch_mode=True, autotest_mode=True):
self._run_test(request, workspace, editor, test_module,
extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"],
batch_mode=batch_mode,
autotest_mode=autotest_mode)
@@ -24,7 +24,6 @@ from base import TestAutomationBase
class TestAutomation(TestAutomationBase):
def _run_prefab_test(self, request, workspace, editor, test_module, batch_mode=True, autotest_mode=True):
self._run_test(request, workspace, editor, test_module,
extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"],
batch_mode=batch_mode,
autotest_mode=autotest_mode)
@@ -25,8 +25,8 @@ class TestAutomation(TestAutomationBase):
def test_NvCloth_AddClothSimulationToMesh(self, request, workspace, editor, launcher_platform):
from .tests import NvCloth_AddClothSimulationToMesh as test_module
self._run_test(request, workspace, editor, test_module, use_null_renderer = self.use_null_renderer)
self._run_test(request, workspace, editor, test_module, use_null_renderer = self.use_null_renderer, enable_prefab_system=False)
def test_NvCloth_AddClothSimulationToActor(self, request, workspace, editor, launcher_platform):
from .tests import NvCloth_AddClothSimulationToActor as test_module
self._run_test(request, workspace, editor, test_module, use_null_renderer = self.use_null_renderer)
self._run_test(request, workspace, editor, test_module, use_null_renderer = self.use_null_renderer, enable_prefab_system=False)
@@ -26,158 +26,158 @@ class TestAutomation(TestAutomationBase):
r"AutomatedTesting\Levels\Physics\Material_LibraryCrudOperationsReflectOnRagdollBones")
def test_Material_LibraryCrudOperationsReflectOnRagdollBones(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_LibraryCrudOperationsReflectOnRagdollBones as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Material_RagdollBones(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_RagdollBones as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@fm.file_revert("c15308221_material_componentsinsyncwithlibrary.physmaterial",
r"AutomatedTesting\Levels\Physics\Material_ComponentsInSyncWithLibrary")
def test_Material_ComponentsInSyncWithLibrary(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_ComponentsInSyncWithLibrary as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
# BUG: LY-107723")
def test_ScriptCanvas_SetKinematicTargetTransform(self, request, workspace, editor, launcher_platform):
from .tests.script_canvas import ScriptCanvas_SetKinematicTargetTransform as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
# Failing, PhysXTerrain
@fm.file_revert("c4925579_material_addmodifydeleteonterrain.physmaterial",
r"AutomatedTesting\Levels\Physics\Material_LibraryCrudOperationsReflectOnTerrain")
def test_Material_LibraryCrudOperationsReflectOnTerrain(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_LibraryCrudOperationsReflectOnTerrain as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
# Failing, PhysXTerrain
def test_Terrain_TerrainTexturePainterWorks(self, request, workspace, editor, launcher_platform):
from .tests.terrain import Terrain_TerrainTexturePainterWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
# Failing, PhysXTerrain
def test_Material_CanBeAssignedToTerrain(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_CanBeAssignedToTerrain as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
# Failing, PhysXTerrain
def test_Material_DefaultLibraryConsistentOnAllFeatures(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_DefaultLibraryConsistentOnAllFeatures as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
# Failing, PhysXTerrain
@fm.file_revert("all_ones_1.physmaterial", r"AutomatedTesting\Levels\Physics\Material_DefaultMaterialLibraryChangesWork")
@fm.file_override("default.physxconfiguration", "Material_DefaultMaterialLibraryChangesWork.physxconfiguration", "AutomatedTesting")
def test_Material_DefaultMaterialLibraryChangesWork(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_DefaultMaterialLibraryChangesWork as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Collider_SameCollisionGroupSameLayerCollide(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_SameCollisionGroupSameLayerCollide as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Ragdoll_OldRagdollSerializationNoErrors(self, request, workspace, editor, launcher_platform):
from .tests.ragdoll import Ragdoll_OldRagdollSerializationNoErrors as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@fm.file_override("default.physxconfiguration", "ScriptCanvas_OverlapNode.physxconfiguration")
def test_ScriptCanvas_OverlapNode(self, request, workspace, editor, launcher_platform):
from .tests.script_canvas import ScriptCanvas_OverlapNode as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Material_StaticFriction(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_StaticFriction as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@fm.file_revert("c4888315_material_addmodifydeleteoncollider.physmaterial",
r"AutomatedTesting\Levels\Physics\Material_LibraryCrudOperationsReflectOnCollider")
def test_Material_LibraryCrudOperationsReflectOnCollider(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_LibraryCrudOperationsReflectOnCollider as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@fm.file_revert("c15563573_material_addmodifydeleteoncharactercontroller.physmaterial",
r"AutomatedTesting\Levels\Physics\Material_LibraryCrudOperationsReflectOnCharacterController")
def test_Material_LibraryCrudOperationsReflectOnCharacterController(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_LibraryCrudOperationsReflectOnCharacterController as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@fm.file_revert("c4888315_material_addmodifydeleteoncollider.physmaterial",
r"AutomatedTesting\Levels\Physics\Material_LibraryCrudOperationsReflectOnCollider")
def test_Material_LibraryCrudOperationsReflectOnCollider(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_LibraryCrudOperationsReflectOnCollider as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@fm.file_revert("c15563573_material_addmodifydeleteoncharactercontroller.physmaterial",
r"AutomatedTesting\Levels\Physics\Material_LibraryCrudOperationsReflectOnCharacterController")
def test_Material_LibraryCrudOperationsReflectOnCharacterController(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_LibraryCrudOperationsReflectOnCharacterController as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@fm.file_revert("c4044455_material_librarychangesinstantly.physmaterial",
r"AutomatedTesting\Levels\Physics\C4044455_Material_LibraryChangesInstantly")
def test_Material_LibraryChangesReflectInstantly(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_LibraryChangesReflectInstantly as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@fm.file_revert("Material_LibraryUpdatedAcrossLevels.physmaterial",
r"AutomatedTesting\Levels\Physics\Material_LibraryUpdatedAcrossLevels")
def test_Material_LibraryUpdatedAcrossLevels(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_LibraryUpdatedAcrossLevels as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_RigidBody_LinearDampingAffectsMotion(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_LinearDampingAffectsMotion as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Terrain_CollisionAgainstRigidBody(self, request, workspace, editor, launcher_platform):
from .tests.terrain import Terrain_CollisionAgainstRigidBody as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ShapeCollider_CylinderShapeCollides(self, request, workspace, editor, launcher_platform):
from .tests.collider import ShapeCollider_CylinderShapeCollides as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Physics_WorldBodyBusWorksOnEditorComponents(self, request, workspace, editor, launcher_platform):
from .tests import Physics_WorldBodyBusWorksOnEditorComponents as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Collider_PxMeshErrorIfNoMesh(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_PxMeshErrorIfNoMesh as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ForceRegion_ImpulsesBoxShapedRigidBody(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_ImpulsesBoxShapedRigidBody as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Terrain_SpawnSecondTerrainComponentWarning(self, request, workspace, editor, launcher_platform):
from .tests.terrain import Terrain_SpawnSecondTerrainComponentWarning as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Terrain_AddPhysTerrainComponent(self, request, workspace, editor, launcher_platform):
from .tests.terrain import Terrain_AddPhysTerrainComponent as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Terrain_CanAddMultipleTerrainComponents(self, request, workspace, editor, launcher_platform):
from .tests.terrain import Terrain_CanAddMultipleTerrainComponents as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Terrain_MultipleTerrainComponentsWarning(self, request, workspace, editor, launcher_platform):
from .tests.terrain import Terrain_MultipleTerrainComponentsWarning as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Terrain_MultipleTerrainComponentsWarning(self, request, workspace, editor, launcher_platform):
from .tests.terrain import Terrain_MultipleTerrainComponentsWarning as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ForceRegion_HighValuesDirectionAxesWorkWithNoError(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_HighValuesDirectionAxesWorkWithNoError as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Terrain_MultipleResolutionsValid(self, request, workspace, editor, launcher_platform):
from .tests.terrain import Terrain_MultipleResolutionsValid as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ForceRegion_SmallMagnitudeDeviationOnLargeForces(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_SmallMagnitudeDeviationOnLargeForces as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@@ -30,33 +30,33 @@ class TestAutomation(TestAutomationBase):
def test_RigidBody_EnablingGravityWorksUsingNotificationsPoC(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_EnablingGravityWorksUsingNotificationsPoC as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_LocalSpaceForceOnRigidBodies(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_LocalSpaceForceOnRigidBodies as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','Material_DynamicFriction.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_Material_DynamicFriction(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_DynamicFriction as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Collider_SameCollisionGroupDiffLayersCollide(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_SameCollisionGroupDiffLayersCollide as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_CharacterController_SwitchLevels(self, request, workspace, editor, launcher_platform):
from .tests.character_controller import CharacterController_SwitchLevels as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Ragdoll_AddPhysxRagdollComponentWorks(self, request, workspace, editor, launcher_platform):
from .tests.ragdoll import Ragdoll_AddPhysxRagdollComponentWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ScriptCanvas_MultipleRaycastNode(self, request, workspace, editor, launcher_platform):
@@ -64,43 +64,43 @@ class TestAutomation(TestAutomationBase):
# Fixme: This test previously relied on unexpected lines log reading with is now not supported.
# Now the log reading must be done inside the test, preferably with the Tracer() utility
# unexpected_lines = ["Assert"] + test_module.Lines.unexpected
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_Collider_DiffCollisionGroupDiffCollidingLayersNotCollide(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_DiffCollisionGroupDiffCollidingLayersNotCollide as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Joints_HingeLeadFollowerCollide(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_HingeLeadFollowerCollide as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Collider_PxMeshConvexMeshCollides(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_PxMeshConvexMeshCollides as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ShapeCollider_CylinderShapeCollides(self, request, workspace, editor, launcher_platform):
from .tests.shape_collider import ShapeCollider_CylinderShapeCollides as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_C15425929_Undo_Redo(self, request, workspace, editor, launcher_platform):
from .tests import Physics_UndoRedoWorksOnEntityWithPhysComponents as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.GROUP_tick
@pytest.mark.xfail(reason="Test still under development.")
def test_Tick_InterpolatedRigidBodyMotionIsSmooth(self, request, workspace, editor, launcher_platform):
from .tests.tick import Tick_InterpolatedRigidBodyMotionIsSmooth as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.GROUP_tick
@pytest.mark.xfail(reason="Test still under development.")
def test_Tick_CharacterGameplayComponentMotionIsSmooth(self, request, workspace, editor, launcher_platform):
from .tests.tick import Tick_CharacterGameplayComponentMotionIsSmooth as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@@ -59,9 +59,6 @@ class EditorSingleTest_WithFileOverrides(EditorSingleTest):
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomationWithPrefabSystemEnabled(EditorTestSuite):
global_extra_cmdline_args = ['-BatchMode', '-autotest_mode',
'--regset=/Amazon/Preferences/EnablePrefabSystem=true']
@staticmethod
def get_number_parallel_editors():
return 16
@@ -81,6 +78,8 @@ class TestAutomationWithPrefabSystemEnabled(EditorTestSuite):
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(EditorTestSuite):
enable_prefab_system = False
@staticmethod
def get_number_parallel_editors():
return 16
@@ -31,223 +31,223 @@ class TestAutomation(TestAutomationBase):
@revert_physics_config
def test_Terrain_NoPhysTerrainComponentNoCollision(self, request, workspace, editor, launcher_platform):
from .tests.terrain import Terrain_NoPhysTerrainComponentNoCollision as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_InitialLinearVelocity(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_InitialLinearVelocity as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_StartGravityEnabledWorks(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_StartGravityEnabledWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_KinematicModeWorks(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_KinematicModeWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_LinearDampingForceOnRigidBodies(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_LinearDampingForceOnRigidBodies as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_SimpleDragForceOnRigidBodies(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_SimpleDragForceOnRigidBodies as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_CapsuleShapedForce(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_CapsuleShapedForce as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_ImpulsesCapsuleShapedRigidBody(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_ImpulsesCapsuleShapedRigidBody as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_MomentOfInertiaManualSetting(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_MomentOfInertiaManualSetting as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_COM_ManualSettingWorks(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_COM_ManualSettingWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_AddRigidBodyComponent(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_AddRigidBodyComponent as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_SplineForceOnRigidBodies(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_SplineForceOnRigidBodies as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','Material_RestitutionCombine.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_Material_RestitutionCombine(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_RestitutionCombine as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','Material_FrictionCombine.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_Material_FrictionCombine(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_FrictionCombine as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Collider_ColliderPositionOffset(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_ColliderPositionOffset as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_AngularDampingAffectsRotation(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_AngularDampingAffectsRotation as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether(self, request, workspace, editor, launcher_platform):
from .tests import Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_MultipleForcesInSameComponentCombineForces(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_MultipleForcesInSameComponentCombineForces as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_ImpulsesPxMeshShapedRigidBody(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_ImpulsesPxMeshShapedRigidBody as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ScriptCanvas_TriggerEvents(self, request, workspace, editor, launcher_platform):
from .tests.script_canvas import ScriptCanvas_TriggerEvents as test_module
# FIXME: expected_lines = test_module.LogLines.expected_lines
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_ZeroPointForceDoesNothing(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_ZeroPointForceDoesNothing as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_ZeroWorldSpaceForceDoesNothing(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_ZeroWorldSpaceForceDoesNothing as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_ZeroLinearDampingDoesNothing(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_ZeroLinearDampingDoesNothing as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_MovingForceRegionChangesNetForce(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_MovingForceRegionChangesNetForce as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ScriptCanvas_CollisionEvents(self, request, workspace, editor, launcher_platform):
from .tests.script_canvas import ScriptCanvas_CollisionEvents as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_DirectionHasNoAffectOnTotalForce(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_DirectionHasNoAffectOnTotalForce as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_StartAsleepWorks(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_StartAsleepWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_SliceFileInstantiates(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_SliceFileInstantiates as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_ZeroLocalSpaceForceDoesNothing(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_ZeroLocalSpaceForceDoesNothing as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_ZeroSimpleDragForceDoesNothing(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_ZeroSimpleDragForceDoesNothing as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_COM_ComputingWorks(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_COM_ComputingWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_MassDifferentValuesWorks(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_MassDifferentValuesWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','Material_RestitutionCombinePriorityOrder.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_Material_RestitutionCombinePriorityOrder(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_RestitutionCombinePriorityOrder as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_SplineRegionWithModifiedTransform(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_SplineRegionWithModifiedTransform as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ScriptCanvas_ShapeCast(self, request, workspace, editor, launcher_platform):
from .tests.script_canvas import ScriptCanvas_ShapeCast as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_InitialAngularVelocity(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_InitialAngularVelocity as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_ZeroSplineForceDoesNothing(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_ZeroSplineForceDoesNothing as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Physics_DynamicSliceWithPhysNotSpawnsStaticSlice(self, request, workspace, editor, launcher_platform):
from .tests import Physics_DynamicSliceWithPhysNotSpawnsStaticSlice as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_PositionOffset(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_PositionOffset as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','Material_FrictionCombinePriorityOrder.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_Material_FrictionCombinePriorityOrder(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_FrictionCombinePriorityOrder as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(
reason="Something with the CryRenderer disabling is causing this test to fail now.")
@revert_physics_config
def test_Ragdoll_LevelSwitchDoesNotCrash(self, request, workspace, editor, launcher_platform):
from .tests.ragdoll import Ragdoll_LevelSwitchDoesNotCrash as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_MultipleComponentsCombineForces(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_MultipleComponentsCombineForces as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
# Marking the test as an expected failure due to sporadic failure on Automated Review: LYN-2580
# The test still runs, but a failure of the test doesn't result in the test run failing
@@ -258,102 +258,102 @@ class TestAutomation(TestAutomationBase):
'AutomatedTesting/Registry', search_subdirs=True)
def test_Material_PerFaceMaterialGetsCorrectMaterial(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_PerFaceMaterialGetsCorrectMaterial as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(
reason="This test will sometimes fail as the ball will continue to roll before the timeout is reached.")
@revert_physics_config
def test_RigidBody_SleepWhenBelowKineticThreshold(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_SleepWhenBelowKineticThreshold as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_COM_NotIncludesTriggerShapes(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_COM_NotIncludesTriggerShapes as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Material_NoEffectIfNoColliderShape(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_NoEffectIfNoColliderShape as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Collider_TriggerPassThrough(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_TriggerPassThrough as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_SetGravityWorks(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_SetGravityWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','Material_CharacterController.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_Material_CharacterController(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_CharacterController as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Material_EmptyLibraryUsesDefault(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_EmptyLibraryUsesDefault as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_NoQuiverOnHighLinearDampingForce(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_NoQuiverOnHighLinearDampingForce as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_RigidBody_ComputeInertiaWorks(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_ComputeInertiaWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ScriptCanvas_PostPhysicsUpdate(self, request, workspace, editor, launcher_platform):
from .tests.script_canvas import ScriptCanvas_PostPhysicsUpdate as test_module
# Fixme: unexpected_lines = ["Assert"] + test_module.Lines.unexpected
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','Collider_NoneCollisionGroupSameLayerNotCollide.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_Collider_NoneCollisionGroupSameLayerNotCollide(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_NoneCollisionGroupSameLayerNotCollide as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','Collider_SameCollisionGroupSameCustomLayerCollide.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_Collider_SameCollisionGroupSameCustomLayerCollide(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_SameCollisionGroupSameCustomLayerCollide as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxdefaultsceneconfiguration.setreg','ScriptCanvas_PostUpdateEvent.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_ScriptCanvas_PostUpdateEvent(self, request, workspace, editor, launcher_platform):
from .tests.script_canvas import ScriptCanvas_PostUpdateEvent as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','Material_Restitution.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_Material_Restitution(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_Restitution as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxdefaultsceneconfiguration.setreg', 'ScriptCanvas_PreUpdateEvent.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_ScriptCanvas_PreUpdateEvent(self, request, workspace, editor, launcher_platform):
from .tests.script_canvas import ScriptCanvas_PreUpdateEvent as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_PxMeshShapedForce(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_PxMeshShapedForce as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
# Marking the Test as expected to fail using the xfail decorator due to sporadic failure on Automated Review: SPEC-3146
# The test still runs, but a failure of the test doesn't result in the test run failing
@@ -361,176 +361,173 @@ class TestAutomation(TestAutomationBase):
@revert_physics_config
def test_RigidBody_MaxAngularVelocityWorks(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_MaxAngularVelocityWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Joints_HingeSoftLimitsConstrained(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_HingeSoftLimitsConstrained as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Joints_BallSoftLimitsConstrained(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_BallSoftLimitsConstrained as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Joints_BallLeadFollowerCollide(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_BallLeadFollowerCollide as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','Collider_AddingNewGroupWorks.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_Collider_AddingNewGroupWorks(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_AddingNewGroupWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ShapeCollider_InactiveWhenNoShapeComponent(self, request, workspace, editor, launcher_platform):
from .tests.shape_collider import ShapeCollider_InactiveWhenNoShapeComponent as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Collider_CheckDefaultShapeSettingIsPxMesh(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_CheckDefaultShapeSettingIsPxMesh as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor(self, request, workspace, editor, launcher_platform):
from .tests.shape_collider import ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Collider_SphereShapeEditing(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_SphereShapeEditing as test_module
self._run_test(request, workspace, editor, test_module,
extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"])
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
def test_Collider_BoxShapeEditing(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_BoxShapeEditing as test_module
self._run_test(request, workspace, editor, test_module,
extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"])
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
def test_Collider_CapsuleShapeEditing(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_CapsuleShapeEditing as test_module
self._run_test(request, workspace, editor, test_module,
extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"])
self._run_test(request, workspace, editor, test_module)
def test_ForceRegion_WithNonTriggerColliderWarning(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_WithNonTriggerColliderWarning as test_module
# Fixme: expected_lines = ["[Warning] (PhysX Force Region) - Please ensure collider component marked as trigger exists in entity"]
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ForceRegion_WorldSpaceForceOnRigidBodies(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_WorldSpaceForceOnRigidBodies as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ForceRegion_PointForceOnRigidBodies(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_PointForceOnRigidBodies as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ForceRegion_SphereShapedForce(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_SphereShapedForce as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ForceRegion_RotationalOffset(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_RotationalOffset as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Material_LibraryClearingAssignsDefault(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_LibraryClearingAssignsDefault as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Collider_AddColliderComponent(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_AddColliderComponent as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(
reason="This will fail due to this issue ATOM-15487.")
def test_Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Collider_MultipleSurfaceSlots(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_MultipleSurfaceSlots as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_RigidBody_EnablingGravityWorksPoC(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_EnablingGravityWorksPoC as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','Collider_CollisionGroupsWorkflow.setreg_override',
'AutomatedTesting/Registry', search_subdirs=True)
def test_Collider_CollisionGroupsWorkflow(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_CollisionGroupsWorkflow as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Collider_ColliderRotationOffset(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_ColliderRotationOffset as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ForceRegion_ParentChildForcesCombineForces(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_ParentChildForcesCombineForces as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_ShapeCollider_CanBeAddedWitNoWarnings(self, request, workspace, editor, launcher_platform):
from .tests.shape_collider import ShapeCollider_CanBeAddedWitNoWarnings as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Physics_UndoRedoWorksOnEntityWithPhysComponents(self, request, workspace, editor, launcher_platform):
from .tests import Physics_UndoRedoWorksOnEntityWithPhysComponents as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Joints_Fixed2BodiesConstrained(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_Fixed2BodiesConstrained as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Joints_Hinge2BodiesConstrained(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_Hinge2BodiesConstrained as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Joints_Ball2BodiesConstrained(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_Ball2BodiesConstrained as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Joints_FixedBreakable(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_FixedBreakable as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Joints_HingeBreakable(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_HingeBreakable as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Joints_BallBreakable(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_BallBreakable as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Joints_HingeNoLimitsConstrained(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_HingeNoLimitsConstrained as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Joints_BallNoLimitsConstrained(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_BallNoLimitsConstrained as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Joints_GlobalFrameConstrained(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_GlobalFrameConstrained as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@revert_physics_config
def test_Material_DefaultLibraryUpdatedAcrossLevels(self, request, workspace, editor, launcher_platform):
@@ -540,7 +537,7 @@ class TestAutomation(TestAutomationBase):
search_subdirs=True)
def levels_before(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_DefaultLibraryUpdatedAcrossLevels_before as test_module_0
self._run_test(request, workspace, editor, test_module_0)
self._run_test(request, workspace, editor, test_module_0, enable_prefab_system=False)
# File override replaces the previous physxconfiguration file with another where the only difference is the default material library
@fm.file_override("physxsystemconfiguration.setreg",
@@ -549,7 +546,7 @@ class TestAutomation(TestAutomationBase):
search_subdirs=True)
def levels_after(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_DefaultLibraryUpdatedAcrossLevels_after as test_module_1
self._run_test(request, workspace, editor, test_module_1)
self._run_test(request, workspace, editor, test_module_1, enable_prefab_system=False)
levels_before(self, request, workspace, editor, launcher_platform)
levels_after(self, request, workspace, editor, launcher_platform)
@@ -32,7 +32,7 @@ class TestAutomation(TestAutomationBase):
def test_ScriptCanvas_GetCollisionNameReturnsName(self, request, workspace, editor, launcher_platform):
from .tests.script_canvas import ScriptCanvas_GetCollisionNameReturnsName as test_module
# Fixme: expected_lines=["Layer Name: Right"]
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
## Seems to be flaky, need to investigate
def test_ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer(self, request, workspace, editor, launcher_platform):
@@ -42,4 +42,4 @@ class TestAutomation(TestAutomationBase):
# Fixme: for group in collision_groups:
# Fixme: unexpected_lines.append(f"GroupName: {group}")
# Fixme: expected_lines=["GroupName: "]
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@@ -30,11 +30,11 @@ class TestUtils(TestAutomationBase):
expected_lines = []
unexpected_lines = ["Assert"]
self._run_test(request, workspace, editor, physmaterial_editor_test_module, expected_lines, unexpected_lines)
self._run_test(request, workspace, editor, physmaterial_editor_test_module, expected_lines, unexpected_lines, enable_prefab_system=False)
def test_UtilTest_Tracer_PicksErrorsAndWarnings(self, request, workspace, launcher_platform, editor):
from .utils import UtilTest_Tracer_PicksErrorsAndWarnings as testcase_module
self._run_test(request, workspace, editor, testcase_module, [], [])
self._run_test(request, workspace, editor, testcase_module, [], [], enable_prefab_system=False)
def test_FileManagement_FindingFiles(self, workspace, launcher_platform):
"""
@@ -263,4 +263,4 @@ class TestUtils(TestAutomationBase):
expected_lines = []
unexpected_lines = ["Assert"]
self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines)
self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines, enable_prefab_system=False)
@@ -23,7 +23,6 @@ class TestAutomation(TestAutomationBase):
def _run_prefab_test(self, request, workspace, editor, test_module, batch_mode=True, autotest_mode=True):
self._run_test(request, workspace, editor, test_module,
extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"],
batch_mode=batch_mode,
autotest_mode=autotest_mode)
@@ -20,6 +20,8 @@ from ly_test_tools.o3de.editor_test import EditorTestSuite, EditorSharedTest
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(EditorTestSuite):
enable_prefab_system = False
class test_AxisAlignedBoxShape_ConfigurationWorks(EditorSharedTest):
from .EditorScripts import TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges as test_module
@@ -24,12 +24,12 @@ from base import TestAutomationBase
class TestAutomation(TestAutomationBase):
def test_WhiteBox_AddComponentToEntity(self, request, workspace, editor, launcher_platform):
from .tests import WhiteBox_AddComponentToEntity as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_WhiteBox_SetDefaultShape(self, request, workspace, editor, launcher_platform):
from .tests import WhiteBox_SetDefaultShape as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_WhiteBox_SetInvisible(self, request, workspace, editor, launcher_platform):
from .tests import WhiteBox_SetInvisible as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@@ -52,7 +52,7 @@ class TestAutomationBase:
cls._kill_ly_processes()
def _run_test(self, request, workspace, editor, testcase_module, extra_cmdline_args=[], batch_mode=True,
autotest_mode=True, use_null_renderer=True):
autotest_mode=True, use_null_renderer=True, enable_prefab_system=True):
test_starttime = time.time()
self.logger = logging.getLogger(__name__)
errors = []
@@ -97,6 +97,11 @@ class TestAutomationBase:
pycmd += ["-BatchMode"]
if autotest_mode:
pycmd += ["-autotest_mode"]
if enable_prefab_system:
pycmd += ["--regset=/Amazon/Preferences/EnablePrefabSystem=true"]
else:
pycmd += ["--regset=/Amazon/Preferences/EnablePrefabSystem=false"]
pycmd += extra_cmdline_args
editor.args.extend(pycmd) # args are added to the WinLauncher start command
editor.start(backupFiles = False, launch_ap = False)
@@ -33,14 +33,14 @@ class TestAutomation(TestAutomationBase):
def test_BasicEditorWorkflows_LevelEntityComponentCRUD(self, request, workspace, editor, launcher_platform,
remove_test_level):
from .EditorScripts import BasicEditorWorkflows_LevelEntityComponentCRUD as test_module
self._run_test(request, workspace, editor, test_module, batch_mode=False, autotest_mode=False)
self._run_test(request, workspace, editor, test_module, batch_mode=False, autotest_mode=False, enable_prefab_system=False)
@pytest.mark.REQUIRES_gpu
def test_BasicEditorWorkflows_GPU_LevelEntityComponentCRUD(self, request, workspace, editor, launcher_platform,
remove_test_level):
from .EditorScripts import BasicEditorWorkflows_LevelEntityComponentCRUD as test_module
self._run_test(request, workspace, editor, test_module, batch_mode=False, autotest_mode=False,
use_null_renderer=False)
use_null_renderer=False, enable_prefab_system=False)
def test_EntityOutlienr_EntityOrdering(self, request, workspace, editor, launcher_platform):
from .EditorScripts import EntityOutliner_EntityOrdering as test_module
@@ -51,5 +51,4 @@ class TestAutomation(TestAutomationBase):
test_module,
batch_mode=False,
autotest_mode=True,
extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"]
)
@@ -21,6 +21,8 @@ class TestAutomationNoAutoTestMode(EditorTestSuite):
# Disable -autotest_mode and -BatchMode. Tests cannot run in -BatchMode due to UI interactions, and these tests
# interact with modal dialogs
global_extra_cmdline_args = []
enable_prefab_system = False
class test_BasicEditorWorkflows_LevelEntityComponentCRUD(EditorSingleTest):
# Custom teardown to remove slice asset created during test
@@ -56,6 +58,8 @@ class TestAutomationAutoTestMode(EditorTestSuite):
# Enable only -autotest_mode for these tests. Tests cannot run in -BatchMode due to UI interactions
global_extra_cmdline_args = ["-autotest_mode"]
enable_prefab_system = False
class test_AssetBrowser_TreeNavigation(EditorSharedTest):
from .EditorScripts import AssetBrowser_TreeNavigation as test_module
@@ -32,29 +32,29 @@ class TestAutomation(TestAutomationBase):
def test_AssetBrowser_TreeNavigation(self, request, workspace, editor, launcher_platform):
from .EditorScripts import AssetBrowser_TreeNavigation as test_module
self._run_test(request, workspace, editor, test_module, batch_mode=False)
self._run_test(request, workspace, editor, test_module, batch_mode=False, enable_prefab_system=False)
def test_AssetBrowser_SearchFiltering(self, request, workspace, editor, launcher_platform):
from .EditorScripts import AssetBrowser_SearchFiltering as test_module
self._run_test(request, workspace, editor, test_module, batch_mode=False)
self._run_test(request, workspace, editor, test_module, batch_mode=False, enable_prefab_system=False)
def test_AssetPicker_UI_UX(self, request, workspace, editor, launcher_platform):
from .EditorScripts import AssetPicker_UI_UX as test_module
self._run_test(request, workspace, editor, test_module, autotest_mode=False, batch_mode=False)
self._run_test(request, workspace, editor, test_module, autotest_mode=False, batch_mode=False, enable_prefab_system=False)
def test_ComponentCRUD_Add_Delete_Components(self, request, workspace, editor, launcher_platform):
from .EditorScripts import ComponentCRUD_Add_Delete_Components as test_module
self._run_test(request, workspace, editor, test_module, batch_mode=False)
self._run_test(request, workspace, editor, test_module, batch_mode=False, enable_prefab_system=False)
def test_InputBindings_Add_Remove_Input_Events(self, request, workspace, editor, launcher_platform):
from .EditorScripts import InputBindings_Add_Remove_Input_Events as test_module
self._run_test(request, workspace, editor, test_module, batch_mode=False, autotest_mode=False)
self._run_test(request, workspace, editor, test_module, batch_mode=False, autotest_mode=False, enable_prefab_system=False)
def test_Menus_ViewMenuOptions_Work(self, request, workspace, editor, launcher_platform):
from .EditorScripts import Menus_ViewMenuOptions as test_module
self._run_test(request, workspace, editor, test_module, batch_mode=False)
self._run_test(request, workspace, editor, test_module, batch_mode=False, enable_prefab_system=False)
@pytest.mark.skip(reason="Times out due to dialogs failing to dismiss: LYN-4208")
def test_Menus_FileMenuOptions_Work(self, request, workspace, editor, launcher_platform):
from .EditorScripts import Menus_FileMenuOptions as test_module
self._run_test(request, workspace, editor, test_module, batch_mode=False)
self._run_test(request, workspace, editor, test_module, batch_mode=False, enable_prefab_system=False)
@@ -20,8 +20,8 @@ class TestAutomation(TestAutomationBase):
def test_Menus_EditMenuOptions_Work(self, request, workspace, editor, launcher_platform):
from .EditorScripts import Menus_EditMenuOptions as test_module
self._run_test(request, workspace, editor, test_module, batch_mode=False)
self._run_test(request, workspace, editor, test_module, batch_mode=False, enable_prefab_system=False)
def test_Docking_BasicDockedTools(self, request, workspace, editor, launcher_platform):
from .EditorScripts import Docking_BasicDockedTools as test_module
self._run_test(request, workspace, editor, test_module, batch_mode=False)
self._run_test(request, workspace, editor, test_module, batch_mode=False, enable_prefab_system=False)
@@ -19,6 +19,8 @@ class TestAutomationAutoTestMode(EditorTestSuite):
# Enable only -autotest_mode for these tests. Tests cannot run in -BatchMode due to UI interactions
global_extra_cmdline_args = ["-autotest_mode"]
enable_prefab_system = False
class test_Docking_BasicDockedTools(EditorSharedTest):
from .EditorScripts import Docking_BasicDockedTools as test_module
@@ -20,8 +20,8 @@ class TestAutomation(TestAutomationBase):
def test_DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks(self, request, workspace, editor, launcher_platform):
from .EditorScripts import DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_EmptyInstanceSpawner_EmptySpawnerWorks(self, request, workspace, editor, launcher_platform):
from .EditorScripts import EmptyInstanceSpawner_EmptySpawnerWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@@ -18,6 +18,8 @@ from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, E
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(EditorTestSuite):
enable_prefab_system = False
class test_DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks(EditorParallelTest):
from .EditorScripts import DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks as test_module
@@ -52,158 +52,158 @@ class TestAutomation(TestAutomationBase):
def test_AltitudeFilter_ComponentAndOverrides_InstancesPlantAtSpecifiedAltitude(self, request, workspace, editor, launcher_platform):
from .EditorScripts import AltitudeFilter_ComponentAndOverrides_InstancesPlantAtSpecifiedAltitude as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_AltitudeFilter_ShapeSample_InstancesPlantAtSpecifiedAltitude(self, request, workspace, editor, launcher_platform):
from .EditorScripts import AltitudeFilter_ShapeSample_InstancesPlantAtSpecifiedAltitude as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_AltitudeFilter_FilterStageToggle(self, request, workspace, editor, launcher_platform):
from .EditorScripts import AltitudeFilter_FilterStageToggle as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_SpawnerSlices_SliceCreationAndVisibilityToggleWorks(self, request, workspace, editor, remove_test_slice, launcher_platform):
from .EditorScripts import SpawnerSlices_SliceCreationAndVisibilityToggleWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_AssetListCombiner_CombinedDescriptorsExpressInConfiguredArea(self, request, workspace, editor, launcher_platform):
from .EditorScripts import AssetListCombiner_CombinedDescriptorsExpressInConfiguredArea as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_AssetWeightSelector_InstancesExpressBasedOnWeight(self, request, workspace, editor, launcher_platform):
from .EditorScripts import AssetWeightSelector_InstancesExpressBasedOnWeight as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/4155")
def test_DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius(self, request, workspace, editor, launcher_platform):
from .EditorScripts import DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/4155")
def test_DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius(self, request, workspace, editor, launcher_platform):
from .EditorScripts import DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_SurfaceDataRefreshes_RemainsStable(self, request, workspace, editor, launcher_platform):
from .EditorScripts import SurfaceDataRefreshes_RemainsStable as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_VegetationInstances_DespawnWhenOutOfRange(self, request, workspace, editor, launcher_platform):
from .EditorScripts import VegetationInstances_DespawnWhenOutOfRange as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_InstanceSpawnerPriority_LayerAndSubPriority_HigherValuesPlantOverLower(self, request, workspace, editor, launcher_platform):
from .EditorScripts import InstanceSpawnerPriority_LayerAndSubPriority as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LayerBlocker_InstancesBlockedInConfiguredArea(self, request, workspace, editor, launcher_platform):
from .EditorScripts import LayerBlocker_InstancesBlockedInConfiguredArea as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LayerSpawner_InheritBehaviorFlag(self, request, workspace, editor, launcher_platform):
from .EditorScripts import LayerSpawner_InheritBehaviorFlag as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LayerSpawner_InstancesPlantInAllSupportedShapes(self, request, workspace, editor, launcher_platform):
from .EditorScripts import LayerSpawner_InstancesPlantInAllSupportedShapes as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LayerSpawner_FilterStageToggle(self, request, workspace, editor, launcher_platform):
from .EditorScripts import LayerSpawner_FilterStageToggle as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/2038")
def test_LayerSpawner_InstancesRefreshUsingCorrectViewportCamera(self, request, workspace, editor, launcher_platform):
from .EditorScripts import LayerSpawner_InstancesRefreshUsingCorrectViewportCamera as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_MeshBlocker_InstancesBlockedByMesh(self, request, workspace, editor, launcher_platform):
from .EditorScripts import MeshBlocker_InstancesBlockedByMesh as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_MeshBlocker_InstancesBlockedByMeshHeightTuning(self, request, workspace, editor, launcher_platform):
from .EditorScripts import MeshBlocker_InstancesBlockedByMeshHeightTuning as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_MeshSurfaceTagEmitter_DependentOnMeshComponent(self, request, workspace, editor, launcher_platform):
from .EditorScripts import MeshSurfaceTagEmitter_DependentOnMeshComponent as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully(self, request, workspace, editor, launcher_platform):
from .EditorScripts import MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_PhysXColliderSurfaceTagEmitter_E2E_Editor(self, request, workspace, editor, launcher_platform):
from .EditorScripts import PhysXColliderSurfaceTagEmitter_E2E_Editor as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_PositionModifier_ComponentAndOverrides_InstancesPlantAtSpecifiedOffsets(self, request, workspace, editor, launcher_platform):
from .EditorScripts import PositionModifier_ComponentAndOverrides_InstancesPlantAtSpecifiedOffsets as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_PositionModifier_AutoSnapToSurfaceWorks(self, request, workspace, editor, launcher_platform):
from .EditorScripts import PositionModifier_AutoSnapToSurfaceWorks as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_RotationModifier_InstancesRotateWithinRange(self, request, workspace, editor, launcher_platform):
from .EditorScripts import RotationModifier_InstancesRotateWithinRange as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_RotationModifierOverrides_InstancesRotateWithinRange(self, request, workspace, editor, launcher_platform):
from .EditorScripts import RotationModifierOverrides_InstancesRotateWithinRange as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ScaleModifier_InstancesProperlyScale(self, request, workspace, editor, launcher_platform):
from .EditorScripts import ScaleModifier_InstancesProperlyScale as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ScaleModifierOverrides_InstancesProperlyScale(self, request, workspace, editor, launcher_platform):
from .EditorScripts import ScaleModifierOverrides_InstancesProperlyScale as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ShapeIntersectionFilter_InstancesPlantInAssignedShape(self, request, workspace, editor, launcher_platform):
from .EditorScripts import ShapeIntersectionFilter_InstancesPlantInAssignedShape as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ShapeIntersectionFilter_FilterStageToggle(self, request, workspace, editor, launcher_platform):
from .EditorScripts import ShapeIntersectionFilter_FilterStageToggle as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_SlopeAlignmentModifier_InstanceSurfaceAlignment(self, request, workspace, editor, launcher_platform):
from .EditorScripts import SlopeAlignmentModifier_InstanceSurfaceAlignment as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_SlopeAlignmentModifierOverrides_InstanceSurfaceAlignment(self, request, workspace, editor, launcher_platform):
from .EditorScripts import SlopeAlignmentModifierOverrides_InstanceSurfaceAlignment as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_SurfaceMaskFilter_BasicSurfaceTagCreation(self, request, workspace, editor, launcher_platform):
from .EditorScripts import SurfaceMaskFilter_BasicSurfaceTagCreation as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_SurfaceMaskFilter_ExclusiveSurfaceTags_Function(self, request, workspace, editor, launcher_platform):
from .EditorScripts import SurfaceMaskFilter_ExclusionList as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_SurfaceMaskFilter_InclusiveSurfaceTags_Function(self, request, workspace, editor, launcher_platform):
from .EditorScripts import SurfaceMaskFilter_InclusionList as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_SurfaceMaskFilterOverrides_MultipleDescriptorOverridesPlantAsExpected(self, request, workspace, editor, launcher_platform):
from .EditorScripts import SurfaceMaskFilterOverrides_MultipleDescriptorOverridesPlantAsExpected as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_SystemSettings_SectorPointDensity(self, request, workspace, editor, launcher_platform):
from .EditorScripts import SystemSettings_SectorPointDensity as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_SystemSettings_SectorSize(self, request, workspace, editor, launcher_platform):
from .EditorScripts import SystemSettings_SectorSize as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_SlopeFilter_ComponentAndOverrides_InstancesPlantOnValidSlopes(self, request, workspace, editor, launcher_platform):
from .EditorScripts import SlopeFilter_ComponentAndOverrides_InstancesPlantOnValidSlope as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.SUITE_periodic
@@ -219,7 +219,7 @@ class TestAutomationE2E(TestAutomationBase):
file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True)
from .EditorScripts import DynamicSliceInstanceSpawner_Embedded_E2E as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.parametrize("launcher_platform", ['windows'])
def test_DynamicSliceInstanceSpawner_Embedded_E2E_Launcher(self, workspace, launcher, level,
@@ -240,7 +240,7 @@ class TestAutomationE2E(TestAutomationBase):
file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True)
from .EditorScripts import DynamicSliceInstanceSpawner_External_E2E as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.parametrize("launcher_platform", ['windows'])
def test_DynamicSliceInstanceSpawner_External_E2E_Launcher(self, workspace, launcher, level,
@@ -261,7 +261,7 @@ class TestAutomationE2E(TestAutomationBase):
file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True)
from .EditorScripts import LayerBlender_E2E_Editor as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.parametrize("launcher_platform", ['windows'])
@pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/4170")
@@ -17,7 +17,7 @@ from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, E
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(EditorTestSuite):
global_extra_cmdline_args = ["-BatchMode", "-autotest_mode", "--regset=/Amazon/Preferences/EnablePrefabSystem=true"]
global_extra_cmdline_args = ["-BatchMode", "-autotest_mode"]
class test_DynVegUtils_TempPrefabCreationWorks(EditorSharedTest):
from .EditorScripts import DynVegUtils_TempPrefabCreationWorks as test_module
@@ -20,52 +20,52 @@ class TestAutomation(TestAutomationBase):
def test_GradientGenerators_Incompatibilities(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientGenerators_Incompatibilities as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_GradientModifiers_Incompatibilities(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientModifiers_Incompatibilities as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_GradientPreviewSettings_DefaultPinnedEntityIsSelf(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientPreviewSettings_DefaultPinnedEntityIsSelf as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_GradientSampling_GradientReferencesAddRemoveSuccessfully(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientSampling_GradientReferencesAddRemoveSuccessfully as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_GradientSurfaceTagEmitter_ComponentDependencies(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientSurfaceTagEmitter_ComponentDependencies as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_GradientTransform_RequiresShape(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientTransform_RequiresShape as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_GradientTransform_ComponentIncompatibleWithSpawners(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientTransform_ComponentIncompatibleWithSpawners as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_GradientTransform_ComponentIncompatibleWithExpectedGradients(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientTransform_ComponentIncompatibleWithExpectedGradients as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ImageGradient_RequiresShape(self, request, workspace, editor, launcher_platform):
from .EditorScripts import ImageGradient_RequiresShape as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ImageGradient_ProcessedImageAssignedSuccessfully(self, request, workspace, editor, launcher_platform):
from .EditorScripts import ImageGradient_ProcessedImageAssignedSuccessfully as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@@ -15,6 +15,8 @@ from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, E
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(EditorTestSuite):
enable_prefab_system = False
class test_GradientGenerators_Incompatibilities(EditorSharedTest):
from .EditorScripts import GradientGenerators_Incompatibilities as test_module
@@ -22,8 +22,8 @@ class TestAutomation(TestAutomationBase):
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)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_LandscapeCanvas_GradientMixer_NodeConstruction(self, request, workspace, editor, launcher_platform):
from .EditorScripts import GradientMixer_NodeConstruction as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@@ -18,6 +18,8 @@ from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, E
@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
@@ -33,89 +33,89 @@ 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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@@ -27,15 +27,15 @@ TEST_DIRECTORY = os.path.dirname(__file__)
class TestAutomation(TestAutomationBase):
def test_Pane_HappyPath_OpenCloseSuccessfully(self, request, workspace, editor, launcher_platform):
from . import Pane_HappyPath_OpenCloseSuccessfully as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Pane_HappyPath_DocksProperly(self, request, workspace, editor, launcher_platform):
from . import Pane_HappyPath_DocksProperly as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Pane_HappyPath_ResizesProperly(self, request, workspace, editor, launcher_platform):
from . import Pane_HappyPath_ResizesProperly as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@@ -45,7 +45,7 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptCanvas_TwoComponents_InteractSuccessfully as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@@ -55,15 +55,15 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptCanvas_ChangingAssets_ComponentStable as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Graph_HappyPath_ZoomInZoomOut(self, request, workspace, editor, launcher_platform):
from . import Graph_HappyPath_ZoomInZoomOut as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_NodePalette_HappyPath_CanSelectNode(self, request, workspace, editor, launcher_platform):
from . import NodePalette_HappyPath_CanSelectNode as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@@ -73,11 +73,11 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_NodePalette_HappyPath_ClearSelection(self, request, workspace, editor, launcher_platform, project):
from . import NodePalette_HappyPath_ClearSelection as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@@ -87,7 +87,7 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptCanvas_TwoEntities_UseSimultaneously as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ScriptEvent_HappyPath_CreatedWithoutError(self, request, workspace, editor, launcher_platform, project):
def teardown():
@@ -99,19 +99,19 @@ class TestAutomation(TestAutomationBase):
[os.path.join(workspace.paths.project(), "ScriptCanvas", "test_file.scriptevent")], True, True
)
from . import ScriptEvent_HappyPath_CreatedWithoutError as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ScriptCanvasTools_Toggle_OpenCloseSuccess(self, request, workspace, editor, launcher_platform):
from . import ScriptCanvasTools_Toggle_OpenCloseSuccess as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_NodeInspector_HappyPath_VariableRenames(self, request, workspace, editor, launcher_platform, project):
from . import NodeInspector_HappyPath_VariableRenames as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Debugger_HappyPath_TargetMultipleGraphs(self, request, workspace, editor, launcher_platform, project):
from . import Debugger_HappyPath_TargetMultipleGraphs as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.parametrize("level", ["tmp_level"])
def test_Debugger_HappyPath_TargetMultipleEntities(self, request, workspace, editor, launcher_platform, project, level):
@@ -120,16 +120,16 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import Debugger_HappyPath_TargetMultipleEntities as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
def test_EditMenu_Default_UndoRedo(self, request, workspace, editor, launcher_platform, project):
from . import EditMenu_Default_UndoRedo as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Pane_Undocked_ClosesSuccessfully(self, request, workspace, editor, launcher_platform):
from . import Pane_Undocked_ClosesSuccessfully as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.parametrize("level", ["tmp_level"])
def test_Entity_HappyPath_AddScriptCanvasComponent(self, request, workspace, editor, launcher_platform, project, level):
@@ -138,11 +138,11 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import Entity_HappyPath_AddScriptCanvasComponent as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Pane_Default_RetainOnSCRestart(self, request, workspace, editor, launcher_platform):
from . import Pane_Default_RetainOnSCRestart as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@@ -152,7 +152,7 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptEvents_HappyPath_SendReceiveAcrossMultiple as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@@ -162,7 +162,7 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptEvents_Default_SendReceiveSuccessfully as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@@ -172,24 +172,24 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptEvents_ReturnSetType_Successfully as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_NodeCategory_ExpandOnClick(self, request, workspace, editor, launcher_platform):
from . import NodeCategory_ExpandOnClick as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_NodePalette_SearchText_Deletion(self, request, workspace, editor, launcher_platform):
from . import NodePalette_SearchText_Deletion as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
def test_VariableManager_UnpinVariableType_Works(self, request, workspace, editor, launcher_platform):
from . import VariableManager_UnpinVariableType_Works as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_Node_HappyPath_DuplicateNode(self, request, workspace, editor, launcher_platform):
from . import Node_HappyPath_DuplicateNode as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
def test_ScriptEvent_AddRemoveParameter_ActionsSuccessful(self, request, workspace, editor, launcher_platform):
def teardown():
@@ -201,7 +201,7 @@ class TestAutomation(TestAutomationBase):
[os.path.join(workspace.paths.project(), "ScriptCanvas", "test_file.scriptevent")], True, True
)
from . import ScriptEvent_AddRemoveParameter_ActionsSuccessful as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
# NOTE: We had to use hydra_test_utils.py, as TestAutomationBase run_test method
# fails because of pyside_utils import
@@ -220,7 +220,14 @@ class TestScriptCanvasTests(object):
"File->Open action working as expected: True",
]
hydra.launch_and_validate_results(
request, TEST_DIRECTORY, editor, "FileMenu_Default_NewAndOpen.py", expected_lines, auto_test_mode=False, timeout=60,
request,
TEST_DIRECTORY,
editor,
"FileMenu_Default_NewAndOpen.py",
expected_lines,
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@@ -239,6 +246,7 @@ class TestScriptCanvasTests(object):
expected_lines,
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
def test_GraphClose_Default_SavePrompt(self, request, editor, launcher_platform):
@@ -255,6 +263,7 @@ class TestScriptCanvasTests(object):
expected_lines,
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
def test_VariableManager_Default_CreateDeleteVars(self, request, editor, launcher_platform):
@@ -269,6 +278,7 @@ class TestScriptCanvasTests(object):
expected_lines,
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
@pytest.mark.parametrize(
@@ -304,6 +314,7 @@ class TestScriptCanvasTests(object):
cfg_args=[config.get('cfg_args')],
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@@ -332,6 +343,7 @@ class TestScriptCanvasTests(object):
expected_lines,
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@@ -359,5 +371,6 @@ class TestScriptCanvasTests(object):
expected_lines,
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
@@ -23,4 +23,4 @@ class TestAutomation(TestAutomationBase):
def test_Opening_Closing_Pane(self, request, workspace, editor, launcher_platform):
from . import Opening_Closing_Pane as test_module
self._run_test(request, workspace, editor, test_module)
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@@ -31,4 +31,4 @@ class TestAutomation(TestAutomationBase):
from . import Editor_NewExistingLevels_Works as test_module
self._run_test(request, workspace, editor, test_module, extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=false"])
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@@ -1,7 +1,7 @@
{
"Amazon": {
"Preferences": {
"EnablePrefabSystem": false
"EnablePrefabSystem": true
}
}
}
@@ -27,7 +27,6 @@
#include <AzToolsFramework/Manipulators/ScaleManipulators.h>
#include <AzToolsFramework/Manipulators/TranslationManipulators.h>
#include <AzToolsFramework/Maths/TransformUtils.h>
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
#include <AzToolsFramework/ToolsComponents/EditorLockComponentBus.h>
@@ -893,37 +892,34 @@ namespace AzToolsFramework
prevModifiers = action.m_modifiers;
}
static void HandleAccents(
const bool hasSelectedEntities,
const AZ::EntityId entityIdUnderCursor,
const bool ctrlHeld,
AZ::EntityId& hoveredEntityId,
void HandleAccents(
const AZ::EntityId currentEntityIdUnderCursor,
AZ::EntityId& hoveredEntityIdUnderCursor,
const HandleAccentsContext& handleAccentsContext,
const ViewportInteraction::MouseButtons mouseButtons,
const bool usingBoxSelect)
const AZStd::function<void(AZ::EntityId, bool)>& setEntityAccentedFn)
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
const bool invalidMouseButtonHeld = mouseButtons.Middle() || mouseButtons.Right();
const bool hasSelectedEntities = handleAccentsContext.m_hasSelectedEntities;
const bool ctrlHeld = handleAccentsContext.m_ctrlHeld;
const bool boxSelect = handleAccentsContext.m_usingBoxSelect;
const bool stickySelect = handleAccentsContext.m_usingStickySelect;
const bool canSelect = stickySelect ? !hasSelectedEntities || ctrlHeld : true;
if ((hoveredEntityId.IsValid() && hoveredEntityId != entityIdUnderCursor) ||
(hasSelectedEntities && !ctrlHeld && hoveredEntityId.IsValid()) || invalidMouseButtonHeld)
const bool removePreviousAccent =
(currentEntityIdUnderCursor != hoveredEntityIdUnderCursor && hoveredEntityIdUnderCursor.IsValid()) || invalidMouseButtonHeld;
const bool addNextAccent = currentEntityIdUnderCursor.IsValid() && canSelect && !invalidMouseButtonHeld && !boxSelect;
if (removePreviousAccent)
{
if (hoveredEntityId.IsValid())
{
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetEntityHighlighted, hoveredEntityId, false);
hoveredEntityId.SetInvalid();
}
setEntityAccentedFn(hoveredEntityIdUnderCursor, false);
hoveredEntityIdUnderCursor.SetInvalid();
}
if (!invalidMouseButtonHeld && !usingBoxSelect && (!hasSelectedEntities || ctrlHeld))
if (addNextAccent)
{
if (entityIdUnderCursor.IsValid())
{
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetEntityHighlighted, entityIdUnderCursor, true);
hoveredEntityId = entityIdUnderCursor;
}
setEntityAccentedFn(currentEntityIdUnderCursor, true);
hoveredEntityIdUnderCursor = currentEntityIdUnderCursor;
}
}
@@ -1781,7 +1777,7 @@ namespace AzToolsFramework
const AzFramework::CameraState cameraState = GetCameraState(viewportId);
const auto cursorEntityIdQuery = m_editorHelpers->FindEntityIdUnderCursor(cameraState, mouseInteraction);
m_cachedEntityIdUnderCursor = cursorEntityIdQuery.ContainerAncestorEntityId();
m_currentEntityIdUnderCursor = cursorEntityIdQuery.ContainerAncestorEntityId();
const auto selectClickEvent = ClickDetectorEventFromViewportInteraction(mouseInteraction);
m_cursorState.SetCurrentPosition(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
@@ -1802,7 +1798,7 @@ namespace AzToolsFramework
mouseInteraction.m_mouseInteraction,
AZ::Aabb::CreateFromMinMax(boxPosition - scaledSize, boxPosition + scaledSize)))
{
m_cachedEntityIdUnderCursor = entityId;
m_currentEntityIdUnderCursor = entityId;
}
}
}
@@ -1822,7 +1818,7 @@ namespace AzToolsFramework
return true;
}
const AZ::EntityId entityIdUnderCursor = m_cachedEntityIdUnderCursor;
const AZ::EntityId entityIdUnderCursor = m_currentEntityIdUnderCursor;
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::DoubleClick &&
mouseInteraction.m_mouseInteraction.m_mouseButtons.Left())
@@ -3341,9 +3337,23 @@ namespace AzToolsFramework
m_cursorState.Update();
bool stickySelect = false;
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
stickySelect, viewportInfo.m_viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::StickySelectEnabled);
HandleAccentsContext handleAccentsContext;
handleAccentsContext.m_ctrlHeld = keyboardModifiers.Ctrl();
handleAccentsContext.m_hasSelectedEntities = !m_selectedEntityIds.empty();
handleAccentsContext.m_usingBoxSelect = m_boxSelect.Active();
handleAccentsContext.m_usingStickySelect = stickySelect;
HandleAccents(
!m_selectedEntityIds.empty(), m_cachedEntityIdUnderCursor, keyboardModifiers.Ctrl(), m_hoveredEntityId,
ViewportInteraction::BuildMouseButtons(QGuiApplication::mouseButtons()), m_boxSelect.Active());
m_currentEntityIdUnderCursor, m_hoveredEntityId, handleAccentsContext,
ViewportInteraction::BuildMouseButtons(QGuiApplication::mouseButtons()),
[](const AZ::EntityId entityId, bool highlighted)
{
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetEntityHighlighted, entityId, highlighted);
});
const ReferenceFrame referenceFrame = m_spaceCluster.m_spaceLock.value_or(ReferenceFrameFromModifiers(keyboardModifiers));
@@ -3589,7 +3599,8 @@ namespace AzToolsFramework
if (auto prefabFocusPublicInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabFocusPublicInterface>::Get())
{
AzFramework::EntityContextId editorEntityContextId = GetEntityContextId();
if (AZ::EntityId focusRoot = prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId); focusRoot.IsValid())
if (AZ::EntityId focusRoot = prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId);
focusRoot.IsValid())
{
m_selectedEntityIds.erase(focusRoot);
}
@@ -3721,7 +3732,6 @@ namespace AzToolsFramework
break;
case ViewportEditorMode::Focus:
{
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::RemoveViewportBorder);
}
@@ -317,7 +317,7 @@ namespace AzToolsFramework
void SetAllViewportUiVisible(bool visible);
AZ::EntityId m_hoveredEntityId; //!< What EntityId is the mouse currently hovering over (if any).
AZ::EntityId m_cachedEntityIdUnderCursor; //!< Store the EntityId on each mouse move for use in Display.
AZ::EntityId m_currentEntityIdUnderCursor; //!< Store the EntityId on each mouse move for use in Display.
AZ::EntityId m_editorCameraComponentEntityId; //!< The EditorCameraComponent EntityId if it is set.
EntityIdSet m_selectedEntityIds; //!< Represents the current entities in the selection.
@@ -357,6 +357,23 @@ namespace AzToolsFramework
bool m_viewportUiVisible = true; //!< Used to hide/show the viewport ui elements.
};
//! Bundles viewport state that impacts how accents are added/removed in HandleAccents.
struct HandleAccentsContext
{
bool m_hasSelectedEntities;
bool m_ctrlHeld;
bool m_usingBoxSelect;
bool m_usingStickySelect;
};
//! Updates whether accents (icon highlights) are added/removed for a given entity based on the cursor position.
void HandleAccents(
AZ::EntityId currentEntityIdUnderCursor,
AZ::EntityId& hoveredEntityIdUnderCursor,
const HandleAccentsContext& handleAccentsContext,
ViewportInteraction::MouseButtons mouseButtons,
const AZStd::function<void(AZ::EntityId, bool)>& setEntityAccentedFn);
//! The ETCS (EntityTransformComponentSelection) namespace contains functions and data used exclusively by
//! the EditorTransformComponentSelection type. Functions in this namespace are exposed to facilitate testing
//! and should not be used outside of EditorTransformComponentSelection or EditorTransformComponentSelectionTests.
@@ -15,10 +15,10 @@ namespace AzToolsFramework::EmbeddedPython
PythonLoader::PythonLoader()
{
constexpr char libPythonName[] = "libpython3.7m.so.1.0";
if (m_embeddedLibPythonHandle = dlopen(libPythonName, RTLD_NOW | RTLD_GLOBAL);
m_embeddedLibPythonHandle == nullptr)
m_embeddedLibPythonHandle = dlopen(libPythonName, RTLD_NOW | RTLD_GLOBAL);
if (m_embeddedLibPythonHandle == nullptr)
{
char* err = dlerror();
[[maybe_unused]] const char* err = dlerror();
AZ_Error("PythonLoader", false, "Failed to load %s with error: %s\n", libPythonName, err ? err : "Unknown Error");
}
}
@@ -2781,4 +2781,196 @@ namespace UnitTest
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
TEST(HandleAccents, CurrentValidEntityIdBecomesHoveredWithNoSelectionAndUnstickySelect)
{
namespace azvi = AzToolsFramework::ViewportInteraction;
const AZ::EntityId currentEntityId = AZ::EntityId(12345);
AZ::EntityId hoveredEntityEntityId;
AzToolsFramework::HandleAccentsContext handleAccentsContext;
handleAccentsContext.m_ctrlHeld = false;
handleAccentsContext.m_hasSelectedEntities = false;
handleAccentsContext.m_usingBoxSelect = false;
handleAccentsContext.m_usingStickySelect = false;
bool currentEntityIdAccentAdded = false;
AzToolsFramework::HandleAccents(
currentEntityId, hoveredEntityEntityId, handleAccentsContext, azvi::MouseButtonsFromButton(azvi::MouseButton::None),
[&currentEntityIdAccentAdded, currentEntityId](const AZ::EntityId entityId, const bool accent)
{
if (entityId == currentEntityId && accent)
{
currentEntityIdAccentAdded = true;
}
});
using ::testing::Eq;
using ::testing::IsTrue;
EXPECT_THAT(currentEntityId, Eq(hoveredEntityEntityId));
EXPECT_THAT(currentEntityIdAccentAdded, IsTrue());
}
TEST(HandleAccents, CurrentValidEntityIdBecomesHoveredWithSelectionAndUnstickySelect)
{
namespace azvi = AzToolsFramework::ViewportInteraction;
const AZ::EntityId currentEntityId = AZ::EntityId(12345);
AZ::EntityId hoveredEntityEntityId;
AzToolsFramework::HandleAccentsContext handleAccentsContext;
handleAccentsContext.m_ctrlHeld = false;
handleAccentsContext.m_hasSelectedEntities = true;
handleAccentsContext.m_usingBoxSelect = false;
handleAccentsContext.m_usingStickySelect = false;
bool currentEntityIdAccentAdded = false;
AzToolsFramework::HandleAccents(
currentEntityId, hoveredEntityEntityId, handleAccentsContext, azvi::MouseButtonsFromButton(azvi::MouseButton::None),
[&currentEntityIdAccentAdded, currentEntityId](const AZ::EntityId entityId, const bool accent)
{
if (entityId == currentEntityId && accent)
{
currentEntityIdAccentAdded = true;
}
});
using ::testing::Eq;
using ::testing::IsTrue;
EXPECT_THAT(currentEntityId, Eq(hoveredEntityEntityId));
EXPECT_THAT(currentEntityIdAccentAdded, IsTrue());
}
TEST(HandleAccents, CurrentValidEntityIdDoesNotBecomeHoveredWithSelectionUnstickySelectAndInvalidButton)
{
namespace azvi = AzToolsFramework::ViewportInteraction;
const AZ::EntityId currentEntityId = AZ::EntityId(12345);
AZ::EntityId hoveredEntityEntityId = AZ::EntityId(54321);
AzToolsFramework::HandleAccentsContext handleAccentsContext;
handleAccentsContext.m_ctrlHeld = false;
handleAccentsContext.m_hasSelectedEntities = false;
handleAccentsContext.m_usingBoxSelect = false;
handleAccentsContext.m_usingStickySelect = false;
bool hoveredEntityIdAccentRemoved = false;
AzToolsFramework::HandleAccents(
currentEntityId, hoveredEntityEntityId, handleAccentsContext, azvi::MouseButtonsFromButton(azvi::MouseButton::Middle),
[&hoveredEntityIdAccentRemoved, hoveredEntityEntityId](const AZ::EntityId entityId, const bool accent)
{
if (entityId == hoveredEntityEntityId && !accent)
{
hoveredEntityIdAccentRemoved = true;
}
});
using ::testing::Eq;
using ::testing::IsFalse;
using ::testing::IsTrue;
EXPECT_THAT(hoveredEntityEntityId.IsValid(), IsFalse());
EXPECT_THAT(hoveredEntityIdAccentRemoved, IsTrue());
}
TEST(HandleAccents, CurrentValidEntityIdDoesNotBecomeHoveredWithSelectionUnstickySelectAndDoingBoxSelect)
{
namespace azvi = AzToolsFramework::ViewportInteraction;
const AZ::EntityId currentEntityId = AZ::EntityId(12345);
AZ::EntityId hoveredEntityEntityId = AZ::EntityId(54321);
AzToolsFramework::HandleAccentsContext handleAccentsContext;
handleAccentsContext.m_ctrlHeld = false;
handleAccentsContext.m_hasSelectedEntities = false;
handleAccentsContext.m_usingBoxSelect = true;
handleAccentsContext.m_usingStickySelect = false;
bool hoveredEntityIdAccentRemoved = false;
AzToolsFramework::HandleAccents(
currentEntityId, hoveredEntityEntityId, handleAccentsContext, azvi::MouseButtonsFromButton(azvi::MouseButton::None),
[&hoveredEntityIdAccentRemoved, hoveredEntityEntityId](const AZ::EntityId entityId, const bool accent)
{
if (entityId == hoveredEntityEntityId && !accent)
{
hoveredEntityIdAccentRemoved = true;
}
});
using ::testing::Eq;
using ::testing::IsFalse;
using ::testing::IsTrue;
EXPECT_THAT(hoveredEntityEntityId.IsValid(), IsFalse());
EXPECT_THAT(hoveredEntityIdAccentRemoved, IsTrue());
}
// mimics the mouse moving off of hovered entity onto a new entity with sticky select enabled
TEST(HandleAccents, CurrentValidEntityIdDoesNotBecomeHoveredWithSelectionAndStickySelect)
{
namespace azvi = AzToolsFramework::ViewportInteraction;
const AZ::EntityId currentEntityId = AZ::EntityId(12345);
AZ::EntityId hoveredEntityEntityId = AZ::EntityId(54321);
AzToolsFramework::HandleAccentsContext handleAccentsContext;
handleAccentsContext.m_ctrlHeld = false;
handleAccentsContext.m_hasSelectedEntities = true;
handleAccentsContext.m_usingBoxSelect = false;
handleAccentsContext.m_usingStickySelect = true;
bool hoveredEntityIdAccentRemoved = false;
AzToolsFramework::HandleAccents(
currentEntityId, hoveredEntityEntityId, handleAccentsContext, azvi::MouseButtonsFromButton(azvi::MouseButton::None),
[&hoveredEntityIdAccentRemoved, hoveredEntityEntityId](const AZ::EntityId entityId, const bool accent)
{
if (entityId == hoveredEntityEntityId && !accent)
{
hoveredEntityIdAccentRemoved = true;
}
});
using ::testing::Eq;
using ::testing::IsFalse;
using ::testing::IsTrue;
EXPECT_THAT(hoveredEntityIdAccentRemoved, IsTrue());
EXPECT_THAT(hoveredEntityEntityId.IsValid(), IsFalse());
}
TEST(HandleAccents, CurrentValidEntityIdDoesBecomeHoveredWithSelectionAndStickySelectAndCtrl)
{
namespace azvi = AzToolsFramework::ViewportInteraction;
const AZ::EntityId currentEntityId = AZ::EntityId(12345);
AZ::EntityId hoveredEntityEntityId = AZ::EntityId(54321);
AzToolsFramework::HandleAccentsContext handleAccentsContext;
handleAccentsContext.m_ctrlHeld = true;
handleAccentsContext.m_hasSelectedEntities = true;
handleAccentsContext.m_usingBoxSelect = false;
handleAccentsContext.m_usingStickySelect = true;
bool currentEntityIdAccentAdded = false;
bool hoveredEntityIdAccentRemoved = false;
AzToolsFramework::HandleAccents(
currentEntityId, hoveredEntityEntityId, handleAccentsContext, azvi::MouseButtonsFromButton(azvi::MouseButton::None),
[&hoveredEntityIdAccentRemoved, &currentEntityIdAccentAdded, currentEntityId,
hoveredEntityEntityId](const AZ::EntityId entityId, const bool accent)
{
if (entityId == currentEntityId && accent)
{
currentEntityIdAccentAdded = true;
}
if (entityId == hoveredEntityEntityId && !accent)
{
hoveredEntityIdAccentRemoved = true;
}
});
using ::testing::Eq;
using ::testing::IsFalse;
using ::testing::IsTrue;
EXPECT_THAT(currentEntityIdAccentAdded, IsTrue());
EXPECT_THAT(hoveredEntityIdAccentRemoved, IsTrue());
EXPECT_THAT(hoveredEntityEntityId, Eq(AZ::EntityId(12345)));
}
} // namespace UnitTest
@@ -49,18 +49,17 @@ namespace
rlimit limit;
if (getrlimit(resource, &limit) != 0)
{
AZ_Error("Launcher", false, "[ERROR] Failed to get limit for resource %d. Error: %s", resource, strerror(errno));
return false;
AZ_Warning("Launcher", false, "[WARNING] Unable to get limit for resource %d. Error: %s", resource, strerror(errno));
}
if (updateLimit(limit))
{
if (setrlimit(resource, &limit) != 0)
{
AZ_Error("Launcher", false, "[ERROR] Failed to update resource limit for resource %d. Error: %s", resource, strerror(errno));
return false;
AZ_Warning("Launcher", false, "[WARNING] Unable to update resource limit for resource %d. Error: %s", resource, strerror(errno));
}
}
return true;
}
}
@@ -103,6 +103,8 @@ set(FILES
native/utilities/PlatformConfiguration.cpp
native/utilities/PlatformConfiguration.h
native/utilities/PotentialDependencies.h
native/utilities/StatsCapture.cpp
native/utilities/StatsCapture.h
native/utilities/SpecializedDependencyScanner.h
native/utilities/ThreadHelper.cpp
native/utilities/ThreadHelper.h
@@ -36,6 +36,7 @@ set(FILES
native/tests/platformconfiguration/platformconfigurationtests.h
native/tests/utilities/JobModelTest.cpp
native/tests/utilities/JobModelTest.h
native/tests/utilities/StatsCaptureTest.cpp
native/tests/AssetCatalog/AssetCatalogUnitTests.cpp
native/tests/assetscanner/AssetScannerTests.h
native/tests/assetscanner/AssetScannerTests.cpp
@@ -25,6 +25,7 @@
#include <native/AssetManager/PathDependencyManager.h>
#include <native/utilities/BuilderConfigurationBus.h>
#include <native/utilities/StatsCapture.h>
#include "AssetRequestHandler.h"
@@ -123,6 +124,9 @@ namespace AssetProcessor
{
if (status == AssetProcessor::AssetScanningStatus::Started)
{
// capture scanning stats:
AssetProcessor::StatsCapture::BeginCaptureStat("AssetScanning");
// Ensure that the source file list is populated before a scan begins
m_sourceFilesInDatabase.clear();
m_fileModTimes.clear();
@@ -176,6 +180,8 @@ namespace AssetProcessor
(status == AssetProcessor::AssetScanningStatus::Stopped))
{
m_isCurrentlyScanning = false;
AssetProcessor::StatsCapture::EndCaptureStat("AssetScanning");
// we cannot invoke this immediately - the scanner might be done, but we aren't actually ready until we've processed all remaining messages:
QMetaObject::invokeMethod(this, "CheckMissingFiles", Qt::QueuedConnection);
}
@@ -209,13 +215,24 @@ namespace AssetProcessor
}
else
{
QString statKey = QString("ProcessJob,%1,%2,%3").arg(jobEntry.m_databaseSourceName).arg(jobEntry.m_jobKey).arg(jobEntry.m_platformInfo.m_identifier.c_str());
if (status == JobStatus::InProgress)
{
//update to in progress status
m_jobRunKeyToJobInfoMap[jobEntry.m_jobRunKey].m_status = JobStatus::InProgress;
// stats tracking. Start accumulating time.
AssetProcessor::StatsCapture::BeginCaptureStat(statKey.toUtf8().constData());
}
else //if failed or succeeded remove from the map
{
// note that sometimes this gets called twice, once by the RCJobs thread and once by the AP itself,
// because sometimes jobs take a short cut from "started" -> "failed" or "started" -> "complete
// without going thru the RC.
// as such, all the code in this block should be crafted to work regardless of whether its double called.
AssetProcessor::StatsCapture::EndCaptureStat(statKey.toUtf8().constData());
m_jobRunKeyToJobInfoMap.erase(jobEntry.m_jobRunKey);
Q_EMIT SourceFinished(sourceUUID, legacySourceUUID);
Q_EMIT JobComplete(jobEntry, status);
@@ -3355,8 +3372,13 @@ namespace AssetProcessor
AZStd::string logFileName = AssetUtilities::ComputeJobLogFileName(createJobsRequest);
{
AssetUtilities::JobLogTraceListener jobLogTraceListener(logFileName, runKey, true);
// track the time it takes to createJobs. We can perform analysis later to present it by extension and other stats.
QString statKey = QString("CreateJobs,%1,%2").arg(actualRelativePath).arg(builderInfo.m_name.c_str());
AssetProcessor::StatsCapture::BeginCaptureStat(statKey.toUtf8().constData());
builderInfo.m_createJobFunction(createJobsRequest, createJobsResponse);
AssetProcessor::StatsCapture::EndCaptureStat(statKey.toUtf8().constData());
}
AssetProcessor::SetThreadLocalJobId(0);
bool isBuilderMissingFingerprint = (createJobsResponse.m_result == AssetBuilderSDK::CreateJobsResultCode::Success
@@ -4839,5 +4861,7 @@ namespace AssetProcessor
}
return filesFound;
}
} // namespace AssetProcessor
@@ -0,0 +1,200 @@
/*
* 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 <native/tests/AssetProcessorTest.h>
#include <native/utilities/StatsCapture.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzCore/Debug/TraceMessageBus.h>
#include <AzCore/StringFunc/StringFunc.h>
// the simple stats capture system has a trivial interface and only writes to printf.
// So the simplest tests we can do is make sure it only asserts when it should
// and doesn't assert in cases when it shouldn't, and that the stats are reasonable
// in printf format.
namespace AssetProcessor
{
// Its okay to talk to this system when unintialized, you can gain some perf
// by not intializing it at all
TEST_F(AssetProcessorTest, StatsCaptureTest_UninitializedSystemDoesNotAssert)
{
AssetProcessor::StatsCapture::BeginCaptureStat("Test");
AssetProcessor::StatsCapture::EndCaptureStat("Test");
AssetProcessor::StatsCapture::Dump();
AssetProcessor::StatsCapture::Shutdown();
}
// Double-intiailize is an error
TEST_F(AssetProcessorTest, StatsCaptureTest_DoubleInitializeIsAnAssert)
{
m_errorAbsorber->Clear();
AssetProcessor::StatsCapture::Initialize();
AssetProcessor::StatsCapture::Initialize();
EXPECT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0);
EXPECT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 1); // not allowed to assert on this
AssetProcessor::StatsCapture::BeginCaptureStat("Test");
AssetProcessor::StatsCapture::Shutdown();
}
class StatsCaptureOutputTest : public AssetProcessorTest, public AZ::Debug::TraceMessageBus::Handler
{
public:
void SetUp() override
{
AssetProcessorTest::SetUp();
AssetProcessor::StatsCapture::Initialize();
}
// dump but also capture the dump as a vector of lines:
void Dump()
{
AZ::Debug::TraceMessageBus::Handler::BusConnect();
AssetProcessor::StatsCapture::Dump();
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
}
virtual bool OnPrintf(const char* /*window*/, const char* message)
{
m_gatheredMessages.emplace_back(message);
AZ::StringFunc::TrimWhiteSpace(m_gatheredMessages.back(), true, true);
return false;
}
void TearDown() override
{
m_gatheredMessages = {};
AssetProcessor::StatsCapture::Shutdown();
AssetProcessorTest::TearDown();
}
AZStd::vector<AZStd::string> m_gatheredMessages;
};
// turning off machine and human readable mode, should not dump anything.
TEST_F(StatsCaptureOutputTest, StatsCaptureTest_DisabledByRegset_DumpsNothing)
{
auto registry = AZ::SettingsRegistry::Get();
ASSERT_NE(registry, nullptr);
registry->Set("/Amazon/AssetProcessor/Settings/Stats/HumanReadable", false);
registry->Set("/Amazon/AssetProcessor/Settings/Stats/MachineReadable", false);
AssetProcessor::StatsCapture::BeginCaptureStat("Test");
AssetProcessor::StatsCapture::EndCaptureStat("Test");
Dump();
EXPECT_EQ(m_gatheredMessages.size(), 0);
}
// turning on Human Readable, turn off Machine Readable, should not output any machine readable stats.
TEST_F(StatsCaptureOutputTest, StatsCaptureTest_HumanReadableOnly_DumpsNoMachineReadable)
{
auto registry = AZ::SettingsRegistry::Get();
ASSERT_NE(registry, nullptr);
registry->Set("/Amazon/AssetProcessor/Settings/Stats/HumanReadable", true);
registry->Set("/Amazon/AssetProcessor/Settings/Stats/MachineReadable", false);
AssetProcessor::StatsCapture::BeginCaptureStat("Test");
AssetProcessor::StatsCapture::EndCaptureStat("Test");
Dump();
EXPECT_GT(m_gatheredMessages.size(), 0);
for (const auto& message : m_gatheredMessages)
{
// we expect to see ZERO "Machine Readable" lines
EXPECT_FALSE(message.contains("MachineReadableStat:")) << "Found unexpected line in output: " << message.c_str();
}
}
// Turn on Machine Readable, Turn off Human Readable, ensure only Machine Readable stats emitted.
TEST_F(StatsCaptureOutputTest, StatsCaptureTest_MachineReadableOnly_DumpsNoHumanReadable)
{
auto registry = AZ::SettingsRegistry::Get();
ASSERT_NE(registry, nullptr);
registry->Set("/Amazon/AssetProcessor/Settings/Stats/HumanReadable", false);
registry->Set("/Amazon/AssetProcessor/Settings/Stats/MachineReadable", true);
AssetProcessor::StatsCapture::BeginCaptureStat("Test");
AssetProcessor::StatsCapture::EndCaptureStat("Test");
Dump();
for (const auto& message : m_gatheredMessages)
{
// we expect to see ONLY "Machine Readable" lines
EXPECT_TRUE(message.contains("MachineReadableStat:")) << "Found unexpected line in output: " << message.c_str();
}
EXPECT_GT(m_gatheredMessages.size(), 0);
}
// The interface for StatsCapture just captures and then dumps.
// For us to test this, we thus have to capture and parse the dump output.
TEST_F(StatsCaptureOutputTest, StatsCaptureTest_Sanity)
{
auto registry = AZ::SettingsRegistry::Get();
ASSERT_NE(registry, nullptr);
// Make it output in "machine raadable" format so that it is simpler to parse.
registry->Set("/Amazon/AssetProcessor/Settings/Stats/HumanReadable", false);
registry->Set("/Amazon/AssetProcessor/Settings/Stats/MachineReadable", true);
AssetProcessor::StatsCapture::BeginCaptureStat("CreateJobs,foo,mybuilder");
AssetProcessor::StatsCapture::EndCaptureStat("CreateJobs,foo,mybuilder");
// Intentionally not using sleeps in this test. It means that the
// captured duration will be likely 0 but its not worth it to slow down tests.
// If the durations end up 0 its going to be extremely noticable in day-to-day use.
AssetProcessor::StatsCapture::BeginCaptureStat("CreateJobs,foo,mybuilder");
AssetProcessor::StatsCapture::EndCaptureStat("CreateJobs,foo,mybuilder");
// for the second stat, we'll double capture and double end, in order to test debounce
AssetProcessor::StatsCapture::BeginCaptureStat("CreateJobs,foo2,mybuilder");
AssetProcessor::StatsCapture::BeginCaptureStat("CreateJobs,foo2,mybuilder");
AssetProcessor::StatsCapture::EndCaptureStat("CreateJobs,foo2,mybuilder2");
AssetProcessor::StatsCapture::EndCaptureStat("CreateJobs,foo2,mybuilder2");
m_gatheredMessages.clear();
Dump();
EXPECT_GT(m_gatheredMessages.size(), 0);
// We'll parse the machine readable stat lines here and make sure that the following is true
// mybuilder appears
// mybuilder appears only once but count is 2
bool foundFoo = false;
bool foundFoo2 = false;
for (const auto& stat : m_gatheredMessages)
{
if (stat.contains("MachineReadableStat:"))
{
AZStd::vector<AZStd::string> tokens;
AZ::StringFunc::Tokenize(stat, tokens, ":", false, false);
ASSERT_EQ(tokens.size(), 5); // should be "MachineReadableStat:time:count:average:name)
const auto& countData = tokens[2];
const auto& nameData = tokens[4];
if (AZ::StringFunc::Equal(nameData, "CreateJobs,foo,mybuilder"))
{
EXPECT_FALSE(foundFoo); // should only find one of these
foundFoo = true;
EXPECT_STREQ(countData.c_str(), "2");
}
if (AZ::StringFunc::Equal(nameData, "CreateJobs,foo2,mybuilder2"))
{
EXPECT_FALSE(foundFoo2); // should only find one of these
foundFoo2 = true;
EXPECT_STREQ(countData.c_str(), "1");
}
}
}
EXPECT_TRUE(foundFoo) << "The expected token CreateJobs,foo,mybuilder did not appear in the output.";
EXPECT_TRUE(foundFoo2) << "The expected CreateJobs.foo2.mybuilder2 did not appear in the output";
}
}
@@ -16,7 +16,8 @@
#include <AzFramework/Logging/LoggingComponent.h>
#include <AzFramework/Asset/AssetSystemComponent.h>
#include "native/resourcecompiler/RCBuilder.h"
#include <native/resourcecompiler/RCBuilder.h>
#include <native/utilities/StatsCapture.h>
#include <QLocale>
#include <QTranslator>
@@ -200,6 +201,10 @@ ApplicationManager::~ApplicationManager()
delete m_appDependencies[idx];
}
// end stats capture (dump and shutdown)
AssetProcessor::StatsCapture::Dump();
AssetProcessor::StatsCapture::Shutdown();
qInstallMessageHandler(nullptr);
//deleting QCoreApplication/QApplication
@@ -571,6 +576,8 @@ bool ApplicationManager::StartAZFramework()
bool ApplicationManager::ActivateModules()
{
AssetProcessor::StatsCapture::BeginCaptureStat("LoadingModules");
// we load the editor xml for our modules since it contains the list of gems we need for tools to function (not just runtime)
connect(&m_frameworkApp, &AssetProcessorAZApplication::AssetProcessorStatus, this,
[this](AssetProcessor::AssetProcessorStatusEntry entry)
@@ -587,6 +594,8 @@ bool ApplicationManager::ActivateModules()
}
m_frameworkApp.LoadDynamicModules();
AssetProcessor::StatsCapture::EndCaptureStat("LoadingModules");
return true;
}
@@ -618,6 +627,9 @@ ApplicationManager::BeforeRunStatus ApplicationManager::BeforeRun()
return ApplicationManager::BeforeRunStatus::Status_Failure;
}
// enable stats capture from this point on
AssetProcessor::StatsCapture::Initialize();
return ApplicationManager::BeforeRunStatus::Status_Success;
}
@@ -1173,6 +1173,7 @@ void ApplicationManagerBase::InitBuilderManager()
{
m_builderManager->ConnectionLost(connId);
});
}
void ApplicationManagerBase::ShutdownBuilderManager()
@@ -0,0 +1,394 @@
/*
* 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 <native/utilities/StatsCapture.h>
#include <native/assetprocessor.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzCore/std/chrono/chrono.h>
#include <AzCore/std/chrono/clocks.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/sort.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/containers/unordered_set.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <inttypes.h>
namespace AssetProcessor
{
namespace StatsCapture
{
// This class captures stats by storing them in a map of type
// [name of stat] -> Stat struct
// It can then analyze these stats and produce more stats from the original
// Captures, before dumping.
class StatsCaptureImpl final
{
public:
AZ_CLASS_ALLOCATOR(StatsCaptureImpl, AZ::SystemAllocator, 0);
void BeginCaptureStat(AZStd::string_view statName);
void EndCaptureStat(AZStd::string_view statName);
void Dump();
private:
using timepoint = AZStd::chrono::high_resolution_clock::time_point;
using duration = AZStd::chrono::milliseconds;
struct StatsEntry
{
duration m_cumulativeTime = {}; // The total amount of time spent on this.
timepoint m_operationStartTime = {}; // Async tracking - the last time stamp an operation started.
int64_t m_operationCount = 0; // In case there's more than one sample. Used to calc average.
};
AZStd::unordered_map<AZStd::string, StatsEntry> m_stats;
bool m_dumpMachineReadableStats = false;
bool m_dumpHumanReadableStats = true;
// Make a friendly time string of the format nnHnnMhhS.xxxms
AZStd::string FormatDuration(const duration& duration)
{
int64_t milliseconds = duration.count();
constexpr int64_t millisecondsInASecond = 1000;
constexpr int64_t millisecondsInAMinute = millisecondsInASecond * 60;
constexpr int64_t millisecondsInAnHour = millisecondsInAMinute * 60;
int64_t hours = milliseconds / millisecondsInAnHour;
milliseconds -= hours * millisecondsInAnHour;
int64_t minutes = milliseconds / millisecondsInAMinute;
milliseconds -= minutes * millisecondsInAMinute;
int64_t seconds = milliseconds / millisecondsInASecond;
milliseconds -= seconds * millisecondsInASecond;
// omit the sections which dont make sense for readability
if (hours)
{
return AZStd::string::format("%02" PRId64 "h%02" PRId64 "m%02" PRId64 "s%03" PRId64 "ms" , hours, minutes, seconds, milliseconds);
}
else if (minutes)
{
return AZStd::string::format(" %02" PRId64 "m%02" PRId64 "s%03" PRId64 "ms", minutes, seconds, milliseconds);
}
else if (seconds)
{
return AZStd::string::format(" %02" PRId64 "s%03" PRId64 "ms", seconds, milliseconds);
}
return AZStd::string::format(" %03" PRId64 "ms", milliseconds);
}
// Prints out a single stat.
void PrintStat([[maybe_unused]] const char* name, duration milliseconds, int64_t count)
{
// note that name may be unused as it only appears in Trace macros, which are
// stripped out in release builds.
if (count <= 1)
{
count = 1;
}
duration average(static_cast<int64_t>(static_cast<double>(milliseconds.count()) / static_cast<double>(count)));
if (m_dumpHumanReadableStats)
{
if (count > 1)
{
AZ_TracePrintf(AssetProcessor::ConsoleChannel, " Time: %s, Count: %4" PRId64 ", Average: %s, EventName: %s\n",
FormatDuration(milliseconds).c_str(),
count,
FormatDuration(average).c_str(),
name);
}
else
{
AZ_TracePrintf(AssetProcessor::ConsoleChannel, " Time: %s, EventName: %s\n",
FormatDuration(milliseconds).c_str(),
name);
}
}
if (m_dumpMachineReadableStats)
{
// machine Readable mode prints raw milliseconds and uses a CSV-like format
// note that the stat itself may contain commas, so we dont acutally separate with comma
// instead we separate with :
// and each "interesting line" is 'MachineReadableStat:milliseconds:count:average:name'
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "MachineReadableStat:%" PRId64 ":%" PRId64 ":%" PRId64 ":%s\n",
milliseconds.count(),
count,
count > 1 ? average.count() : milliseconds.count(),
name);
}
}
// calls PrintStat on each element in the vector.
void PrintStatsArray(AZStd::vector<AZStd::string>& keys, int maxToPrint, const char* header)
{
if ((m_dumpHumanReadableStats)&&(header))
{
AZ_TracePrintf(AssetProcessor::ConsoleChannel,"Top %i %s\n", maxToPrint, header);
}
auto sortByTimeDescending = [&](const AZStd::string& s1, const AZStd::string& s2)
{
return this->m_stats[s1].m_cumulativeTime > this->m_stats[s2].m_cumulativeTime;
};
AZStd::sort(keys.begin(), keys.end(), sortByTimeDescending);
for (int idx = 0; idx < maxToPrint; ++idx)
{
if (idx < keys.size())
{
PrintStat(keys[idx].c_str(), m_stats[keys[idx]].m_cumulativeTime, m_stats[keys[idx]].m_operationCount);
}
}
}
};
void StatsCaptureImpl::BeginCaptureStat(AZStd::string_view statName)
{
StatsEntry& existingStat = m_stats[statName];
if (existingStat.m_operationStartTime != timepoint())
{
// prevent double 'Begins'
return;
}
existingStat.m_operationStartTime = AZStd::chrono::high_resolution_clock::now();
}
void StatsCaptureImpl::EndCaptureStat(AZStd::string_view statName)
{
StatsEntry& existingStat = m_stats[statName];
if (existingStat.m_operationStartTime != timepoint())
{
existingStat.m_cumulativeTime = AZStd::chrono::high_resolution_clock::now() - existingStat.m_operationStartTime;
existingStat.m_operationCount = existingStat.m_operationCount + 1;
existingStat.m_operationStartTime = timepoint(); // reset the start time so that double 'Ends' are ignored.
}
}
void StatsCaptureImpl::Dump()
{
timepoint startTimeStamp = AZStd::chrono::high_resolution_clock::now();
auto settingsRegistry = AZ::SettingsRegistry::Get();
int maxCumulativeStats = 5; // default max cumulative stats to show
int maxIndividualStats = 5; // default max individual files to show
if (settingsRegistry)
{
AZ::u64 cumulativeStats = static_cast<AZ::u64>(maxCumulativeStats);
AZ::u64 individualStats = static_cast<AZ::u64>(maxIndividualStats);
settingsRegistry->Get(m_dumpHumanReadableStats, "/Amazon/AssetProcessor/Settings/Stats/HumanReadable");
settingsRegistry->Get(m_dumpMachineReadableStats, "/Amazon/AssetProcessor/Settings/Stats/MachineReadable");
settingsRegistry->Get(cumulativeStats, "/Amazon/AssetProcessor/Settings/Stats/MaxCumulativeStats");
settingsRegistry->Get(individualStats, "/Amazon/AssetProcessor/Settings/Stats/MaxIndividualStats");
maxCumulativeStats = static_cast<int>(cumulativeStats);
maxIndividualStats = static_cast<int>(individualStats);
}
if ((!m_dumpHumanReadableStats)&&(!m_dumpMachineReadableStats))
{
return;
}
AZStd::vector<AZStd::string> allCreateJobs; // individual
AZStd::vector<AZStd::string> allCreateJobsByBuilder; // bucketed by builder
AZStd::vector<AZStd::string> allProcessJobs; // individual
AZStd::vector<AZStd::string> allProcessJobsByPlatform; // bucketed by platform
AZStd::vector<AZStd::string> allProcessJobsByJobKey; // bucketed by type of job (job key)
AZStd::vector<AZStd::string> allHashFiles;
// capture only existing keys as we will be expanding the stats
// this approach avoids mutating an iterator.
AZStd::vector<AZStd::string> statKeys;
for (const auto& element : m_stats)
{
statKeys.push_back(element.first);
}
for (const AZStd::string& statKey : statKeys)
{
const StatsEntry& statistic = m_stats[statKey];
// Createjobs stats encode like (CreateJobs,sourcefilepath,builderid)
if (AZ::StringFunc::StartsWith(statKey, "CreateJobs,", true))
{
allCreateJobs.push_back(statKey);
AZStd::vector<AZStd::string> tokens;
AZ::StringFunc::Tokenize(statKey, tokens, ",", false, false);
// look up the builder so you can get its name:
AZStd::string_view builderName = tokens[2];
// synthesize a stat to track per-builder createjobs times:
{
AZStd::string newStatKey = AZStd::string::format("CreateJobsByBuilder,%.*s", AZ_STRING_ARG(builderName));
auto insertion = m_stats.insert(newStatKey);
StatsEntry& statToSynth = insertion.first->second;
statToSynth.m_cumulativeTime += statistic.m_cumulativeTime;
statToSynth.m_operationCount += statistic.m_operationCount;
if (insertion.second)
{
allCreateJobsByBuilder.push_back(newStatKey);
}
}
// synthesize a stat to track total createjobs times:
{
StatsEntry& statToSynth = m_stats["CreateJobsTotal"];
statToSynth.m_cumulativeTime += statistic.m_cumulativeTime;
statToSynth.m_operationCount += statistic.m_operationCount;
}
}
else if (AZ::StringFunc::StartsWith(statKey, "ProcessJob,", true))
{
allProcessJobs.push_back(statKey);
// processjob has the format ProcessJob,sourcename,jobkey,platformname
AZStd::vector<AZStd::string> tokens;
AZ::StringFunc::Tokenize(statKey, tokens, ",", false, false);
AZStd::string_view jobKey = tokens[2];
AZStd::string_view platformName = tokens[3];
// synthesize a stat to record process time accumulated by job key platform
{
AZStd::string newStatKey = AZStd::string::format("ProcessJobsByPlatform,%.*s", AZ_STRING_ARG(platformName));
auto insertion = m_stats.insert(newStatKey);
StatsEntry& statToSynth = insertion.first->second;
statToSynth.m_cumulativeTime += statistic.m_cumulativeTime;
statToSynth.m_operationCount += statistic.m_operationCount;
if (insertion.second)
{
allProcessJobsByPlatform.push_back(newStatKey);
}
}
// synthesize a stat to record process time accumulated job key total across all platforms
{
AZStd::string newStatKey = AZStd::string::format("ProcessJobsByJobKey,%.*s", AZ_STRING_ARG(jobKey));
auto insertion = m_stats.insert(newStatKey);
StatsEntry& statToSynth = insertion.first->second;
statToSynth.m_cumulativeTime += statistic.m_cumulativeTime;
statToSynth.m_operationCount += statistic.m_operationCount;
if (insertion.second)
{
allProcessJobsByJobKey.push_back(newStatKey);
}
}
// synthesize a stat to track total processjob times:
{
StatsEntry& statToSynth = m_stats["ProcessJobsTotal"];
statToSynth.m_cumulativeTime += statistic.m_cumulativeTime;
statToSynth.m_operationCount += statistic.m_operationCount;
}
}
else if (AZ::StringFunc::StartsWith(statKey, "HashFile,", true))
{
allHashFiles.push_back(statKey);
// processjob has the format ProcessJob,sourcename,jobkey,platformname
// synthesize a stat to track total hash times:
StatsEntry& statToSynth = m_stats["HashFileTotal"];
statToSynth.m_cumulativeTime += statistic.m_cumulativeTime;
statToSynth.m_operationCount += statistic.m_operationCount;
}
}
StatsEntry& gemLoadStat = m_stats["LoadingModules"];
PrintStat("LoadingGems", gemLoadStat.m_cumulativeTime, 1);
// analysis-related stats
StatsEntry& totalScanTime = m_stats["AssetScanning"];
PrintStat("AssetScanning", totalScanTime.m_cumulativeTime, totalScanTime.m_operationCount);
StatsEntry& totalHashTime = m_stats["HashFileTotal"];
PrintStat("HashFileTotal", totalHashTime.m_cumulativeTime, totalHashTime.m_operationCount);
PrintStatsArray(allHashFiles, maxIndividualStats, "longest individual file hashes:");
// CreateJobs stats
StatsEntry& totalCreateJobs = m_stats["CreateJobsTotal"];
if (totalCreateJobs.m_operationCount)
{
PrintStat("CreateJobsTotal", totalCreateJobs.m_cumulativeTime, totalCreateJobs.m_operationCount);
PrintStatsArray(allCreateJobs, maxIndividualStats, "longest individual CreateJobs");
PrintStatsArray(allCreateJobsByBuilder, maxCumulativeStats, "longest CreateJobs By builder");
}
// ProcessJobs stats
StatsEntry& totalProcessJobs = m_stats["ProcessJobsTotal"];
if (totalProcessJobs.m_operationCount)
{
PrintStat("ProcessJobsTotal", totalProcessJobs.m_cumulativeTime, totalProcessJobs.m_operationCount);
PrintStatsArray(allProcessJobs, maxIndividualStats, "longest individual ProcessJob");
PrintStatsArray(allProcessJobsByJobKey, maxCumulativeStats, "cumulative time spent in ProcessJob by JobKey");
PrintStatsArray(allProcessJobsByPlatform, maxCumulativeStats, "cumulative time spent in ProcessJob by Platform");
}
duration costToGenerateStats = AZStd::chrono::high_resolution_clock::now() - startTimeStamp;
PrintStat("ComputeStatsTime", costToGenerateStats, 1);
}
// Public interface:
static StatsCaptureImpl* g_instance = nullptr;
//! call this one time before capturing stats.
void Initialize()
{
if (g_instance)
{
AZ_Assert(false, "An instance of StatsCaptureImpl already exists.");
return;
}
g_instance = aznew StatsCaptureImpl();
}
//! Call this one time as part of shutting down.
//! note that while it is an error to double-initialize, it is intentionally
//! not an error to call any other function when uninitialized, allowing this system
//! to essentially be "turned off" just by not initializing it in the first place.
void Shutdown()
{
if (g_instance)
{
delete g_instance;
g_instance = nullptr;
}
}
//! Start the clock running for a particular stat name.
void BeginCaptureStat(AZStd::string_view statName)
{
if (g_instance)
{
g_instance->BeginCaptureStat(statName);
}
}
//! Stop the clock running for a particular stat name.
void EndCaptureStat(AZStd::string_view statName)
{
if (g_instance)
{
g_instance->EndCaptureStat(statName);
}
}
//! Do additional processing and then write the cumulative stats to log.
//! Note that since this is an AP-specific system, the analysis done in the dump function
//! is going to make a lot of assumptions about the way the data is encoded.
void Dump()
{
if (g_instance)
{
g_instance->Dump();
}
}
}
}
@@ -0,0 +1,40 @@
/*
* 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
*
*/
// This is an AssetProcessor-only stats capture system. Its kept out-of-band
// from the rest of the Asset Processor systems so that it can avoid interfering
// with the rest of the processing decision making and other parts of AssetProcessor.
// This is not meant to be used anywhere except in AssetProcessor.
#pragma once
#include <AzCore/std/string/string_view.h>
namespace AssetProcessor
{
namespace StatsCapture
{
//! call this one time before capturing stats.
void Initialize();
//! Call this one time as part of shutting down.
void Shutdown();
//! Start the clock running for a particular stat name.
void BeginCaptureStat(AZStd::string_view statName);
//! Stop the clock running for a particular stat name.
void EndCaptureStat(AZStd::string_view statName);
//! Do additional processing and then write the cumulative stats to log.
//! Note that since this is an AP-specific system, the analysis done in the dump function
//! is going to make a lot of assumptions about the way the data is encoded.
void Dump();
}
}
@@ -10,9 +10,10 @@
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/Math/Sha1.h>
#include "native/utilities/PlatformConfiguration.h"
#include "native/AssetManager/FileStateCache.h"
#include "native/AssetDatabase/AssetDatabase.h"
#include <native/utilities/PlatformConfiguration.h>
#include <native/utilities/StatsCapture.h>
#include <native/AssetManager/FileStateCache.h>
#include <native/AssetDatabase/AssetDatabase.h>
#include <utilities/ThreadHelper.h>
#include <QCoreApplication>
#include <QElapsedTimer>
+19
View File
@@ -154,10 +154,20 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
AZ::AWSNativeSDKInit
Gem::AWSCore.Static
)
ly_add_googletest(
NAME Gem::AWSCore.Tests
)
ly_add_target_files(
TARGETS
AWSCore.Tests
FILES
${CMAKE_CURRENT_SOURCE_DIR}/Tools/ResourceMappingTool/resource_mapping_schema.json
OUTPUT_SUBDIRECTORY
Gems/AWSCore
)
if (PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_target(
NAME AWSCore.Editor.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
@@ -189,4 +199,13 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
endif()
endif()
ly_add_target_files(
TARGETS
AWSCore
FILES
${CMAKE_CURRENT_SOURCE_DIR}/Tools/ResourceMappingTool/resource_mapping_schema.json
OUTPUT_SUBDIRECTORY
Gems/AWSCore
)
ly_install_directory(DIRECTORIES Tools/ResourceMappingTool)
@@ -22,63 +22,6 @@ namespace AWSCore
static constexpr const char ResourceMappingTypeKeyName[] = "Type";
static constexpr const char ResourceMappingVersionKeyName[] = "Version";
// TODO: move this into an independent file under AWSCore gem, if resource mapping tool can reuse it
static constexpr const char ResourceMappingJsonSchema[] =
R"({
"$schema": "http://json-schema.org/draft-04/schema",
"type": "object",
"title": "The AWS Resource Mapping Root schema",
"required": ["AWSResourceMappings", "AccountId", "Region", "Version"],
"properties": {
"AWSResourceMappings": {
"type": "object",
"title": "The AWSResourceMappings schema",
"patternProperties": {
"^.+$": {
"type": "object",
"title": "The AWS Resource Entry schema",
"required": ["Type", "Name/ID"],
"properties": {
"Type": {
"$ref": "#/NonEmptyString"
},
"Name/ID": {
"$ref": "#/NonEmptyString"
},
"AccountId": {
"$ref": "#/AccountIdString"
},
"Region": {
"$ref": "#/RegionString"
}
}
}
},
"additionalProperties": false
},
"AccountId": {
"$ref": "#/AccountIdString"
},
"Region": {
"$ref": "#/RegionString"
},
"Version": {
"pattern": "^[0-9]{1}.[0-9]{1}.[0-9]{1}$"
}
},
"AccountIdString": {
"type": "string",
"pattern": "^[0-9]{12}$|EMPTY|^$"
},
"NonEmptyString": {
"type": "string",
"minLength": 1
},
"RegionString": {
"type": "string",
"pattern": "^[a-z]{2}-[a-z]{4,9}-[0-9]{1}$"
},
"additionalProperties": false
})";
static constexpr const char ResourceMapppingJsonSchemaFilePath[] =
"Gems/AWSCore/resource_mapping_schema.json";
} // namespace AWSCore
@@ -12,6 +12,7 @@
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AWSCoreInternalBus.h>
@@ -244,14 +245,16 @@ namespace AWSCore
bool AWSResourceMappingManager::ValidateJsonDocumentAgainstSchema(const rapidjson::Document& jsonDocument)
{
rapidjson::Document jsonSchemaDocument;
if (jsonSchemaDocument.Parse(ResourceMappingJsonSchema).HasParseError())
AZ::IO::Path executablePath = AZ::IO::PathView(AZ::Utils::GetExecutableDirectory());
AZ::IO::Path jsonSchemaPath = (executablePath / ResourceMapppingJsonSchemaFilePath).LexicallyNormal();
AZ::Outcome<rapidjson::Document, AZStd::string> readJsonOutcome = AZ::JsonSerializationUtils::ReadJsonFile(jsonSchemaPath.c_str());
if (!readJsonOutcome.IsSuccess() || readJsonOutcome.TakeValue().ObjectEmpty())
{
AZ_Error(AWSResourceMappingManagerName, false, ResourceMappingFileInvalidSchemaErrorMessage);
return false;
}
auto jsonSchema = rapidjson::SchemaDocument(jsonSchemaDocument);
auto jsonSchema = rapidjson::SchemaDocument(readJsonOutcome.TakeValue());
rapidjson::SchemaValidator validator(jsonSchema);
if (!jsonDocument.Accept(validator))
@@ -121,7 +121,7 @@ public:
void SetUp() override
{
AWSCoreFixture::SetUp();
AWSCoreFixture::SetUpFixture(false);
m_normalizedSourceProjectFolder = AZStd::string::format("%s/%s%s/", AZ::Test::GetCurrentExecutablePath().c_str(),
"AWSResourceMappingManager", AZ::Uuid::CreateRandom().ToString<AZStd::string>(false, false).c_str());
@@ -142,7 +142,7 @@ public:
m_resourceMappingManager->DeactivateManager();
m_resourceMappingManager.reset();
AWSCoreFixture::TearDown();
AWSCoreFixture::TearDownFixture(false);
}
// AWSCoreInternalRequestBus interface implementation
@@ -8,6 +8,7 @@
#pragma once
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/Memory/PoolAllocator.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/Settings/SettingsRegistryImpl.h>
@@ -111,6 +112,11 @@ public:
~AWSCoreFixture() override = default;
void SetUp() override
{
SetUpFixture();
}
void SetUpFixture(bool mockSettingsRegistry = true)
{
AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Create();
AZ::AllocatorInstance<AZ::PoolAllocator>::Create();
@@ -120,14 +126,33 @@ public:
AZ::IO::FileIOBase::SetInstance(nullptr);
AZ::IO::FileIOBase::SetInstance(m_localFileIO);
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
if (mockSettingsRegistry)
{
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
AZ::SettingsRegistry::Register(m_settingsRegistry.get());
}
else
{
m_app = AZStd::make_unique<AZ::ComponentApplication>();
}
}
void TearDown() override
{
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
m_settingsRegistry.reset();
TearDownFixture();
}
void TearDownFixture(bool mockSettingsRegistry = true)
{
if (mockSettingsRegistry)
{
AZ::SettingsRegistry::Unregister(m_settingsRegistry.get());
m_settingsRegistry.reset();
}
else
{
m_app.reset();
}
AZ::IO::FileIOBase::SetInstance(nullptr);
@@ -173,4 +198,5 @@ private:
protected:
AZStd::unique_ptr<AZ::SettingsRegistryImpl> m_settingsRegistry;
AZStd::unique_ptr<AZ::ComponentApplication> m_app;
};
@@ -17,7 +17,7 @@ Or follow **AWS CLI** configuration which can be reused by boto3 lib:
1. In order to use engine python environment, it requires to link Qt binaries for this tool.
Follow cmake instructions to configure your project, for example:
```
$ cmake -B <BUILD_FOLDER> -S . -G "Visual Studio 16 2019" -DLY_3RDPARTY_PATH=<PATH_TO_3RDPARTY> -DLY_PROJECTS=<PROJECT_NAME>
$ cmake -B <BUILD_FOLDER> -S . -G "Visual Studio 16 2019" -DLY_PROJECTS=<PROJECT_NAME>
```
2. At this point, double check engine python environment gets setup under *<ENGINE_ROOT_PATH>/python/runtime* directory
@@ -0,0 +1,56 @@
{
"$schema": "http://json-schema.org/draft-04/schema",
"type": "object",
"title": "O3DE AWS Resource mapping file schema",
"required": ["AWSResourceMappings", "AccountId", "Region", "Version"],
"properties": {
"AWSResourceMappings": {
"type": "object",
"title": "AWS resource mappings schema",
"patternProperties": {
"^.+$": {
"type": "object",
"title": "AWS resource entry schema",
"required": ["Type", "Name/ID"],
"properties": {
"Type": {
"$ref": "#/NonEmptyString"
},
"Name/ID": {
"$ref": "#/NonEmptyString"
},
"AccountId": {
"$ref": "#/AccountIdString"
},
"Region": {
"$ref": "#/RegionString"
}
}
}
},
"additionalProperties": false
},
"AccountId": {
"$ref": "#/AccountIdString"
},
"Region": {
"$ref": "#/RegionString"
},
"Version": {
"pattern": "^[0-9]{1}.[0-9]{1}.[0-9]{1}$"
}
},
"AccountIdString": {
"type": "string",
"pattern": "^[0-9]{12}$|EMPTY|^$"
},
"NonEmptyString": {
"type": "string",
"minLength": 1
},
"RegionString": {
"type": "string",
"pattern": "^[a-z]{2}-[a-z]{4,9}-[0-9]{1}$"
},
"additionalProperties": false
}
@@ -10,6 +10,7 @@ import logging
import sys
from utils import environment_utils
from utils import json_utils
from utils import file_utils
# arguments setup
@@ -74,6 +75,15 @@ if __name__ == "__main__":
except FileNotFoundError:
logger.warning("Failed to load style sheet for resource mapping tool")
try:
schema_path: str = file_utils.join_path(file_utils.get_parent_directory_path(__file__),
'resource_mapping_schema.json')
json_utils.load_resource_mapping_json_schema(schema_path)
except (FileNotFoundError, ValueError, KeyError) as e:
logger.error(f"Failed to load schema file {e}")
environment_utils.cleanup_qt_environment()
exit(-1)
logger.info("Initializing configuration manager ...")
configuration_manager: ConfigurationManager = ConfigurationManager()
configuration_error: bool = not configuration_manager.setup(arguments.profile, arguments.config_path)
@@ -68,12 +68,65 @@ class TestFileUtils(TestCase):
self._mock_path.cwd.assert_called_once()
assert actual_path_name == TestFileUtils._expected_path_name
def test_get_parent_directory_path_return_expected_path_name(self) -> None:
self._mock_path.return_value.parent = TestFileUtils._expected_path_name
def test_get_parent_directory_path_return_empty_when_invalid_input(self) -> None:
mocked_path: MagicMock = self._mock_path.return_value
mocked_path.exists.return_value = False
actual_path_name: str = file_utils.get_parent_directory_path("dummy")
self._mock_path.assert_called_once()
assert actual_path_name == TestFileUtils._expected_path_name
assert actual_path_name == ""
def test_get_parent_directory_path_return_empty_when_parent_invalid(self) -> None:
mocked_path: MagicMock = self._mock_path.return_value
mocked_path.exists.return_value = True
mocked_parent_path: MagicMock = MagicMock()
mocked_path.parent = mocked_parent_path
mocked_parent_path.exists.return_value = False
actual_path_name: str = file_utils.get_parent_directory_path("dummy")
self._mock_path.assert_called()
assert actual_path_name == ""
def test_get_parent_directory_path_return_expected_path_when_parent_valid(self) -> None:
mocked_path: MagicMock = self._mock_path.return_value
mocked_path.exists.return_value = True
mocked_parent_path: MagicMock = MagicMock()
mocked_path.parent = mocked_parent_path
mocked_parent_path.exists.return_value = True
mocked_parent_path.resolve.return_value = TestFileUtils._expected_file_name
actual_path_name: str = file_utils.get_parent_directory_path("dummy")
self._mock_path.assert_called()
assert actual_path_name == TestFileUtils._expected_file_name
def test_get_parent_directory_path_return_empty_when_level_two_parent_invalid(self) -> None:
mocked_path: MagicMock = self._mock_path.return_value
mocked_path.exists.return_value = True
mocked_parent_path1: MagicMock = MagicMock()
mocked_path.parent = mocked_parent_path1
mocked_parent_path1.exists.return_value = True
mocked_parent_path2: MagicMock = MagicMock()
mocked_parent_path1.parent = mocked_parent_path2
mocked_parent_path2.exists.return_value = False
actual_path_name: str = file_utils.get_parent_directory_path("dummy", 2)
self._mock_path.assert_called()
assert actual_path_name == ""
def test_get_parent_directory_path_return_expected_path_when_level_two_parent_valid(self) -> None:
mocked_path: MagicMock = self._mock_path.return_value
mocked_path.exists.return_value = True
mocked_parent_path1: MagicMock = MagicMock()
mocked_path.parent = mocked_parent_path1
mocked_parent_path1.exists.return_value = True
mocked_parent_path2: MagicMock = MagicMock()
mocked_parent_path1.parent = mocked_parent_path2
mocked_parent_path2.exists.return_value = True
mocked_parent_path2.resolve.return_value = TestFileUtils._expected_file_name
actual_path_name: str = file_utils.get_parent_directory_path("dummy", 2)
self._mock_path.assert_called()
assert actual_path_name == TestFileUtils._expected_file_name
def test_find_files_with_suffix_under_directory_return_expected_file_name(self) -> None:
mocked_path: MagicMock = self._mock_path.return_value
@@ -10,6 +10,7 @@ from typing import (Dict, List)
from unittest import TestCase
from unittest.mock import (MagicMock, mock_open, patch)
from utils import file_utils
from utils import json_utils
from model import constants
from model.resource_mapping_attributes import (ResourceMappingAttributes, ResourceMappingAttributesBuilder,
@@ -49,6 +50,10 @@ class TestJsonUtils(TestCase):
}
def setUp(self) -> None:
schema_path: str = file_utils.join_path(file_utils.get_parent_directory_path(__file__, 4),
'resource_mapping_schema.json')
json_utils.load_resource_mapping_json_schema(schema_path)
self._mock_open = mock_open()
open_patcher: patch = patch("utils.json_utils.open", self._mock_open)
self.addCleanup(open_patcher.stop)
@@ -33,8 +33,29 @@ def get_current_directory_path() -> str:
return str(pathlib.Path.cwd())
def get_parent_directory_path(file_path: str) -> str:
return pathlib.Path(file_path).parent
def get_parent_directory_path(file_path: str, level: int = 1) -> str:
"""
Get parent directory path based on requested file path
:param file_path: The requested file path
:param level: The level of parent directory, default value is 1
:return The string value of parent directory path if exist; otherwise empty string
"""
if not pathlib.Path(file_path).exists():
return ""
result: pathlib.Path = pathlib.Path(file_path).parent
current_level: int = 1
while current_level < level:
current_level += 1
if result.exists():
result = result.parent
else:
return ""
if not result.exists():
return ""
else:
return result.resolve()
def find_files_with_suffix_under_directory(dir_path: str, suffix: str) -> List[str]:
@@ -19,18 +19,29 @@ Json Utils provide related functions to read/write/serialize/deserialize json fo
"""
logger = logging.getLogger(__name__)
# resource mapping json content constants
_RESOURCE_MAPPING_JSON_KEY_NAME: str = "AWSResourceMappings"
_RESOURCE_MAPPING_TYPE_JSON_KEY_NAME: str = "Type"
_RESOURCE_MAPPING_NAMEID_JSON_KEY_NAME: str = "Name/ID"
_RESOURCE_MAPPING_REGION_JSON_KEY_NAME: str = "Region"
_RESOURCE_MAPPING_VERSION_JSON_KEY_NAME: str = "Version"
_RESOURCE_MAPPING_JSON_FORMAT_VERSION: str = "1.1.0"
RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME: str = "AccountId"
RESOURCE_MAPPING_ACCOUNTID_TEMPLATE_VALUE: str = "EMPTY"
_RESOURCE_MAPPING_ACCOUNTID_PATTERN: str = f"^[0-9]{{12}}$|{RESOURCE_MAPPING_ACCOUNTID_TEMPLATE_VALUE}|^$"
_RESOURCE_MAPPING_REGION_PATTERN: str = "^[a-z]{2}-[a-z]{4,9}-[0-9]{1}$"
_RESOURCE_MAPPING_VERSION_PATTERN: str = "^[0-9]{1}.[0-9]{1}.[0-9]{1}$"
# resource mapping json schema constants
_RESOURCE_MAPPING_SCHEMA_ACCOUNTID_KEY_NAME: str = "AccountIdString"
_RESOURCE_MAPPING_SCHEMA_REGION_KEY_NAME: str = "RegionString"
_RESOURCE_MAPPING_SCHEMA_REQUIRED_PROPERTIES_KEY_NAME: str = "required"
_RESOURCE_MAPPING_SCHEMA_PROPERTIES_KEY_NAME: str = "properties"
_RESOURCE_MAPPING_SCHEMA_PATTERN_PROPERTIES_KEY_NAME: str = "patternProperties"
_RESOURCE_MAPPING_SCHEMA_PROPERTY_PATTERN_KEY_NAME: str = "pattern"
_RESOURCE_MAPPING_SCHEMA: Dict[str, any] = {}
_RESOURCE_MAPPING_SCHEMA_REQUIRED_ROOT_PROPERTIES: List[str] = []
_RESOURCE_MAPPING_SCHEMA_REQUIRED_RESOURCE_PROPERTIES: List[str] = []
_RESOURCE_MAPPING_SCHEMA_ACCOUNTID_PATTERN: str = ""
_RESOURCE_MAPPING_SCHEMA_REGION_PATTERN: str = ""
_RESOURCE_MAPPING_SCHEMA_VERSION_PATTERN: str = ""
def _add_validation_error_message(errors: Dict[int, List[str]], row: int, error_message: str) -> None:
if row in errors.keys():
@@ -119,6 +130,26 @@ def convert_json_dict_to_resources(json_dict: Dict[str, any]) -> List[ResourceMa
return resources
def load_resource_mapping_json_schema(schema_path: str) -> None:
global _RESOURCE_MAPPING_SCHEMA, _RESOURCE_MAPPING_SCHEMA_REQUIRED_ROOT_PROPERTIES, _RESOURCE_MAPPING_SCHEMA_REQUIRED_RESOURCE_PROPERTIES,\
_RESOURCE_MAPPING_SCHEMA_ACCOUNTID_PATTERN, _RESOURCE_MAPPING_SCHEMA_REGION_PATTERN, _RESOURCE_MAPPING_SCHEMA_VERSION_PATTERN
if not _RESOURCE_MAPPING_SCHEMA:
# assume schema should be in correct format, and manually load expected pattern; tool will log error if schema is invalid
_RESOURCE_MAPPING_SCHEMA = read_from_json_file(schema_path)
_RESOURCE_MAPPING_SCHEMA_REQUIRED_ROOT_PROPERTIES = _RESOURCE_MAPPING_SCHEMA[_RESOURCE_MAPPING_SCHEMA_REQUIRED_PROPERTIES_KEY_NAME]
schema_properties: Dict[str, any] = _RESOURCE_MAPPING_SCHEMA[_RESOURCE_MAPPING_SCHEMA_PROPERTIES_KEY_NAME]
schema_pattern_properties: Dict[str, any] = \
schema_properties[_RESOURCE_MAPPING_JSON_KEY_NAME][_RESOURCE_MAPPING_SCHEMA_PATTERN_PROPERTIES_KEY_NAME]
_RESOURCE_MAPPING_SCHEMA_REQUIRED_RESOURCE_PROPERTIES = list(schema_pattern_properties.values())[0][_RESOURCE_MAPPING_SCHEMA_REQUIRED_PROPERTIES_KEY_NAME]
_RESOURCE_MAPPING_SCHEMA_ACCOUNTID_PATTERN = \
_RESOURCE_MAPPING_SCHEMA[_RESOURCE_MAPPING_SCHEMA_ACCOUNTID_KEY_NAME][_RESOURCE_MAPPING_SCHEMA_PROPERTY_PATTERN_KEY_NAME]
_RESOURCE_MAPPING_SCHEMA_REGION_PATTERN = \
_RESOURCE_MAPPING_SCHEMA[_RESOURCE_MAPPING_SCHEMA_REGION_KEY_NAME][_RESOURCE_MAPPING_SCHEMA_PROPERTY_PATTERN_KEY_NAME]
_RESOURCE_MAPPING_SCHEMA_VERSION_PATTERN = \
schema_properties[_RESOURCE_MAPPING_VERSION_JSON_KEY_NAME][_RESOURCE_MAPPING_SCHEMA_PROPERTY_PATTERN_KEY_NAME]
def read_from_json_file(file_name: str) -> Dict[str, any]:
try:
json_dict: Dict[str, any] = {}
@@ -166,20 +197,20 @@ def validate_resources_according_to_json_schema(resources: List[ResourceMappingA
invalid_resources, row_count,
error_messages.INVALID_FORMAT_DUPLICATED_KEY_ERROR_MESSAGE.format(resource.key_name))
if not re.match(_RESOURCE_MAPPING_ACCOUNTID_PATTERN, resource.account_id):
if not re.match(_RESOURCE_MAPPING_SCHEMA_ACCOUNTID_PATTERN, resource.account_id):
_add_validation_error_message(
invalid_resources, row_count,
error_messages.INVALID_FORMAT_UNEXPECTED_VALUE_IN_TABLE_ERROR_MESSAGE.format(
resource.account_id,
RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME,
_RESOURCE_MAPPING_ACCOUNTID_PATTERN))
_RESOURCE_MAPPING_SCHEMA_ACCOUNTID_PATTERN))
if not re.match(_RESOURCE_MAPPING_REGION_PATTERN, resource.region):
if not re.match(_RESOURCE_MAPPING_SCHEMA_REGION_PATTERN, resource.region):
_add_validation_error_message(
invalid_resources, row_count,
error_messages.INVALID_FORMAT_UNEXPECTED_VALUE_IN_TABLE_ERROR_MESSAGE.format(
resource.region, _RESOURCE_MAPPING_REGION_JSON_KEY_NAME,
_RESOURCE_MAPPING_REGION_PATTERN))
_RESOURCE_MAPPING_SCHEMA_REGION_PATTERN))
row_count += 1
@@ -187,30 +218,32 @@ def validate_resources_according_to_json_schema(resources: List[ResourceMappingA
def validate_json_dict_according_to_json_schema(json_dict: Dict[str, any]) -> None:
_validate_required_key_in_json_dict(json_dict, "root", _RESOURCE_MAPPING_VERSION_JSON_KEY_NAME)
_validate_required_key_in_json_dict(json_dict, "root", _RESOURCE_MAPPING_JSON_KEY_NAME)
# The reason we keep this manual json schema validation is python missing supportive feature in default libs
# When it is ready, we should be able to replace this with straightforward lib function call
root_property: str
for root_property in _RESOURCE_MAPPING_SCHEMA_REQUIRED_ROOT_PROPERTIES:
_validate_required_key_in_json_dict(json_dict, "root", root_property)
_validate_required_key_in_json_dict(json_dict, "root", RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME)
if not re.match(_RESOURCE_MAPPING_ACCOUNTID_PATTERN, json_dict[RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME]):
if not re.match(_RESOURCE_MAPPING_SCHEMA_ACCOUNTID_PATTERN, json_dict[RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME]):
raise ValueError(error_messages.INVALID_FORMAT_UNEXPECTED_VALUE_IN_FILE_ERROR_MESSAGE.format(
json_dict[RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME],
f"root/{RESOURCE_MAPPING_ACCOUNTID_JSON_KEY_NAME}",
_RESOURCE_MAPPING_ACCOUNTID_PATTERN))
_RESOURCE_MAPPING_SCHEMA_ACCOUNTID_PATTERN))
_validate_required_key_in_json_dict(json_dict, "root", _RESOURCE_MAPPING_REGION_JSON_KEY_NAME)
if not re.match(_RESOURCE_MAPPING_REGION_PATTERN, json_dict[_RESOURCE_MAPPING_REGION_JSON_KEY_NAME]):
if not re.match(_RESOURCE_MAPPING_SCHEMA_REGION_PATTERN, json_dict[_RESOURCE_MAPPING_REGION_JSON_KEY_NAME]):
raise ValueError(error_messages.INVALID_FORMAT_UNEXPECTED_VALUE_IN_FILE_ERROR_MESSAGE.format(
json_dict[_RESOURCE_MAPPING_REGION_JSON_KEY_NAME],
f"root/{_RESOURCE_MAPPING_REGION_JSON_KEY_NAME}",
_RESOURCE_MAPPING_REGION_PATTERN))
_RESOURCE_MAPPING_SCHEMA_REGION_PATTERN))
json_resources: Dict[str, any] = json_dict[_RESOURCE_MAPPING_JSON_KEY_NAME]
if json_resources:
resource_key: str
resource_value: Dict[str, str]
for resource_key, resource_value in json_resources.items():
_validate_required_key_in_json_dict(resource_value, resource_key, _RESOURCE_MAPPING_TYPE_JSON_KEY_NAME)
_validate_required_key_in_json_dict(resource_value, resource_key, _RESOURCE_MAPPING_NAMEID_JSON_KEY_NAME)
resource_property: str
for resource_property in _RESOURCE_MAPPING_SCHEMA_REQUIRED_RESOURCE_PROPERTIES:
_validate_required_key_in_json_dict(resource_value, resource_key, resource_property)
def write_into_json_file(file_name: str, json_dict: Dict[str, any]) -> None:
@@ -52,7 +52,7 @@ namespace ImageProcessingAtom
namespace
{
static constexpr const char* const LogWindow = "Image Processing";
[[maybe_unused]] static constexpr const char* const LogWindow = "Image Processing";
}
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
@@ -6,6 +6,8 @@
*
*/
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AtomActorDebugDraw.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/AuxGeom/AuxGeomDraw.h>
@@ -25,6 +27,7 @@
namespace AZ::Render
{
AtomActorDebugDraw::AtomActorDebugDraw(AZ::EntityId entityId)
: m_entityId(entityId)
{
m_auxGeomFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity<RPI::AuxGeomFeatureProcessorInterface>(entityId);
}
@@ -42,9 +45,11 @@ namespace AZ::Render
return;
}
const RPI::Scene* scene = RPI::Scene::GetSceneForEntityId(instance->GetEntityId());
const RPI::Scene* scene = RPI::Scene::GetSceneForEntityId(m_entityId);
const RPI::ViewportContextPtr viewport = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get()->GetViewportContextByScene(scene);
AzFramework::DebugDisplayRequests* debugDisplay = GetDebugDisplay(viewport->GetId());
const AZ::Render::RenderActorSettings& renderActorSettings = EMotionFX::GetRenderActorSettings();
const float scaleMultiplier = CalculateScaleMultiplier(instance);
// Render aabb
if (renderFlags[EMotionFX::ActorRenderFlag::RENDER_AABB])
@@ -75,6 +80,12 @@ namespace AZ::Render
RenderEMFXDebugDraw(instance);
}
// Render
if (renderFlags[EMotionFX::ActorRenderFlag::RENDER_NODEORIENTATION])
{
RenderNodeOrientations(instance, debugDisplay, renderActorSettings.m_nodeOrientationScale * scaleMultiplier);
}
// Render vertex normal, face normal, tagent and wireframe.
const bool renderVertexNormals = renderFlags[EMotionFX::ActorRenderFlag::RENDER_VERTEXNORMALS];
const bool renderFaceNormals = renderFlags[EMotionFX::ActorRenderFlag::RENDER_FACENORMALS];
@@ -87,7 +98,6 @@ namespace AZ::Render
const EMotionFX::Pose* pose = instance->GetTransformData()->GetCurrentPose();
const size_t geomLODLevel = instance->GetLODLevel();
const size_t numEnabled = instance->GetNumEnabledNodes();
const float scaleMultiplier = CalculateScaleMultiplier(instance);
for (size_t i = 0; i < numEnabled; ++i)
{
EMotionFX::Node* node = instance->GetActor()->GetSkeleton()->GetNode(instance->GetEnabledNode(i));
@@ -175,6 +185,13 @@ namespace AZ::Render
}
}
AzFramework::DebugDisplayRequests* AtomActorDebugDraw::GetDebugDisplay(AzFramework::ViewportId viewportId)
{
AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, viewportId);
return AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus);
}
void AtomActorDebugDraw::RenderAABB(EMotionFX::ActorInstance* instance, const AZ::Color& aabbColor)
{
RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue();
@@ -610,4 +627,89 @@ namespace AZ::Render
m_fontDrawInterface->DrawScreenAlignedText3d(m_drawParams, joint->GetName());
}
}
void AtomActorDebugDraw::RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance,
AzFramework::DebugDisplayRequests* debugDisplay, float scale)
{
// Get the actor and the transform data
const float unitScale =
1.0f / (float)MCore::Distance::ConvertValue(1.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType());
const EMotionFX::Actor* actor = actorInstance->GetActor();
const EMotionFX::Skeleton* skeleton = actor->GetSkeleton();
const EMotionFX::TransformData* transformData = actorInstance->GetTransformData();
const EMotionFX::Pose* pose = transformData->GetCurrentPose();
const float constPreScale = scale * unitScale * 3.0f;
const size_t numEnabled = actorInstance->GetNumEnabledNodes();
for (size_t i = 0; i < numEnabled; ++i)
{
EMotionFX::Node* joint = skeleton->GetNode(actorInstance->GetEnabledNode(i));
const size_t jointIndex = joint->GetNodeIndex();
static const float axisBoneScale = 50.0f;
const float size = CalculateBoneScale(actorInstance, joint) * constPreScale * axisBoneScale;
AZ::Transform worldTM = pose->GetWorldSpaceTransform(jointIndex).ToAZTransform();
RenderLineAxis(debugDisplay, worldTM, size, false /*selected*/);
}
}
void AtomActorDebugDraw::RenderLineAxis(
AzFramework::DebugDisplayRequests* debugDisplay,
AZ::Transform worldTM,
float size,
bool selected,
bool renderAxisName)
{
const float axisHeight = size * 0.7f;
const float frontSize = size * 5.0f + 0.2f;
const AZ::Vector3 position = worldTM.GetTranslation();
// Render x axis
{
AZ::Color xSelectedColor = selected ? AZ::Colors::Orange : AZ::Colors::Red;
const AZ::Vector3 xAxisDir = (worldTM.TransformPoint(AZ::Vector3(size, 0.0f, 0.0f)) - position).GetNormalized();
const AZ::Vector3 xAxisArrowStart = position + xAxisDir * axisHeight;
debugDisplay->SetColor(xSelectedColor);
debugDisplay->DrawArrow(position, xAxisArrowStart, size);
if (renderAxisName)
{
const AZ::Vector3 xNamePos = position + xAxisDir * (size * 1.15f);
debugDisplay->DrawTextLabel(xNamePos, frontSize, "X");
}
}
// Render y axis
{
AZ::Color ySelectedColor = selected ? AZ::Colors::Orange : AZ::Colors::Blue;
const AZ::Vector3 yAxisDir = (worldTM.TransformPoint(AZ::Vector3(0.0f, size, 0.0f)) - position).GetNormalized();
const AZ::Vector3 yAxisArrowStart = position + yAxisDir * axisHeight;
debugDisplay->SetColor(ySelectedColor);
debugDisplay->DrawArrow(position, yAxisArrowStart, size);
if (renderAxisName)
{
const AZ::Vector3 yNamePos = position + yAxisDir * (size * 1.15f);
debugDisplay->DrawTextLabel(yNamePos, frontSize, "Y");
}
}
// Render z axis
{
AZ::Color zSelectedColor = selected ? AZ::Colors::Orange : AZ::Colors::Green;
const AZ::Vector3 zAxisDir = (worldTM.TransformPoint(AZ::Vector3(0.0f, 0.0f, size)) - position).GetNormalized();
const AZ::Vector3 zAxisArrowStart = position + zAxisDir * axisHeight;
debugDisplay->SetColor(zSelectedColor);
debugDisplay->DrawArrow(position, zAxisArrowStart, size);
if (renderAxisName)
{
const AZ::Vector3 zNamePos = position + zAxisDir * (size * 1.15f);
debugDisplay->DrawTextLabel(zNamePos, frontSize, "Z");
}
}
}
} // namespace AZ::Render
@@ -15,6 +15,11 @@
#include <Integration/Rendering/RenderActorInstance.h>
#include <Atom/RPI.Public/ViewportContext.h>
namespace AzFramework
{
class DebugDisplayRequests;
}
namespace EMotionFX
{
class Mesh;
@@ -42,6 +47,7 @@ namespace AZ::Render
float CalculateBoneScale(EMotionFX::ActorInstance* actorInstance, EMotionFX::Node* node);
float CalculateScaleMultiplier(EMotionFX::ActorInstance* instance) const;
void PrepareForMesh(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM);
AzFramework::DebugDisplayRequests* GetDebugDisplay(AzFramework::ViewportId viewportId);
void RenderAABB(EMotionFX::ActorInstance* instance, const AZ::Color& aabbColor);
void RenderLineSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor);
@@ -63,11 +69,18 @@ namespace AZ::Render
void RenderWireframe(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM, float wireframeScale, float scaleMultiplier,
const AZ::Color& wireframeColor);
void RenderJointNames(EMotionFX::ActorInstance* actorInstance, RPI::ViewportContextPtr viewportContext, const AZ::Color& jointNameColor);
void RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, AzFramework::DebugDisplayRequests* debugDisplay, float scale = 1.0f);
void RenderLineAxis(
AzFramework::DebugDisplayRequests* debugDisplay,
AZ::Transform worldTM, //!< The world space transformation matrix to visualize. */
float size, //!< The size value in units is used to control the scaling of the axis. */
bool selected, //!< Set to true if you want to render the axis using the selection color. */
bool renderAxisName = false);
EMotionFX::Mesh* m_currentMesh = nullptr; /**< A pointer to the mesh whose world space positions are in the pre-calculated positions buffer.
NULL in case we haven't pre-calculated any positions yet. */
AZStd::vector<AZ::Vector3> m_worldSpacePositions; /**< The buffer used to store world space positions for rendering normals
tangents and the wireframe. */
EMotionFX::Mesh* m_currentMesh = nullptr; //!< A pointer to the mesh whose world space positions are in the pre-calculated positions buffer.
//!< NULL in case we haven't pre-calculated any positions yet.
AZStd::vector<AZ::Vector3> m_worldSpacePositions; //!< The buffer used to store world space positions for rendering normals
//!< tangents and the wireframe.
static constexpr float BaseFontSize = 0.7f;
const Vector3 TopRightBorderPadding = AZ::Vector3(-40.0f, 22.0f, 0.0f);
@@ -75,6 +88,7 @@ namespace AZ::Render
RPI::AuxGeomFeatureProcessorInterface* m_auxGeomFeatureProcessor = nullptr;
AZStd::vector<AZ::Vector3> m_auxVertices;
AZStd::vector<AZ::Color> m_auxColors;
EntityId m_entityId;
AzFramework::TextDrawParameters m_drawParams;
AzFramework::FontDrawInterface* m_fontDrawInterface = nullptr;
@@ -46,8 +46,8 @@ namespace EMStudio
CreateViewOptionEntry(contextMenu, "Line Skeleton", EMotionFX::ActorRenderFlag::RENDER_LINESKELETON);
CreateViewOptionEntry(contextMenu, "Solid Skeleton", EMotionFX::ActorRenderFlag::RENDER_SKELETON);
CreateViewOptionEntry(contextMenu, "Joint Names", EMotionFX::ActorRenderFlag::RENDER_NODENAMES);
CreateViewOptionEntry(contextMenu, "Joint Orientations", EMotionFX::ActorRenderFlag::RENDER_NODEORIENTATION);
// [EMFX-TODO] Add those option once implemented.
// CreateViewOptionEntry(contextMenu, "Joint Orientations", EMotionFX::ActorRenderFlag::RENDER_NODEORIENTATION);
// CreateViewOptionEntry(contextMenu, "Actor Bind Pose", EMotionFX::ActorRenderFlag::RENDER_ACTORBINDPOSE);
contextMenu->addSeparator();
CreateViewOptionEntry(contextMenu, "Hit Detection Colliders", EMotionFX::ActorRenderFlag::RENDER_HITDETECTION_COLLIDERS);
@@ -55,13 +55,13 @@ namespace EMStudio
void AnimViewportWidget::Reinit(bool resetCamera)
{
m_renderer->Reinit();
m_renderer->UpdateActorRenderFlag(m_renderFlags);
if (resetCamera)
{
ResetCamera();
}
m_renderer->Reinit();
m_renderer->UpdateActorRenderFlag(m_renderFlags);
}
EMotionFX::ActorRenderFlagBitset AnimViewportWidget::GetRenderFlags() const
@@ -1063,6 +1063,7 @@ namespace EMStudio
settings.m_vertexNormalsScale = m_vertexNormalsScale;
settings.m_faceNormalsScale = m_faceNormalsScale;
settings.m_tangentsScale = m_tangentsScale;
settings.m_nodeOrientationScale = m_nodeOrientationScale;
settings.m_vertexNormalsColor = m_vertexNormalsColor;
settings.m_faceNormalsColor = m_faceNormalsColor;
@@ -1112,6 +1113,7 @@ namespace EMStudio
void RenderOptions::OnNodeOrientationScaleChangedCallback() const
{
PluginOptionsNotificationsBus::Event(s_nodeOrientationScaleOptionName, &PluginOptionsNotificationsBus::Events::OnOptionChanged, s_nodeOrientationScaleOptionName);
CopyToRenderActorSettings(EMotionFX::GetRenderActorSettings());
}
void RenderOptions::OnScaleBonesOnLengthChangedCallback() const
@@ -293,7 +293,7 @@ namespace MCore
// check if the test point is inside the polygon
AZ::Vector2 ClosestPointToPoly(const AZ::Vector2* polyPoints, size_t numPoints, const AZ::Vector2& testPoint)
{
AZ::Vector2 result;
AZ::Vector2 result = AZ::Vector2::CreateZero();
float closestDist = FLT_MAX;
for (size_t i = 0; i < numPoints; ++i)
{
@@ -71,8 +71,6 @@ namespace MysticQt
setWidget(m_rootSplitter);
}
// destructor
DialogStack::~DialogStack()
{
}
@@ -81,6 +79,14 @@ namespace MysticQt
// get rid of all dialogs and their allocated memory
void DialogStack::Clear()
{
for (Dialog& dialog : m_dialogs)
{
if (dialog.m_dialogWidget)
{
dialog.m_dialogWidget->deleteLater();
}
}
// destroy the dialogs
m_dialogs.clear();
@@ -679,6 +685,4 @@ namespace MysticQt
return;
}
}
} // namespace MysticQt
#include <MysticQt/Source/moc_DialogStack.cpp>
} // namespace MysticQt
@@ -6,10 +6,8 @@
*
*/
#ifndef __MYSTICQT_DIALOGSTACK_H
#define __MYSTICQT_DIALOGSTACK_H
#pragma once
//
#if !defined(Q_MOC_RUN)
#include "MysticQtConfig.h"
#include <QtWidgets/QWidget>
@@ -30,14 +28,10 @@ namespace MysticQt
{
class DialogStackSplitter;
/**
*
*
*/
class MYSTICQT_API DialogStack
: public QScrollArea
{
Q_OBJECT
Q_OBJECT // AUTOMOC
public:
DialogStack(QWidget* parent = nullptr);
@@ -89,5 +83,3 @@ namespace MysticQt
int32 m_prevMouseY;
};
} // namespace MysticQt
#endif
@@ -26,6 +26,7 @@ namespace AZ::Render
float m_faceNormalsScale = 1.0f;
float m_tangentsScale = 1.0f;
float m_wireframeScale = 1.0f;
float m_nodeOrientationScale = 1.0f;
AZ::Color m_hitDetectionColliderColor{0.44f, 0.44f, 0.44f, 1.0f};
AZ::Color m_selectedHitDetectionColliderColor{ 0.3f, 0.56f, 0.88f, 1.0f };
@@ -324,8 +324,6 @@ namespace GradientSignal
void GradientTransformComponent::TransformPositionToUVW(const AZ::Vector3& inPosition, AZ::Vector3& outUVW, const bool shouldNormalizeOutput, bool& wasPointRejected) const
{
AZ_PROFILE_FUNCTION(Entity);
AZStd::lock_guard<decltype(m_cacheMutex)> lock(m_cacheMutex);
//transforming coordinate into "local" relative space of shape bounds
@@ -191,8 +191,6 @@ namespace GradientSignal
float ImageGradientComponent::GetValue(const GradientSampleParams& sampleParams) const
{
AZ_PROFILE_FUNCTION(Entity);
AZ::Vector3 uvw = sampleParams.m_position;
bool wasPointRejected = false;
@@ -153,8 +153,6 @@ namespace GradientSignal
float GetValueFromImageAsset(const AZ::Data::Asset<ImageAsset>& imageAsset, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue)
{
AZ_PROFILE_FUNCTION(Entity);
if (imageAsset.IsReady())
{
const auto& image = imageAsset.Get();
@@ -19,7 +19,6 @@
#include <GraphCanvas/Components/StyleBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <GraphCanvas/Types/EntitySaveData.h>
#include <GraphCanvas/Types/TranslationTypes.h>
#include <Widgets/GraphCanvasLabel.h>
namespace GraphCanvas
+10 -1
View File
@@ -58,7 +58,6 @@
#include <GraphCanvas/Types/ConstructPresets.h>
#include <GraphCanvas/Types/EntitySaveData.h>
#include <GraphCanvas/Types/TranslationTypes.h>
#include <GraphCanvas/Widgets/GraphCanvasEditor/GraphCanvasAssetEditorMainWindow.h>
#include <GraphCanvas/Widgets/GraphCanvasMimeEvent.h>
@@ -386,6 +385,16 @@ namespace GraphCanvas
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::EnumerateAssets, nullptr, collectAssetsCb, postEnumerateCb);
}
void GraphCanvasSystemComponent::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId)
{
AZ::Data::AssetInfo assetInfo;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, assetId);
if (assetInfo.m_assetType == azrtti_typeid<TranslationAsset>())
{
GraphCanvas::TranslationRequestBus::Broadcast(&GraphCanvas::TranslationRequests::Restore);
}
}
void GraphCanvasSystemComponent::UnregisterAssetHandler()
{
if (m_assetHandler)
@@ -77,7 +77,10 @@ namespace GraphCanvas
AZ::EntityId CreateVirtualChild(const AZ::EntityId& real, const AZStd::string& virtualChildElement) const override;
////
// AzFramework::AssetCatalogEventBus::Handler
void OnCatalogLoaded(const char* /*catalogFile*/) override;
void OnCatalogAssetChanged(const AZ::Data::AssetId&) override;
////
AZStd::unique_ptr<TranslationAssetHandler> m_assetHandler;
@@ -59,14 +59,14 @@ namespace GraphCanvas
//!
//! Requirements:
//! - Must have a top level array called "entries"
//! - Must provide a "key" element for any entry added
//! - Must provide a "base" element for any entry added
//!
//! Example:
//!
//! {
//! "entries": [
//! {
//! "key": "Globals",
//! "base": "Globals",
//! "details": {
//! "name": "My Name",
//! "tooltip": "My Tooltip"
@@ -90,21 +90,21 @@ namespace GraphCanvas
//! Globals.details.somearray.0.name
//! Globals.details.somearray.1.name
//!
//! There is one important aspect however, if an element in an array has a "key" value, the value of this key
//! There is one important aspect however, if an element in an array has a "base" value, the value of this key
//! will replace the index. This is useful when the index and/or ordering of an entry is not relevant or may
//! change.
//!
//! "somearray": [ {
//! "name": "First one"
//! "key": "a_key"
//! "base": "a_key"
//! }, {
//! "name": "Second one",
//! "key": "b_key"
//! "base": "b_key"
//! } ]
//!
//! Globals.details.somearray.0.key == "a_key"
//! Globals.details.somearray.0.base == "a_key"
//! Globals.details.somearray.0.name == "First one"
//! Globals.details.somearray.1.key == "b_key"
//! Globals.details.somearray.1.base == "b_key"
//! Globals.details.somearray.1.name == "Second one"
//!
class TranslationAssetHandler
@@ -11,17 +11,6 @@
namespace GraphCanvas
{
namespace Schema
{
namespace Field
{
static constexpr char key[] = "key";
static constexpr char context[] = "context";
static constexpr char variant[] = "variant";
static constexpr char entries[] = "entries";
}
}
AZ_CLASS_ALLOCATOR_IMPL(TranslationFormatSerializer, AZ::SystemAllocator, 0);
void AddEntryToDatabase(const AZStd::string& baseKey, const AZStd::string& name, const rapidjson::Value& it, TranslationFormat* translationFormat)
@@ -76,11 +65,15 @@ namespace GraphCanvas
const rapidjson::Value& array = it;
for (rapidjson::SizeType i = 0; i < array.Size(); ++i)
{
// so, here, I need to go in and if there is a "key" member within the object, then I need to use that,
// if there isn't, I can use the %d
// if there is a "base" member within the object, then use it, otherwise use the index
if (array[i].IsObject())
{
if (array[i].HasMember(Schema::Field::key))
if (array[i].HasMember(Schema::Field::deprecated_key))
{
AZStd::string innerKey = array[i].FindMember(Schema::Field::deprecated_key)->value.GetString();
itemKey.append(AZStd::string::format(".%s", innerKey.c_str()));
}
else if (array[i].HasMember(Schema::Field::key))
{
AZStd::string innerKey = array[i].FindMember(Schema::Field::key)->value.GetString();
itemKey.append(AZStd::string::format(".%s", innerKey.c_str()));
@@ -133,7 +126,12 @@ namespace GraphCanvas
AZStd::string keyStr;
rapidjson::Value::ConstMemberIterator keyValue;
if (entry.HasMember(Schema::Field::key))
if (entry.HasMember(Schema::Field::deprecated_key))
{
keyValue = entry.FindMember(Schema::Field::deprecated_key);
keyStr = keyValue->value.GetString();
}
else if (entry.HasMember(Schema::Field::key))
{
keyValue = entry.FindMember(Schema::Field::key);
keyStr = keyValue->value.GetString();
@@ -23,4 +23,17 @@ namespace GraphCanvas
AZ::JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue,
const void* defaultValue, const AZ::Uuid& valueTypeId, AZ::JsonSerializerContext& context) override;
};
namespace Schema
{
namespace Field
{
// Moved away from "key" due to some strict filtering on secrets
static constexpr char deprecated_key[] = "key";
static constexpr char key[] = "base";
static constexpr char context[] = "context";
static constexpr char variant[] = "variant";
static constexpr char entries[] = "entries";
}
}
}
@@ -16,7 +16,6 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option")
AZ_POP_DISABLE_WARNING
#include <GraphCanvas/Styling/StyleHelper.h>
#include <GraphCanvas/Types/TranslationTypes.h>
namespace GraphCanvas
{
@@ -15,7 +15,6 @@
#include <GraphCanvas/Editor/EditorTypes.h>
#include <GraphCanvas/Types/EntitySaveData.h>
#include <GraphCanvas/Types/GraphCanvasGraphSerialization.h>
#include <GraphCanvas/Types/TranslationTypes.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
@@ -11,7 +11,6 @@
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/string/string.h>
#include <GraphCanvas/Types/TranslationTypes.h>
#include <GraphCanvas/Components/StyleBus.h>
#include <GraphCanvas/Types/SceneMemberComponentSaveData.h>
@@ -16,7 +16,6 @@
#include <GraphCanvas/Types/Endpoint.h>
#include <GraphCanvas/Types/Types.h>
#include <GraphCanvas/Types/TranslationTypes.h>
class QGraphicsLayoutItem;
@@ -1,116 +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
*
*/
#pragma once
#include <QCoreApplication>
#include <AzCore/Serialization/SerializeContext.h>
namespace GraphCanvas
{
struct TranslationKeyedString
{
public:
AZ_TYPE_INFO(TranslationKeyedString, "{B796685C-0335-4E74-9EF8-A1933E8B2142}");
AZ_CLASS_ALLOCATOR(TranslationKeyedString, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (!serializeContext)
{
return;
}
serializeContext->Class<TranslationKeyedString>()
->Version(1)
->Field("Fallback", &TranslationKeyedString::m_fallback)
->Field("Context", &TranslationKeyedString::m_context)
->Field("Key", &TranslationKeyedString::m_key)
;
}
TranslationKeyedString()
: m_dirtyText(true)
{
}
~TranslationKeyedString() = default;
TranslationKeyedString(const AZStd::string& fallback, const AZStd::string& context = AZStd::string(), const AZStd::string& key = AZStd::string())
: m_fallback(fallback)
, m_context(context)
, m_key(key)
, m_dirtyText(true)
{
}
const AZStd::string GetDisplayString() const
{
if (m_dirtyText)
{
const_cast<TranslationKeyedString*>(this)->TranslateString();
}
return m_display;
}
void TranslateString()
{
m_display = m_fallback;
if (!m_context.empty() && !m_key.empty())
{
AZStd::string translatedText = QCoreApplication::translate(m_context.c_str(), m_key.c_str()).toUtf8().data();
if (translatedText != m_key)
{
m_display = translatedText;
}
}
m_dirtyText = false;
}
bool empty() const
{
return m_fallback.empty() && (m_context.empty() || m_key.empty());
}
bool operator==(const TranslationKeyedString& other) const
{
return m_fallback == other.m_fallback
&& m_context == other.m_context
&& m_key == other.m_key
;
}
void Clear()
{
m_key.clear();
m_context.clear();
m_fallback.clear();
}
void SetFallback(const AZStd::string& fallback)
{
m_fallback = fallback;
m_dirtyText = true;
}
AZStd::string m_context;
AZStd::string m_key;
AZStd::string m_display;
private:
AZStd::string m_fallback;
bool m_dirtyText;
};
}
@@ -102,8 +102,7 @@ set(FILES
StaticLib/GraphCanvas/Types/GraphCanvasGraphData.h
StaticLib/GraphCanvas/Types/GraphCanvasGraphSerialization.cpp
StaticLib/GraphCanvas/Types/GraphCanvasGraphSerialization.h
StaticLib/GraphCanvas/Types/SceneMemberComponentSaveData.h
StaticLib/GraphCanvas/Types/TranslationTypes.h
StaticLib/GraphCanvas/Types/SceneMemberComponentSaveData.h
StaticLib/GraphCanvas/Types/Types.h
StaticLib/GraphCanvas/Types/QtMetaTypes.h
StaticLib/GraphCanvas/Widgets/Resources/default_style.json
+1 -1
View File
@@ -497,7 +497,7 @@ void CDraw2d::SetSortKey(int64_t key)
AZ::Vector2 CDraw2d::Align(AZ::Vector2 position, AZ::Vector2 size,
HAlign horizontalAlignment, VAlign verticalAlignment)
{
AZ::Vector2 result;
AZ::Vector2 result = AZ::Vector2::CreateZero();
switch (horizontalAlignment)
{
case HAlign::Left:
+1 -1
View File
@@ -4936,7 +4936,7 @@ AZStd::string UiTextComponent::GetLocalizedText([[maybe_unused]] const AZStd::st
////////////////////////////////////////////////////////////////////////////////////////////////////
AZ::Vector2 UiTextComponent::CalculateAlignedPositionWithYOffset(const UiTransformInterface::RectPoints& points)
{
AZ::Vector2 pos;
AZ::Vector2 pos = AZ::Vector2::CreateZero();
const DrawBatchLines& drawBatchLines = GetDrawBatchLines();
size_t numLinesOfText = drawBatchLines.batchLines.size();
-8
View File
@@ -182,14 +182,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
Gem::LmbrCentral
)
if(PAL_TRAIT_JOINTS_TYPED_TEST_CASE)
ly_add_source_properties(
SOURCES Tests/PhysXJointsTest.cpp
PROPERTY COMPILE_DEFINITIONS
VALUES ENABLE_JOINTS_TYPED_TEST_CASE
)
endif()
ly_add_googletest(
NAME Gem::PhysX.Tests
)
@@ -7,20 +7,20 @@
*/
#include "ColliderComponentMode.h"
#include "ColliderAssetScaleMode.h"
#include "ColliderBoxMode.h"
#include "ColliderCapsuleMode.h"
#include "ColliderOffsetMode.h"
#include "ColliderRotationMode.h"
#include "ColliderBoxMode.h"
#include "ColliderSphereMode.h"
#include "ColliderCapsuleMode.h"
#include "ColliderAssetScaleMode.h"
#include <Editor/Source/ComponentModes/PhysXSubComponentModeBase.h>
#include <PhysX/EditorColliderComponentRequestBus.h>
#include <AzFramework/Physics/ShapeConfiguration.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/ComponentModes/BoxComponentMode.h>
#include <AzToolsFramework/ComponentModes/BoxViewportEdit.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
namespace PhysX
{
@@ -31,7 +31,7 @@ namespace PhysX
const AZ::Crc32 SetOffsetSubModeActionUri = AZ_CRC("com.o3de.action.physx.setoffsetsubmode", 0xc06132e5);
const AZ::Crc32 SetRotationSubModeActionUri = AZ_CRC("com.o3de.action.physx.setrotationsubmode", 0xc4225918);
const AZ::Crc32 ResetSubModeActionUri = AZ_CRC("com.o3de.action.physx.resetsubmode", 0xb70b120e);
}
} // namespace
AZ_CLASS_ALLOCATOR_IMPL(ColliderComponentMode, AZ::SystemAllocator, 0);
@@ -39,19 +39,17 @@ namespace PhysX
: AzToolsFramework::ComponentModeFramework::EditorBaseComponentMode(entityComponentIdPair, componentType)
{
CreateSubModes();
CreateSubModeSelectionCluster();
ColliderComponentModeRequestBus::Handler::BusConnect(entityComponentIdPair);
ColliderComponentModeUiRequestBus::Handler::BusConnect(entityComponentIdPair);
CreateSubModeSelectionCluster();
}
ColliderComponentMode::~ColliderComponentMode()
{
RemoveSubModeSelectionCluster();
ColliderComponentModeUiRequestBus::Handler::BusDisconnect();
ColliderComponentModeRequestBus::Handler::BusDisconnect();
RemoveSubModeSelectionCluster();
m_subModes[m_subMode]->Teardown(GetEntityComponentIdPair());
}
@@ -62,39 +60,41 @@ namespace PhysX
AZStd::vector<AzToolsFramework::ActionOverride> ColliderComponentMode::PopulateActionsImpl()
{
AzToolsFramework::ActionOverride setDimensionsModeAction;
setDimensionsModeAction.SetUri(SetDimensionsSubModeActionUri);
setDimensionsModeAction.SetKeySequence(QKeySequence(Qt::Key_1));
setDimensionsModeAction.SetTitle("Set Resize Mode");
setDimensionsModeAction.SetTip("Set resize mode");
setDimensionsModeAction.SetEntityComponentIdPair(GetEntityComponentIdPair());
setDimensionsModeAction.SetCallback([this]()
{
SetCurrentMode(SubMode::Dimensions);
});
AzToolsFramework::ActionOverride setOffsetModeAction;
setOffsetModeAction.SetUri(SetOffsetSubModeActionUri);
setOffsetModeAction.SetKeySequence(QKeySequence(Qt::Key_2));
setOffsetModeAction.SetKeySequence(QKeySequence(Qt::Key_1));
setOffsetModeAction.SetTitle("Set Offset Mode");
setOffsetModeAction.SetTip("Set offset mode");
setOffsetModeAction.SetEntityComponentIdPair(GetEntityComponentIdPair());
setOffsetModeAction.SetCallback([this]()
{
SetCurrentMode(SubMode::Offset);
});
setOffsetModeAction.SetCallback(
[this]()
{
SetCurrentMode(SubMode::Offset);
});
AzToolsFramework::ActionOverride setRotationModeAction;
setRotationModeAction.SetUri(SetRotationSubModeActionUri);
setRotationModeAction.SetKeySequence(QKeySequence(Qt::Key_3));
setRotationModeAction.SetKeySequence(QKeySequence(Qt::Key_2));
setRotationModeAction.SetTitle("Set Rotation Mode");
setRotationModeAction.SetTip("Set rotation mode");
setRotationModeAction.SetEntityComponentIdPair(GetEntityComponentIdPair());
setRotationModeAction.SetCallback([this]()
{
SetCurrentMode(SubMode::Rotation);
});
setRotationModeAction.SetCallback(
[this]()
{
SetCurrentMode(SubMode::Rotation);
});
AzToolsFramework::ActionOverride setDimensionsModeAction;
setDimensionsModeAction.SetUri(SetDimensionsSubModeActionUri);
setDimensionsModeAction.SetKeySequence(QKeySequence(Qt::Key_3));
setDimensionsModeAction.SetTitle("Set Resize Mode");
setDimensionsModeAction.SetTip("Set resize mode");
setDimensionsModeAction.SetEntityComponentIdPair(GetEntityComponentIdPair());
setDimensionsModeAction.SetCallback(
[this]()
{
SetCurrentMode(SubMode::Dimensions);
});
AzToolsFramework::ActionOverride resetModeAction;
resetModeAction.SetUri(ResetSubModeActionUri);
@@ -102,12 +102,13 @@ namespace PhysX
resetModeAction.SetTitle("Reset Current Mode");
resetModeAction.SetTip("Reset current mode");
resetModeAction.SetEntityComponentIdPair(GetEntityComponentIdPair());
resetModeAction.SetCallback([this]()
{
ResetCurrentMode();
});
resetModeAction.SetCallback(
[this]()
{
ResetCurrentMode();
});
return {setDimensionsModeAction, setOffsetModeAction, setRotationModeAction, resetModeAction };
return { setDimensionsModeAction, setOffsetModeAction, setRotationModeAction, resetModeAction };
}
void ColliderComponentMode::CreateSubModes()
@@ -141,7 +142,7 @@ namespace PhysX
if (mouseInteraction.m_mouseEvent == AzToolsFramework::ViewportInteraction::MouseEvent::Wheel &&
mouseInteraction.m_mouseInteraction.m_keyboardModifiers.Ctrl())
{
int direction = MouseWheelDelta(mouseInteraction) > 0.0f ? 1 : -1;
const int direction = MouseWheelDelta(mouseInteraction) > 0.0f ? -1 : 1;
AZ::u32 currentModeIndex = static_cast<AZ::u32>(m_subMode);
AZ::u32 numSubModes = static_cast<AZ::u32>(SubMode::NumModes);
AZ::u32 nextModeIndex = (currentModeIndex + numSubModes + direction) % m_subModes.size();
@@ -159,10 +160,17 @@ namespace PhysX
void ColliderComponentMode::SetCurrentMode(SubMode newMode)
{
AZ_Assert(m_subModes.count(newMode) > 0, "Submode not found:%d", newMode);
AZ_Assert(m_subModes.find(newMode) != m_subModes.end(), "Submode not found:%d", newMode);
m_subModes[m_subMode]->Teardown(GetEntityComponentIdPair());
m_subMode = newMode;
m_subModes[m_subMode]->Setup(GetEntityComponentIdPair());
const auto modeIndex = static_cast<size_t>(newMode);
AZ_Assert(modeIndex < m_buttonIds.size(), "Invalid mode index %i.", modeIndex);
AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
AzToolsFramework::ViewportUi::DefaultViewportId,
&AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterActiveButton, m_modeSelectionClusterId,
m_buttonIds[modeIndex]);
}
AzToolsFramework::ViewportUi::ClusterId ColliderComponentMode::GetClusterId() const
@@ -172,36 +180,40 @@ namespace PhysX
AzToolsFramework::ViewportUi::ButtonId ColliderComponentMode::GetOffsetButtonId() const
{
return m_offsetModeButtonId;
return m_buttonIds[static_cast<size_t>(SubMode::Offset)];
}
AzToolsFramework::ViewportUi::ButtonId ColliderComponentMode::GetRotationButtonId() const
{
return m_rotationModeButtonId;
return m_buttonIds[static_cast<size_t>(SubMode::Rotation)];
}
AzToolsFramework::ViewportUi::ButtonId ColliderComponentMode::GetDimensionsButtonId() const
{
return m_dimensionsModeButtonId;
return m_buttonIds[static_cast<size_t>(SubMode::Dimensions)];
}
AZStd::string ColliderComponentMode::GetComponentModeName() const
{
return "Collider Edit Mode";
}
void RefreshUI()
{
/// The reason this is in a free function is because ColliderComponentMode
/// privately inherits from ToolsApplicationNotificationBus. Trying to invoke
/// the bus inside the class scope causes the compiler to complain it's not accessible
/// to due private inheritence.
/// Using the global namespace operator :: should have fixed that, except there
/// the bus inside the class scope causes the compiler to complain it's not accessible
/// to due private inheritence.
/// Using the global namespace operator :: should have fixed that, except there
/// is a bug in the microsoft compiler meaning it doesn't work. So this is a work around.
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(
&AzToolsFramework::ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay,
AzToolsFramework::Refresh_Values);
&AzToolsFramework::ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay, AzToolsFramework::Refresh_Values);
}
void ColliderComponentMode::ResetCurrentMode()
{
m_subModes[m_subMode]->ResetValues(GetEntityComponentIdPair());
m_subModes[m_subMode]->Refresh(GetEntityComponentIdPair());
m_subModes[m_subMode]->Refresh(GetEntityComponentIdPair());
RefreshUI();
}
@@ -225,8 +237,8 @@ namespace PhysX
void ColliderComponentMode::RemoveSubModeSelectionCluster()
{
AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
AzToolsFramework::ViewportUi::DefaultViewportId,
&AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RemoveCluster, m_modeSelectionClusterId);
AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RemoveCluster,
m_modeSelectionClusterId);
}
void ColliderComponentMode::CreateSubModeSelectionCluster()
@@ -237,29 +249,37 @@ namespace PhysX
&AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateCluster, AzToolsFramework::ViewportUi::Alignment::TopLeft);
// create and register the buttons
m_dimensionsModeButtonId = RegisterClusterButton(m_modeSelectionClusterId, "Scale");
m_offsetModeButtonId = RegisterClusterButton(m_modeSelectionClusterId, "Move");
m_rotationModeButtonId = RegisterClusterButton(m_modeSelectionClusterId, "Rotate");
m_buttonIds.resize(static_cast<size_t>(SubMode::NumModes));
m_buttonIds[static_cast<size_t>(SubMode::Offset)] = RegisterClusterButton(m_modeSelectionClusterId, "Move");
m_buttonIds[static_cast<size_t>(SubMode::Rotation)] = RegisterClusterButton(m_modeSelectionClusterId, "Rotate");
m_buttonIds[static_cast<size_t>(SubMode::Dimensions)] = RegisterClusterButton(m_modeSelectionClusterId, "Scale");
const auto onButtonClicked = [this](AzToolsFramework::ViewportUi::ButtonId buttonId) {
if (buttonId == m_dimensionsModeButtonId)
{
SetCurrentMode(SubMode::Dimensions);
}
else if (buttonId == m_offsetModeButtonId)
SetCurrentMode(SubMode::Offset);
const auto onButtonClicked = [this](AzToolsFramework::ViewportUi::ButtonId buttonId)
{
if (buttonId == m_buttonIds[static_cast<size_t>(SubMode::Offset)])
{
SetCurrentMode(SubMode::Offset);
}
else if (buttonId == m_rotationModeButtonId)
else if (buttonId == m_buttonIds[static_cast<size_t>(SubMode::Rotation)])
{
SetCurrentMode(SubMode::Rotation);
}
else if (buttonId == m_buttonIds[static_cast<size_t>(SubMode::Dimensions)])
{
SetCurrentMode(SubMode::Dimensions);
}
else
{
AZ_Error("PhysX Collider Component Mode", false, "Unrecognized button ID.");
}
};
m_modeSelectionHandler = AZ::Event<AzToolsFramework::ViewportUi::ButtonId>::Handler(onButtonClicked);
AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
AzToolsFramework::ViewportUi::DefaultViewportId,
&AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RegisterClusterEventHandler,
m_modeSelectionClusterId, m_modeSelectionHandler);
&AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RegisterClusterEventHandler, m_modeSelectionClusterId,
m_modeSelectionHandler);
}
}
} // namespace PhysX
@@ -31,21 +31,23 @@ namespace PhysX
ColliderComponentMode(const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType);
~ColliderComponentMode();
// EditorBaseComponentMode ...
// EditorBaseComponentMode overrides ...
void Refresh() override;
AZStd::vector<AzToolsFramework::ActionOverride> PopulateActionsImpl() override;
AZStd::vector<AzToolsFramework::ViewportUi::ClusterId> PopulateViewportUiImpl() override;
// ColliderComponentModeBus ...
// ColliderComponentModeBus overrides ...
SubMode GetCurrentMode() override;
void SetCurrentMode(SubMode index) override;
// ColliderComponentModeUiBus ...
// ColliderComponentModeUiBus overrides ...
AzToolsFramework::ViewportUi::ButtonId GetOffsetButtonId() const override;
AzToolsFramework::ViewportUi::ButtonId GetRotationButtonId() const override;
AzToolsFramework::ViewportUi::ClusterId GetClusterId() const override;
AzToolsFramework::ViewportUi::ButtonId GetDimensionsButtonId() const override;
// ComponentMode overrides ...
AZStd::string GetComponentModeName() const override;
private:
// AzToolsFramework::ViewportInteraction::ViewportSelectionRequests ...
@@ -63,12 +65,9 @@ namespace PhysX
AzToolsFramework::ViewportUi::ClusterId
m_modeSelectionClusterId; //!< Viewport UI cluster for changing sub mode.
AzToolsFramework::ViewportUi::ButtonId
m_dimensionsModeButtonId; //!< Id of the Viewport UI button for resize/dimensions mode.
AzToolsFramework::ViewportUi::ButtonId
m_offsetModeButtonId; //!< Id of the Viewport UI button for offset mode.
AzToolsFramework::ViewportUi::ButtonId
m_rotationModeButtonId; //!< Id of the Viewport UI button for rotation mode.
AZStd::vector<AzToolsFramework::ViewportUi::ButtonId> m_buttonIds; //!< Ids for the Viewport UI buttons for each mode.
AZ::Event<AzToolsFramework::ViewportUi::ButtonId>::Handler
m_modeSelectionHandler; //!< Event handler for sub mode changes.
};
@@ -19,9 +19,9 @@ namespace PhysX
public:
enum class SubMode : AZ::u32
{
Dimensions,
Offset,
Rotation,
Dimensions,
NumModes
};
@@ -760,7 +760,7 @@ namespace PhysX
if (asset == m_shapeConfiguration.m_physicsAsset.m_pxAsset)
{
m_shapeConfiguration.m_physicsAsset.m_pxAsset = asset;
m_shapeConfiguration.m_physicsAsset.m_configuration.m_asset = m_shapeConfiguration.m_physicsAsset.m_pxAsset;
m_shapeConfiguration.m_physicsAsset.m_configuration.m_asset = asset;
UpdateMaterialSlotsFromMeshAsset();
CreateStaticEditorCollider();
@@ -785,7 +785,9 @@ namespace PhysX
{
const PhysX::EditorRigidBodyComponent* entityRigidbody = m_entity->FindComponent<PhysX::EditorRigidBodyComponent>();
if (m_shapeConfiguration.m_physicsAsset.m_pxAsset && (m_shapeConfiguration.m_shapeType == Physics::ShapeType::PhysicsAsset) && entityRigidbody)
if (entityRigidbody &&
m_shapeConfiguration.m_shapeType == Physics::ShapeType::PhysicsAsset &&
m_shapeConfiguration.m_physicsAsset.m_pxAsset.IsReady())
{
AZStd::vector<AZStd::shared_ptr<Physics::Shape>> shapes;
Utils::GetShapesFromAsset(m_shapeConfiguration.m_physicsAsset.m_configuration, m_configuration, m_hasNonUniformScale,
@@ -7,5 +7,3 @@
#
set(PAL_TRAIT_PHYSX_SUPPORTED TRUE)
set(PAL_TRAIT_JOINTS_TYPED_TEST_CASE FALSE)
@@ -7,7 +7,6 @@
#
set(PAL_TRAIT_PHYSX_SUPPORTED TRUE)
set(PAL_TRAIT_JOINTS_TYPED_TEST_CASE FALSE)
if(PAL_TRAIT_BUILD_HOST_TOOLS)
ly_associate_package(PACKAGE_NAME poly2tri-7f0487a-rev1-linux TARGETS poly2tri PACKAGE_HASH b16eef8f0bc469de0e3056d28d7484cf42659667e39b68b239f0d3a4cbb533d0)

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