@@ -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)
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
+7
-2
@@ -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)
|
||||
|
||||
+11
-10
@@ -95,7 +95,8 @@ def EntityOutliner_EntityOrdering():
|
||||
entity_outliner_model.dropMimeData(
|
||||
mime_data, QtCore.Qt.MoveAction, target_row, 0, target_index.parent()
|
||||
)
|
||||
QtWidgets.QApplication.processEvents()
|
||||
# Wait after move to let events (i.e. prefab propagation) process
|
||||
general.idle_wait(1.0)
|
||||
|
||||
# Move an entity before another entity in the order by dragging the source above the target
|
||||
move_entity_before = lambda source_name, target_name: _move_entity(
|
||||
@@ -119,24 +120,24 @@ def EntityOutliner_EntityOrdering():
|
||||
|
||||
# Our new entity should be given a name with a number automatically
|
||||
new_entity = f"Entity{i+1}"
|
||||
# The new entity should be added to the top of its parent entity
|
||||
expected_order = [new_entity] + expected_order
|
||||
# The new entity should be added to the bottom of its parent entity
|
||||
expected_order = expected_order + [new_entity]
|
||||
|
||||
verify_entities_sorted(expected_order)
|
||||
|
||||
# 3) Move "Entity1" to the top of the order
|
||||
move_entity_before("Entity1", "Entity5")
|
||||
expected_order = ["Entity1", "Entity5", "Entity4", "Entity3", "Entity2"]
|
||||
# 3) Move "Entity5" to the top of the order
|
||||
move_entity_before("Entity5", "Entity1")
|
||||
expected_order = ["Entity5", "Entity1", "Entity2", "Entity3", "Entity4"]
|
||||
verify_entities_sorted(expected_order)
|
||||
|
||||
# 4) Move "Entity4" to the bottom of the order
|
||||
move_entity_after("Entity4", "Entity2")
|
||||
expected_order = ["Entity1", "Entity5", "Entity3", "Entity2", "Entity4"]
|
||||
# 4) Move "Entity2" to the bottom of the order
|
||||
move_entity_after("Entity2", "Entity4")
|
||||
expected_order = ["Entity5", "Entity1", "Entity3", "Entity4", "Entity2"]
|
||||
verify_entities_sorted(expected_order)
|
||||
|
||||
# 5) Add another new entity, ensure the rest of the order is unchanged
|
||||
create_entity()
|
||||
expected_order = ["Entity6", "Entity1", "Entity5", "Entity3", "Entity2", "Entity4"]
|
||||
expected_order = ["Entity5", "Entity1", "Entity3", "Entity4", "Entity2", "Entity6"]
|
||||
verify_entities_sorted(expected_order)
|
||||
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+13
-13
@@ -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)
|
||||
|
||||
+2
@@ -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)
|
||||
|
||||
+2
@@ -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
|
||||
|
||||
|
||||
+22
-22
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,7 @@ ly_add_source_properties(
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
VALUES
|
||||
O3DE_COPYRIGHT_YEAR=${LY_VERSION_COPYRIGHT_YEAR}
|
||||
LY_BUILD=${LY_VERSION_BUILD_NUMBER}
|
||||
LY_VERSION_BUILD_NUMBER=${LY_VERSION_BUILD_NUMBER}
|
||||
${LY_PAL_TOOLS_DEFINES}
|
||||
)
|
||||
ly_add_source_properties(
|
||||
|
||||
@@ -911,13 +911,9 @@ namespace
|
||||
QWidget* g_splashScreen = nullptr;
|
||||
}
|
||||
|
||||
QString FormatVersion(const SFileVersion& v)
|
||||
QString FormatVersion([[maybe_unused]] const SFileVersion& v)
|
||||
{
|
||||
#if defined(LY_BUILD)
|
||||
return QObject::tr("Version %1.%2.%3.%4 - Build %5").arg(v[3]).arg(v[2]).arg(v[1]).arg(v[0]).arg(LY_BUILD);
|
||||
#else
|
||||
return QObject::tr("Version %1.%2.%3.%4").arg(v[3]).arg(v[2]).arg(v[1]).arg(v[0]);
|
||||
#endif
|
||||
return QObject::tr("Version %1").arg(LY_VERSION_BUILD_NUMBER);
|
||||
}
|
||||
|
||||
QString FormatRichTextCopyrightNotice()
|
||||
|
||||
@@ -130,10 +130,11 @@ namespace AZStd::Internal
|
||||
|
||||
|
||||
//! Constructors
|
||||
constexpr fixed_trivial_storage() = default;
|
||||
fixed_trivial_storage() = default;
|
||||
|
||||
template <typename U, typename = enable_if_t<is_convertible_v<U, T>>>
|
||||
constexpr fixed_trivial_storage(AZStd::initializer_list<U> ilist) noexcept
|
||||
fixed_trivial_storage(AZStd::initializer_list<U> ilist) noexcept
|
||||
: m_size(aznumeric_caster(ilist.size()))
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(ilist.size() <= capacity(), "Initializer list cannot be larger than storage capacity");
|
||||
size_t index{};
|
||||
@@ -141,20 +142,19 @@ namespace AZStd::Internal
|
||||
{
|
||||
m_data[index++] = element;
|
||||
}
|
||||
resize_no_construct(ilist.size());
|
||||
}
|
||||
|
||||
constexpr pointer data() noexcept
|
||||
pointer data() noexcept
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
constexpr const_pointer data() const noexcept
|
||||
const_pointer data() const noexcept
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
//! Number of elements currently stored.
|
||||
constexpr size_type size() const noexcept
|
||||
size_type size() const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
@@ -164,12 +164,12 @@ namespace AZStd::Internal
|
||||
return Capacity;
|
||||
}
|
||||
//! Is the storage empty?
|
||||
constexpr bool empty() const noexcept
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
//! Is the storage full?
|
||||
constexpr bool full() const noexcept
|
||||
bool full() const noexcept
|
||||
{
|
||||
return size() == capacity();
|
||||
}
|
||||
@@ -186,7 +186,7 @@ namespace AZStd::Internal
|
||||
//! Increases size of the storage by one.
|
||||
//! Always fails for empty storage.
|
||||
template <typename... Args, typename = enable_if_t<is_constructible_v<T, Args...>>>
|
||||
constexpr reference emplace_back(Args&&... args) noexcept
|
||||
reference emplace_back(Args&&... args) noexcept
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(!full(), "emplace_back cannot be invoked on full storage");
|
||||
reference new_element = *(data() + size());
|
||||
@@ -196,7 +196,7 @@ namespace AZStd::Internal
|
||||
}
|
||||
//! Removes the last element of the storage.
|
||||
//! Precondition: size is not empty
|
||||
constexpr void pop_back() noexcept
|
||||
void pop_back() noexcept
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(!empty(), "pop_back cannot be invoked on empty storage");
|
||||
resize_no_construct(size() - 1);
|
||||
@@ -205,7 +205,7 @@ namespace AZStd::Internal
|
||||
//! removing elements (unsafe).
|
||||
//!
|
||||
//! Updates the size of the container while checking that the new size is less than capacity
|
||||
constexpr void resize_no_construct(size_t new_size) noexcept
|
||||
void resize_no_construct(size_t new_size) noexcept
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(new_size <= capacity(), "New size cannot be larger than capacity");
|
||||
m_size = aznumeric_cast<size_type>(new_size);
|
||||
@@ -215,19 +215,19 @@ namespace AZStd::Internal
|
||||
//! This does not modify the size of the storage
|
||||
//! This is a no-op for trivial types
|
||||
template <typename InputIt, typename = enable_if_t<Internal::is_input_iterator_v<InputIt>>>
|
||||
constexpr void unsafe_destroy(InputIt, InputIt) noexcept
|
||||
void unsafe_destroy(InputIt, InputIt) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructs all elements of the storage.
|
||||
//! This does not modify the size of the storage
|
||||
//! This is a no-op for trivial types
|
||||
constexpr void unsafe_destroy_all() noexcept
|
||||
void unsafe_destroy_all() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
T m_data[Capacity]{};
|
||||
T m_data[Capacity];
|
||||
size_type m_size{};
|
||||
};
|
||||
|
||||
@@ -245,7 +245,7 @@ namespace AZStd::Internal
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
|
||||
constexpr fixed_non_trivial_storage() = default;
|
||||
fixed_non_trivial_storage() = default;
|
||||
|
||||
~fixed_non_trivial_storage() noexcept
|
||||
{
|
||||
@@ -253,7 +253,7 @@ namespace AZStd::Internal
|
||||
}
|
||||
|
||||
template <typename U, typename = enable_if_t<is_convertible_v<U, T>>>
|
||||
constexpr fixed_non_trivial_storage(AZStd::initializer_list<U> ilist) noexcept(noexcept(emplace_back(AZStd::declval<U>())))
|
||||
fixed_non_trivial_storage(AZStd::initializer_list<U> ilist) noexcept(noexcept(emplace_back(AZStd::declval<U>())))
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(ilist.size() <= capacity(), "Initializer list cannot be larger than storage capacity");
|
||||
for (const U& element : ilist)
|
||||
@@ -272,7 +272,7 @@ namespace AZStd::Internal
|
||||
}
|
||||
|
||||
//! Number of elements currently stored.
|
||||
constexpr size_type size() const noexcept
|
||||
size_type size() const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
@@ -282,12 +282,12 @@ namespace AZStd::Internal
|
||||
return Capacity;
|
||||
}
|
||||
//! Is the storage empty?
|
||||
constexpr bool empty() const noexcept
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
//! Is the storage full?
|
||||
constexpr bool full() const noexcept
|
||||
bool full() const noexcept
|
||||
{
|
||||
return size() == capacity();
|
||||
}
|
||||
@@ -325,7 +325,7 @@ namespace AZStd::Internal
|
||||
//! removing elements (unsafe).
|
||||
//!
|
||||
//! Updates the size of the container while checking that the new size is less than capacity
|
||||
constexpr void resize_no_construct(size_t new_size) noexcept
|
||||
void resize_no_construct(size_t new_size) noexcept
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(new_size <= capacity(), "New size cannot be larger than capacity");
|
||||
m_size = aznumeric_cast<size_type>(new_size);
|
||||
@@ -402,23 +402,23 @@ namespace AZStd
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// 23.2.4.1 construct/copy/destroy
|
||||
constexpr fixed_vector() = default;
|
||||
fixed_vector() = default;
|
||||
|
||||
constexpr explicit fixed_vector(size_type numElements, const_reference value = value_type())
|
||||
explicit fixed_vector(size_type numElements, const_reference value = value_type())
|
||||
{
|
||||
resize_no_construct(numElements);
|
||||
AZStd::uninitialized_fill_n(data(), numElements, value);
|
||||
}
|
||||
|
||||
template <class InputIt, typename = AZStd::enable_if_t<Internal::is_input_iterator_v<InputIt>>>
|
||||
constexpr fixed_vector(InputIt first, InputIt last)
|
||||
fixed_vector(InputIt first, InputIt last)
|
||||
{
|
||||
resize_no_construct(AZStd::distance(first, last));
|
||||
AZStd::uninitialized_copy(first, last, data());
|
||||
}
|
||||
|
||||
|
||||
constexpr fixed_vector(const fixed_vector& rhs)
|
||||
fixed_vector(const fixed_vector& rhs)
|
||||
{
|
||||
resize_no_construct(rhs.size());
|
||||
AZStd::uninitialized_copy(rhs.data(), rhs.data() + rhs.size(), data());
|
||||
@@ -428,7 +428,7 @@ namespace AZStd
|
||||
// It performs an AZStd::move on each of the fixed_vector elements instead
|
||||
// of swapping pointers to the allocted memory address
|
||||
// as it is unable to perform that operations due to the storage being baked into the container
|
||||
constexpr fixed_vector(fixed_vector&& rhs)
|
||||
fixed_vector(fixed_vector&& rhs)
|
||||
{
|
||||
resize_no_construct(rhs.size());
|
||||
AZStd::uninitialized_move(rhs.data(), rhs.data() + rhs.size(), data());
|
||||
@@ -440,7 +440,7 @@ namespace AZStd
|
||||
// into a fixed_vector given that the type in question isn't the same type as this fixed_vector type
|
||||
template <typename VectorContainer, typename = AZStd::enable_if_t<!AZStd::is_same_v<VectorContainer, fixed_vector>
|
||||
&& !AZStd::is_convertible_v<VectorContainer, size_type>>>
|
||||
constexpr fixed_vector(VectorContainer&& rhs)
|
||||
fixed_vector(VectorContainer&& rhs)
|
||||
{
|
||||
constexpr bool is_const_or_lvalue_reference = AZStd::is_lvalue_reference_v<VectorContainer>
|
||||
|| AZStd::is_const_v<VectorContainer>;
|
||||
@@ -459,12 +459,12 @@ namespace AZStd
|
||||
}
|
||||
}
|
||||
|
||||
constexpr fixed_vector(AZStd::initializer_list<value_type> ilist)
|
||||
fixed_vector(AZStd::initializer_list<value_type> ilist)
|
||||
: base_type(ilist)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr fixed_vector& operator=(const fixed_vector& rhs)
|
||||
fixed_vector& operator=(const fixed_vector& rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
{
|
||||
@@ -475,7 +475,7 @@ namespace AZStd
|
||||
return assign_helper(rhs);
|
||||
}
|
||||
|
||||
constexpr fixed_vector& operator=(fixed_vector&& rhs)
|
||||
fixed_vector& operator=(fixed_vector&& rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
{
|
||||
@@ -487,23 +487,23 @@ namespace AZStd
|
||||
}
|
||||
|
||||
template <typename VectorContainer>
|
||||
constexpr AZStd::enable_if_t<!AZStd::is_same_v<AZStd::remove_cvref_t<VectorContainer>, fixed_vector>, fixed_vector>& operator=(VectorContainer&& rhs)
|
||||
AZStd::enable_if_t<!AZStd::is_same_v<AZStd::remove_cvref_t<VectorContainer>, fixed_vector>, fixed_vector>& operator=(VectorContainer&& rhs)
|
||||
{
|
||||
return assign_helper(AZStd::forward<VectorContainer>(rhs));
|
||||
}
|
||||
|
||||
constexpr iterator begin() { return iterator(data()); }
|
||||
constexpr const_iterator begin() const { return const_iterator(data()); }
|
||||
constexpr const_iterator cbegin() const { return const_iterator(data()); }
|
||||
constexpr iterator end() { return iterator(data() + size()); }
|
||||
constexpr const_iterator end() const { return const_iterator(data() + size()); }
|
||||
constexpr const_iterator cend() const { return const_iterator(data() + size()); }
|
||||
constexpr reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
constexpr const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
|
||||
constexpr const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
|
||||
constexpr reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
constexpr const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
|
||||
constexpr const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
|
||||
iterator begin() { return iterator(data()); }
|
||||
const_iterator begin() const { return const_iterator(data()); }
|
||||
const_iterator cbegin() const { return const_iterator(data()); }
|
||||
iterator end() { return iterator(data() + size()); }
|
||||
const_iterator end() const { return const_iterator(data() + size()); }
|
||||
const_iterator cend() const { return const_iterator(data() + size()); }
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
|
||||
const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
|
||||
const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
|
||||
|
||||
// bring in fixed_vector_storage functions into scope
|
||||
using base_type::data;
|
||||
@@ -514,7 +514,7 @@ namespace AZStd
|
||||
// extension method
|
||||
using base_type::resize_no_construct;
|
||||
|
||||
constexpr size_type size() const noexcept
|
||||
size_type size() const noexcept
|
||||
{
|
||||
return base_type::size();
|
||||
}
|
||||
@@ -527,12 +527,12 @@ namespace AZStd
|
||||
return base_type::max_size();
|
||||
}
|
||||
|
||||
constexpr void resize(size_type newSize)
|
||||
void resize(size_type newSize)
|
||||
{
|
||||
return resize(newSize, value_type{});
|
||||
}
|
||||
|
||||
constexpr void resize(size_type newSize, const_reference value)
|
||||
void resize(size_type newSize, const_reference value)
|
||||
{
|
||||
size_type dataSize = size();
|
||||
if (dataSize < newSize)
|
||||
@@ -547,7 +547,7 @@ namespace AZStd
|
||||
|
||||
// Removes unused capacity - For fixed_vector this only asserts
|
||||
// that the supplied capacity is not longer than the fixed_vector capacity
|
||||
constexpr void reserve(size_type newCapacity)
|
||||
void reserve(size_type newCapacity)
|
||||
{
|
||||
// No-op - Implemented to provide consistent std::vector
|
||||
AZSTD_CONTAINER_ASSERT(newCapacity <= capacity(),
|
||||
@@ -556,79 +556,79 @@ namespace AZStd
|
||||
}
|
||||
|
||||
// Removes unused capacity - For fixed_vector this does nothing
|
||||
constexpr void shrink_to_fit()
|
||||
void shrink_to_fit()
|
||||
{
|
||||
// No-op - Implemented to provide consistent std::vector
|
||||
}
|
||||
|
||||
constexpr reference at(size_type position)
|
||||
reference at(size_type position)
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(position < size(), "AZStd::fixed_vector<>::at - position is out of range");
|
||||
return *(data() + position);
|
||||
}
|
||||
constexpr const_reference at(size_type position) const
|
||||
const_reference at(size_type position) const
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(position < size(), "AZStd::fixed_vector<>::at - position is out of range");
|
||||
return *(data() + position);
|
||||
}
|
||||
|
||||
constexpr reference operator[](size_type position)
|
||||
reference operator[](size_type position)
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(position < size(), "AZStd::fixed_vector<>::at - position is out of range");
|
||||
return *(data() + position);
|
||||
}
|
||||
constexpr const_reference operator[](size_type position) const
|
||||
const_reference operator[](size_type position) const
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(position < size(), "AZStd::fixed_vector<>::at - position is out of range");
|
||||
return *(data() + position);
|
||||
}
|
||||
|
||||
constexpr reference front()
|
||||
reference front()
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::front - container is empty!");
|
||||
return *data();
|
||||
}
|
||||
constexpr const_reference front() const
|
||||
const_reference front() const
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::front - container is empty!");
|
||||
return *data();
|
||||
}
|
||||
constexpr reference back()
|
||||
reference back()
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::back - container is empty!");
|
||||
return *(data() + size() - 1);
|
||||
}
|
||||
constexpr const_reference back() const
|
||||
const_reference back() const
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::back - container is empty!");
|
||||
return *(data() + size() - 1);
|
||||
}
|
||||
|
||||
constexpr void push_back(const_reference value)
|
||||
void push_back(const_reference value)
|
||||
{
|
||||
emplace_back(value);
|
||||
}
|
||||
|
||||
constexpr void assign(size_type numElements, const_reference value)
|
||||
void assign(size_type numElements, const_reference value)
|
||||
{
|
||||
clear();
|
||||
insert(end(), numElements, value);
|
||||
}
|
||||
|
||||
template <class InputIt, typename = AZStd::enable_if_t<Internal::is_input_iterator_v<InputIt>>>
|
||||
constexpr void assign(InputIt first, InputIt last)
|
||||
void assign(InputIt first, InputIt last)
|
||||
{
|
||||
clear();
|
||||
insert(end(), first, last);
|
||||
}
|
||||
|
||||
constexpr void assign(AZStd::initializer_list<value_type> ilist)
|
||||
void assign(AZStd::initializer_list<value_type> ilist)
|
||||
{
|
||||
assign(ilist.begin(), ilist.end());
|
||||
}
|
||||
|
||||
template <typename... Args, typename = AZStd::enable_if_t<is_constructible_v<T, Args...>>>
|
||||
constexpr iterator emplace(const_iterator insertPos, Args&&... args)
|
||||
iterator emplace(const_iterator insertPos, Args&&... args)
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(!full(), "Cannot emplace on a full fixed_vector");
|
||||
AZSTD_CONTAINER_ASSERT(insertPos >= cbegin() && insertPos <= cend(), "insert position must be in range of container");
|
||||
@@ -645,18 +645,18 @@ namespace AZStd
|
||||
AZStd::construct_at(insertPosPtr, AZStd::forward<Args>(args)...);
|
||||
return iterator(insertPosPtr);
|
||||
}
|
||||
constexpr iterator insert(const_iterator insertPos, const_reference value)
|
||||
iterator insert(const_iterator insertPos, const_reference value)
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(insertPos >= cbegin() && insertPos <= cend(), "insert position must be in range of container");
|
||||
return emplace(insertPos, value);
|
||||
}
|
||||
constexpr iterator insert(const_iterator insertPos, value_type&& value)
|
||||
iterator insert(const_iterator insertPos, value_type&& value)
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(insertPos >= cbegin() && insertPos <= cend(), "insert position must be in range of container");
|
||||
return emplace(insertPos, AZStd::move(value));
|
||||
}
|
||||
|
||||
constexpr void insert(const_iterator insertPos, size_type numElements, const_reference value)
|
||||
void insert(const_iterator insertPos, size_type numElements, const_reference value)
|
||||
{
|
||||
if (numElements == 0)
|
||||
{
|
||||
@@ -708,24 +708,24 @@ namespace AZStd
|
||||
}
|
||||
|
||||
template<class InputIt, typename = AZStd::enable_if_t<Internal::is_input_iterator_v<InputIt>>>
|
||||
constexpr void insert(const_iterator insertPos, InputIt first, InputIt last)
|
||||
void insert(const_iterator insertPos, InputIt first, InputIt last)
|
||||
{
|
||||
// specialize for iterator categories.
|
||||
AZSTD_CONTAINER_ASSERT(insertPos >= cbegin() && insertPos <= cend(), "insert position must be in range of container");
|
||||
insert_iter(insertPos, first, last, typename iterator_traits<InputIt>::iterator_category());
|
||||
};
|
||||
|
||||
constexpr void insert(const_iterator insertPos, AZStd::initializer_list<value_type> ilist)
|
||||
void insert(const_iterator insertPos, AZStd::initializer_list<value_type> ilist)
|
||||
{
|
||||
insert(insertPos, ilist.begin(), ilist.end());
|
||||
}
|
||||
|
||||
constexpr iterator erase(const_iterator elementIter)
|
||||
iterator erase(const_iterator elementIter)
|
||||
{
|
||||
return erase(elementIter, elementIter + 1);
|
||||
}
|
||||
|
||||
constexpr iterator erase(const_iterator first, const_iterator last)
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(first >= cbegin() && last <= cend(), "erase iterator must be inside the range of fixed_vector container");
|
||||
iterator dataStart = begin();
|
||||
@@ -741,12 +741,12 @@ namespace AZStd
|
||||
return dataStart + offset;
|
||||
}
|
||||
|
||||
constexpr void clear()
|
||||
void clear()
|
||||
{
|
||||
base_type::unsafe_destroy_all();
|
||||
resize_no_construct(0);
|
||||
}
|
||||
constexpr void swap(fixed_vector& rhs)
|
||||
void swap(fixed_vector& rhs)
|
||||
{
|
||||
// Fixed containers cannot swap pointers, they need to do full copies.
|
||||
// The strategy is to extend the smaller fixed_vector to be the size
|
||||
@@ -776,12 +776,12 @@ namespace AZStd
|
||||
}
|
||||
|
||||
// Validate container status.
|
||||
constexpr bool validate() const
|
||||
bool validate() const
|
||||
{
|
||||
return size() <= max_size();
|
||||
}
|
||||
// Validate iterator.
|
||||
constexpr int validate_iterator(const_iterator iter) const
|
||||
int validate_iterator(const_iterator iter) const
|
||||
{
|
||||
const_pointer start = data();
|
||||
const_pointer end = data() + size();
|
||||
@@ -799,19 +799,19 @@ namespace AZStd
|
||||
}
|
||||
|
||||
// pushes back an empty without a provided instance.
|
||||
constexpr void push_back()
|
||||
void push_back()
|
||||
{
|
||||
emplace_back();
|
||||
}
|
||||
|
||||
constexpr void leak_and_reset()
|
||||
void leak_and_reset()
|
||||
{
|
||||
resize_no_construct(0);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename VectorContainer>
|
||||
constexpr fixed_vector& assign_helper(VectorContainer&& rhs)
|
||||
fixed_vector& assign_helper(VectorContainer&& rhs)
|
||||
{
|
||||
constexpr bool is_const_or_lvalue_reference = AZStd::is_lvalue_reference_v<VectorContainer>
|
||||
|| AZStd::is_const_v<VectorContainer>;
|
||||
@@ -872,7 +872,7 @@ namespace AZStd
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
constexpr void insert_iter(const_iterator insertPos, Iterator first, Iterator last, const forward_iterator_tag&)
|
||||
void insert_iter(const_iterator insertPos, Iterator first, Iterator last, const forward_iterator_tag&)
|
||||
{
|
||||
size_type numElements = AZStd::distance(first, last);
|
||||
if (numElements == 0)
|
||||
@@ -923,7 +923,7 @@ namespace AZStd
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
constexpr void insert_iter(const_iterator insertPos, Iterator first, Iterator last, const input_iterator_tag&)
|
||||
void insert_iter(const_iterator insertPos, Iterator first, Iterator last, const input_iterator_tag&)
|
||||
{
|
||||
iterator dataStart = data();
|
||||
size_type offset = AZStd::distance(dataStart, insertPos);
|
||||
|
||||
@@ -753,7 +753,7 @@ namespace UnitTest
|
||||
|
||||
TEST_F(Arrays, FixedVectorCanCopyAndMoveWithDifferentCapacity)
|
||||
{
|
||||
constexpr AZStd::fixed_vector<int, 32> sourceVector{ 1,2,3,4,5 };
|
||||
AZStd::fixed_vector<int, 32> sourceVector{ 1,2,3,4,5 };
|
||||
|
||||
AZStd::fixed_vector<int, 8> copyConstructVector{ sourceVector };
|
||||
EXPECT_EQ(sourceVector, copyConstructVector);
|
||||
@@ -768,32 +768,32 @@ namespace UnitTest
|
||||
|
||||
AZStd::fixed_vector<int, 16> moveAssignVector = AZStd::move(moveConstructVector);
|
||||
|
||||
constexpr AZStd::fixed_vector expectedVector{ 1,2,3,4,5,6 };
|
||||
AZStd::fixed_vector expectedVector{ 1,2,3,4,5,6 };
|
||||
EXPECT_EQ(expectedVector, moveAssignVector);
|
||||
}
|
||||
|
||||
TEST_F(Arrays, FixedVectorComparisonOperatorsSucceedAsExpected)
|
||||
{
|
||||
constexpr AZStd::fixed_vector<int, 32> testVector{ 1,2,3,4,5 };
|
||||
constexpr AZStd::fixed_vector<int, 32> equalVector{ 1,2,3,4,5 };
|
||||
constexpr AZStd::fixed_vector<int, 32> notEqualVectorDifferentSize{ 1,2,3,4,5,6 };
|
||||
constexpr AZStd::fixed_vector<int, 32> lessVector{ 1,2,3,4,4 };
|
||||
constexpr AZStd::fixed_vector<int, 32> greaterVectorDifferentSize{ 1,2,3,4,5, 1 };
|
||||
AZStd::fixed_vector<int, 32> testVector{ 1,2,3,4,5 };
|
||||
AZStd::fixed_vector<int, 32> equalVector{ 1,2,3,4,5 };
|
||||
AZStd::fixed_vector<int, 32> notEqualVectorDifferentSize{ 1,2,3,4,5,6 };
|
||||
AZStd::fixed_vector<int, 32> lessVector{ 1,2,3,4,4 };
|
||||
AZStd::fixed_vector<int, 32> greaterVectorDifferentSize{ 1,2,3,4,5, 1 };
|
||||
|
||||
static_assert(testVector == equalVector);
|
||||
static_assert(testVector != notEqualVectorDifferentSize);
|
||||
static_assert(testVector != lessVector);
|
||||
static_assert(lessVector < testVector);
|
||||
static_assert(lessVector < greaterVectorDifferentSize);
|
||||
static_assert(lessVector <= lessVector);
|
||||
static_assert(lessVector <= testVector);
|
||||
static_assert(lessVector <= greaterVectorDifferentSize);
|
||||
static_assert(testVector > lessVector);
|
||||
static_assert(testVector > lessVector);
|
||||
static_assert(notEqualVectorDifferentSize > testVector);
|
||||
static_assert(testVector >= testVector);
|
||||
static_assert(testVector >= lessVector);
|
||||
static_assert(greaterVectorDifferentSize > lessVector);
|
||||
EXPECT_EQ(testVector, equalVector);
|
||||
EXPECT_NE(testVector, notEqualVectorDifferentSize);
|
||||
EXPECT_NE(testVector, lessVector);
|
||||
EXPECT_LT(lessVector, testVector);
|
||||
EXPECT_LT(lessVector, greaterVectorDifferentSize);
|
||||
EXPECT_LE(lessVector, lessVector);
|
||||
EXPECT_LE(lessVector, testVector);
|
||||
EXPECT_LE(lessVector, greaterVectorDifferentSize);
|
||||
EXPECT_GT(testVector, lessVector);
|
||||
EXPECT_GT(testVector, lessVector);
|
||||
EXPECT_GT(notEqualVectorDifferentSize, testVector);
|
||||
EXPECT_GE(testVector, testVector);
|
||||
EXPECT_GE(testVector, lessVector);
|
||||
EXPECT_GT(greaterVectorDifferentSize, lessVector);
|
||||
}
|
||||
|
||||
TEST_F(Arrays, VectorSwap)
|
||||
|
||||
@@ -239,12 +239,14 @@ namespace AzToolsFramework
|
||||
, m_isInIsolationMode(false)
|
||||
{
|
||||
ToolsApplicationRequests::Bus::Handler::BusConnect();
|
||||
AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusConnect();
|
||||
|
||||
m_undoCache.RegisterToUndoCacheInterface();
|
||||
}
|
||||
|
||||
ToolsApplication::~ToolsApplication()
|
||||
{
|
||||
AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusDisconnect();
|
||||
ToolsApplicationRequests::Bus::Handler::BusDisconnect();
|
||||
Stop();
|
||||
}
|
||||
@@ -566,6 +568,12 @@ namespace AzToolsFramework
|
||||
void ToolsApplication::MarkEntitySelected(AZ::EntityId entityId)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
if (m_freezeSelectionUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ_Assert(entityId.IsValid(), "Invalid entity Id being marked as selected.");
|
||||
|
||||
EntityIdList::iterator foundIter = AZStd::find(m_selectedEntities.begin(), m_selectedEntities.end(), entityId);
|
||||
@@ -585,6 +593,11 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
if (m_freezeSelectionUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EntityIdList entitiesSelected;
|
||||
entitiesSelected.reserve(entitiesToSelect.size());
|
||||
|
||||
@@ -608,6 +621,12 @@ namespace AzToolsFramework
|
||||
void ToolsApplication::MarkEntityDeselected(AZ::EntityId entityId)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
if (m_freezeSelectionUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto foundIter = AZStd::find(m_selectedEntities.begin(), m_selectedEntities.end(), entityId);
|
||||
if (foundIter != m_selectedEntities.end())
|
||||
{
|
||||
@@ -625,6 +644,11 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
if (m_freezeSelectionUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ToolsApplicationEvents::Bus::Broadcast(&ToolsApplicationEvents::BeforeEntitySelectionChanged);
|
||||
|
||||
EntityIdSet entitySetToDeselect(entitiesToDeselect.begin(), entitiesToDeselect.end());
|
||||
@@ -679,6 +703,11 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
if (m_freezeSelectionUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We're setting the selection set as a batch from an external caller.
|
||||
// * Filter out any unselectable entities
|
||||
// * Calculate selection/deselection delta so we can notify specific entities only on change.
|
||||
@@ -1569,6 +1598,16 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void ToolsApplication::OnPrefabInstancePropagationBegin()
|
||||
{
|
||||
m_freezeSelectionUpdates = true;
|
||||
}
|
||||
|
||||
void ToolsApplication::OnPrefabInstancePropagationEnd()
|
||||
{
|
||||
m_freezeSelectionUpdates = false;
|
||||
}
|
||||
|
||||
void ToolsApplication::CreateUndosForDirtyEntities()
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <AzToolsFramework/API/EditorEntityAPI.h>
|
||||
#include <AzToolsFramework/Application/EditorEntityManager.h>
|
||||
#include <AzToolsFramework/Commands/PreemptiveUndoCache.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicNotificationBus.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -29,6 +30,7 @@ namespace AzToolsFramework
|
||||
class ToolsApplication
|
||||
: public AzFramework::Application
|
||||
, public ToolsApplicationRequests::Bus::Handler
|
||||
, public AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(ToolsApplication, "{2895561E-BE90-4CC3-8370-DD46FCF74C01}", AzFramework::Application);
|
||||
@@ -169,6 +171,14 @@ namespace AzToolsFramework
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PrefabPublicNotificationBus::Handler
|
||||
|
||||
void OnPrefabInstancePropagationBegin() override;
|
||||
void OnPrefabInstancePropagationEnd() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CreateUndosForDirtyEntities();
|
||||
void ConsistencyCheckUndoCache();
|
||||
AZ::Aabb m_selectionBounds;
|
||||
@@ -181,6 +191,7 @@ namespace AzToolsFramework
|
||||
bool m_isDuringUndoRedo;
|
||||
bool m_isInIsolationMode;
|
||||
EntityIdSet m_isolatedEntityIdSet;
|
||||
bool m_freezeSelectionUpdates = false;
|
||||
|
||||
EditorEntityAPI* m_editorEntityAPI = nullptr;
|
||||
|
||||
|
||||
@@ -449,16 +449,23 @@ namespace AzToolsFramework
|
||||
AZStd::unordered_map<AZ::EntityId, AZStd::pair<AZ::EntityId, AZ::u64>>::const_iterator orderItr = m_savedOrderInfo.find(childId);
|
||||
if (orderItr != m_savedOrderInfo.end() && orderItr->second.first == parentId)
|
||||
{
|
||||
bool sortOrderUpdated = AzToolsFramework::RecoverEntitySortInfo(parentId, childId, orderItr->second.second);
|
||||
m_savedOrderInfo.erase(childId);
|
||||
|
||||
// force notify the child sort order changed on the parent entity info, but only if the restore didn't actually modify
|
||||
// the order internally (and sent ChildEntityOrderArrayUpdated). that may seem heavy handed, and it is, but necessary
|
||||
// to combat scenarios when the initial override detection returns a false positive (see comment about IDH comparisons
|
||||
// in OnChildSortOrderChanged) and the slice instance source-to-live mapping hasn't been fully reconstructed yet.
|
||||
if (!sortOrderUpdated)
|
||||
bool isPrefabEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
// If prefabs are enabled, rely on the component to do a sanity check instead of restoring the order from the model
|
||||
if (!isPrefabEnabled)
|
||||
{
|
||||
parentInfo.OnChildSortOrderChanged();
|
||||
bool sortOrderUpdated = AzToolsFramework::RecoverEntitySortInfo(parentId, childId, orderItr->second.second);
|
||||
m_savedOrderInfo.erase(childId);
|
||||
|
||||
// force notify the child sort order changed on the parent entity info, but only if the restore didn't actually modify
|
||||
// the order internally (and sent ChildEntityOrderArrayUpdated). that may seem heavy handed, and it is, but necessary
|
||||
// to combat scenarios when the initial override detection returns a false positive (see comment about IDH comparisons
|
||||
// in OnChildSortOrderChanged) and the slice instance source-to-live mapping hasn't been fully reconstructed yet.
|
||||
if (!sortOrderUpdated)
|
||||
{
|
||||
parentInfo.OnChildSortOrderChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
+93
-17
@@ -8,11 +8,17 @@
|
||||
#include "EditorEntitySortComponent.h"
|
||||
#include "EditorEntityInfoBus.h"
|
||||
#include "EditorEntityHelpers.h"
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/Json/RegistrationContext.h>
|
||||
#include <AzCore/std/sort.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicRequestBus.h>
|
||||
#include <AzToolsFramework/Undo/UndoSystem.h>
|
||||
#include <AzCore/Serialization/Json/RegistrationContext.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntitySortComponentSerializer.h>
|
||||
|
||||
static_assert(sizeof(AZ::u64) == sizeof(AZ::EntityId), "We use AZ::EntityId for Persistent ID, which is a u64 under the hood. These must be the same size otherwise the persistent id will have to be rewritten");
|
||||
|
||||
@@ -51,6 +57,12 @@ namespace AzToolsFramework
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::JsonRegistrationContext* jsonRegistration = azrtti_cast<AZ::JsonRegistrationContext*>(context);
|
||||
if (jsonRegistration)
|
||||
{
|
||||
jsonRegistration->Serializer<JsonEditorEntitySortComponentSerializer>()->HandlesType<EditorEntitySortComponent>();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorEntitySortComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
|
||||
@@ -167,9 +179,6 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
MarkDirtyAndSendChangedEvent();
|
||||
|
||||
// Use the ToolsApplication to mark the entity dirty, this will only do something if we already have an undo batch
|
||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::AddDirtyEntity, GetEntityId());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -187,6 +196,10 @@ namespace AzToolsFramework
|
||||
else
|
||||
{
|
||||
EntityOrderArray::iterator insertPosition = GetFirstSelectedEntityPosition();
|
||||
if (insertPosition != m_childEntityOrderArray.end())
|
||||
{
|
||||
++insertPosition;
|
||||
}
|
||||
retval = AddChildEntityInternal(entityId, false, insertPosition);
|
||||
}
|
||||
|
||||
@@ -220,9 +233,6 @@ namespace AzToolsFramework
|
||||
|
||||
MarkDirtyAndSendChangedEvent();
|
||||
|
||||
// Use the ToolsApplication to mark the entity dirty, this will only do something if we already have an undo batch
|
||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::AddDirtyEntity, GetEntityId());
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -272,6 +282,12 @@ namespace AzToolsFramework
|
||||
void EditorEntitySortComponent::OnPrefabInstancePropagationEnd()
|
||||
{
|
||||
m_ignoreIncomingOrderChanges = false;
|
||||
|
||||
if (m_shouldSanityCheckStateAfterPropagation)
|
||||
{
|
||||
SanitizeOrderEntryArray();
|
||||
m_shouldSanityCheckStateAfterPropagation = false;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorEntitySortComponent::MarkDirtyAndSendChangedEvent()
|
||||
@@ -280,14 +296,8 @@ namespace AzToolsFramework
|
||||
// one of the event listeners needs to build the InstanceDataHierarchy
|
||||
m_entityOrderIsDirty = true;
|
||||
|
||||
// Force an immediate update for prefabs, which won't receive PrepareSave
|
||||
bool isPrefabEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
if (isPrefabEnabled)
|
||||
{
|
||||
PrepareSave();
|
||||
}
|
||||
// Use the ToolsApplication to mark the entity dirty, this will only do something if we already have an undo batch
|
||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::AddDirtyEntity, GetEntityId());
|
||||
EditorEntitySortNotificationBus::Event(GetEntityId(), &EditorEntitySortNotificationBus::Events::ChildEntityOrderArrayUpdated);
|
||||
}
|
||||
|
||||
@@ -308,9 +318,8 @@ namespace AzToolsFramework
|
||||
isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
if (isPrefabEnabled)
|
||||
{
|
||||
PostLoad();
|
||||
m_shouldSanityCheckStateAfterPropagation = true;
|
||||
}
|
||||
|
||||
// Send out that the order for our entity is now updated
|
||||
EditorEntitySortNotificationBus::Event(GetEntityId(), &EditorEntitySortNotificationBus::Events::ChildEntityOrderArrayUpdated);
|
||||
}
|
||||
@@ -336,6 +345,73 @@ namespace AzToolsFramework
|
||||
m_entityOrderIsDirty = false;
|
||||
}
|
||||
|
||||
void EditorEntitySortComponent::SanitizeOrderEntryArray()
|
||||
{
|
||||
bool shouldEmitDirtyState = false;
|
||||
|
||||
// Remove invalid and duplicate entries that point at non-existent entities
|
||||
AZStd::unordered_set<AZ::EntityId> duplicateIds;
|
||||
for (auto it = m_childEntityOrderArray.begin(); it != m_childEntityOrderArray.end();)
|
||||
{
|
||||
if (!it->IsValid() || GetEntityById(*it) == nullptr || duplicateIds.contains(*it))
|
||||
{
|
||||
it = m_childEntityOrderArray.erase(it);
|
||||
shouldEmitDirtyState = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
duplicateIds.insert(*it);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// Append any missing children
|
||||
EntityIdList children;
|
||||
AZ::TransformBus::EventResult(children, GetEntityId(), &AZ::TransformBus::Events::GetChildren);
|
||||
for (auto it = m_childEntityOrderArray.begin(); it != m_childEntityOrderArray.end(); ++it)
|
||||
{
|
||||
if (auto removedChildrenIt = AZStd::remove(children.begin(), children.end(), *it); removedChildrenIt != children.end())
|
||||
{
|
||||
children.erase(removedChildrenIt);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::sort(children.begin(), children.end(), [](AZ::EntityId lhs, AZ::EntityId rhs)
|
||||
{
|
||||
return GetEntityById(lhs)->GetName() < GetEntityById(rhs)->GetName();
|
||||
});
|
||||
|
||||
if (!children.empty())
|
||||
{
|
||||
shouldEmitDirtyState = true;
|
||||
EntityOrderArray::iterator insertPosition = GetFirstSelectedEntityPosition();
|
||||
if (insertPosition != m_childEntityOrderArray.end())
|
||||
{
|
||||
++insertPosition;
|
||||
}
|
||||
m_childEntityOrderArray.insert(insertPosition, children.begin(), children.end());
|
||||
}
|
||||
|
||||
// Clear out the vector to be rebuilt from persistent id
|
||||
m_childEntityOrderEntryArray.resize(m_childEntityOrderArray.size());
|
||||
for (size_t i = 0; i < m_childEntityOrderArray.size(); ++i)
|
||||
{
|
||||
m_childEntityOrderEntryArray[i] = {
|
||||
m_childEntityOrderArray[i],
|
||||
static_cast<AZ::u64>(i)
|
||||
};
|
||||
}
|
||||
|
||||
RebuildEntityOrderCache();
|
||||
|
||||
if (shouldEmitDirtyState)
|
||||
{
|
||||
ToolsApplicationRequests::Bus::Broadcast(&ToolsApplicationRequests::Bus::Events::AddDirtyEntity, GetEntityId());
|
||||
}
|
||||
|
||||
m_entityOrderIsDirty = false;
|
||||
}
|
||||
|
||||
void EditorEntitySortComponent::PostLoad()
|
||||
{
|
||||
// Clear out the vector to be rebuilt from persistent id
|
||||
@@ -383,7 +459,7 @@ namespace AzToolsFramework
|
||||
firstSelectedEntityPos = selectedEntityPos < firstSelectedEntityPos ? selectedEntityPos : firstSelectedEntityPos;
|
||||
}
|
||||
|
||||
return firstSelectedEntityPos == m_childEntityOrderArray.end() ? m_childEntityOrderArray.begin() : firstSelectedEntityPos;
|
||||
return firstSelectedEntityPos;
|
||||
}
|
||||
}
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace AzToolsFramework
|
||||
, public EditorEntityContextNotificationBus::Handler
|
||||
, public AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
|
||||
{
|
||||
friend class JsonEditorEntitySortComponentSerializer;
|
||||
|
||||
public:
|
||||
AZ_COMPONENT(EditorEntitySortComponent, "{6EA1E03D-68B2-466D-97F7-83998C8C27F0}", EditorComponentBase);
|
||||
|
||||
@@ -64,6 +66,8 @@ namespace AzToolsFramework
|
||||
void PrepareSave();
|
||||
void PostLoad();
|
||||
|
||||
void SanitizeOrderEntryArray();
|
||||
|
||||
class EntitySortSerializationEvents
|
||||
: public AZ::SerializeContext::IEventHandler
|
||||
{
|
||||
@@ -112,6 +116,7 @@ namespace AzToolsFramework
|
||||
|
||||
bool m_entityOrderIsDirty = true; ///< This flag indicates our stored serialization order data is out of date and must be rebuilt before serialization occurs
|
||||
bool m_ignoreIncomingOrderChanges = false; ///< This is set when prefab propagation occurs so that non-authored order changes can be ignored
|
||||
bool m_shouldSanityCheckStateAfterPropagation = false; //< This is set after activation, to queue a cleanup of any invalid state after the next prefab propagation.
|
||||
};
|
||||
}
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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 <AzCore/Serialization/Json/JsonSerializationResult.h>
|
||||
#include <AzCore/std/sort.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntitySortComponent.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntitySortComponentSerializer.h>
|
||||
|
||||
namespace AzToolsFramework::Components
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(JsonEditorEntitySortComponentSerializer, AZ::SystemAllocator, 0);
|
||||
|
||||
AZ::JsonSerializationResult::Result JsonEditorEntitySortComponentSerializer::Load(
|
||||
void* outputValue,
|
||||
[[maybe_unused]] const AZ::Uuid& outputValueTypeId,
|
||||
const rapidjson::Value& inputValue,
|
||||
AZ::JsonDeserializerContext& context)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
AZ_Assert(
|
||||
azrtti_typeid<EditorEntitySortComponent>() == outputValueTypeId,
|
||||
"Unable to deserialize EditorEntitySortComponent from json because the provided type is %s.",
|
||||
outputValueTypeId.ToString<AZStd::string>().c_str());
|
||||
|
||||
EditorEntitySortComponent* sortComponentInstance = reinterpret_cast<EditorEntitySortComponent*>(outputValue);
|
||||
AZ_Assert(sortComponentInstance, "Output value for JsonEditorEntitySortComponentSerializer can't be null.");
|
||||
|
||||
JSR::ResultCode result(JSR::Tasks::ReadField);
|
||||
{
|
||||
JSR::ResultCode componentIdLoadResult = ContinueLoadingFromJsonObjectField(
|
||||
&sortComponentInstance->m_id, azrtti_typeid<decltype(sortComponentInstance->m_id)>(), inputValue,
|
||||
"Id", context);
|
||||
|
||||
result.Combine(componentIdLoadResult);
|
||||
}
|
||||
|
||||
{
|
||||
sortComponentInstance->m_childEntityOrderArray.clear();
|
||||
JSR::ResultCode enryLoadResult = ContinueLoadingFromJsonObjectField(
|
||||
&sortComponentInstance->m_childEntityOrderArray,
|
||||
azrtti_typeid<decltype(sortComponentInstance->m_childEntityOrderArray)>(), inputValue, "Child Entity Order",
|
||||
context);
|
||||
|
||||
// Migrate ChildEntityOrderEntryArray -> ChildEntityOrderArray
|
||||
if (sortComponentInstance->m_childEntityOrderArray.empty())
|
||||
{
|
||||
enryLoadResult = ContinueLoadingFromJsonObjectField(
|
||||
&sortComponentInstance->m_childEntityOrderEntryArray,
|
||||
azrtti_typeid<decltype(sortComponentInstance->m_childEntityOrderEntryArray)>(), inputValue,
|
||||
"ChildEntityOrderEntryArray", context);
|
||||
|
||||
AZStd::sort(
|
||||
sortComponentInstance->m_childEntityOrderEntryArray.begin(),
|
||||
sortComponentInstance->m_childEntityOrderEntryArray.end(),
|
||||
[](const EditorEntitySortComponent::EntityOrderEntry& lhs,
|
||||
const EditorEntitySortComponent::EntityOrderEntry& rhs) -> bool
|
||||
{
|
||||
return lhs.m_sortIndex < rhs.m_sortIndex;
|
||||
});
|
||||
|
||||
// Sort by index and copy to the order array, any duplicates or invalid entries will be cleaned up by the sanitization pass
|
||||
sortComponentInstance->m_childEntityOrderArray.resize(sortComponentInstance->m_childEntityOrderEntryArray.size());
|
||||
for (size_t i = 0; i < sortComponentInstance->m_childEntityOrderEntryArray.size(); ++i)
|
||||
{
|
||||
sortComponentInstance->m_childEntityOrderArray[i] = sortComponentInstance->m_childEntityOrderEntryArray[i].m_entityId;
|
||||
}
|
||||
}
|
||||
|
||||
sortComponentInstance->RebuildEntityOrderCache();
|
||||
|
||||
result.Combine(enryLoadResult);
|
||||
}
|
||||
|
||||
return context.Report(
|
||||
result,
|
||||
result.GetProcessing() != JSR::Processing::Halted ? "Successfully loaded EditorEntitySortComponent information."
|
||||
: "Failed to load EditorEntitySortComponent information.");
|
||||
}
|
||||
|
||||
AZ::JsonSerializationResult::Result JsonEditorEntitySortComponentSerializer::Store(
|
||||
rapidjson::Value& outputValue,
|
||||
const void* inputValue,
|
||||
const void* defaultValue,
|
||||
[[maybe_unused]] const AZ::Uuid& valueTypeId,
|
||||
AZ::JsonSerializerContext& context)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
AZ_Assert(
|
||||
azrtti_typeid<EditorEntitySortComponent>() == valueTypeId,
|
||||
"Unable to Serialize EditorEntitySortComponent because the provided type is %s.",
|
||||
valueTypeId.ToString<AZStd::string>().c_str());
|
||||
|
||||
const EditorEntitySortComponent* sortComponentInstance = reinterpret_cast<const EditorEntitySortComponent*>(inputValue);
|
||||
AZ_Assert(sortComponentInstance, "Input value for JsonEditorEntitySortComponentSerializer can't be null.");
|
||||
const EditorEntitySortComponent* defaultsortComponentInstance =
|
||||
reinterpret_cast<const EditorEntitySortComponent*>(defaultValue);
|
||||
|
||||
JSR::ResultCode result(JSR::Tasks::WriteValue);
|
||||
{
|
||||
AZ::ScopedContextPath subPathName(context, "m_id");
|
||||
const AZ::ComponentId* componentId = &sortComponentInstance->m_id;
|
||||
const AZ::ComponentId* defaultComponentId =
|
||||
defaultsortComponentInstance ? &defaultsortComponentInstance->m_id : nullptr;
|
||||
|
||||
JSR::ResultCode resultComponentId = ContinueStoringToJsonObjectField(
|
||||
outputValue, "Id", componentId, defaultComponentId, azrtti_typeid<decltype(sortComponentInstance->m_id)>(),
|
||||
context);
|
||||
|
||||
result.Combine(resultComponentId);
|
||||
}
|
||||
|
||||
{
|
||||
AZ::ScopedContextPath subPathName(context, "m_childEntityOrderArray");
|
||||
const EntityOrderArray* childEntityOrderArray = &sortComponentInstance->m_childEntityOrderArray;
|
||||
const EntityOrderArray* defaultChildEntityOrderArray =
|
||||
defaultsortComponentInstance ? &defaultsortComponentInstance->m_childEntityOrderArray : nullptr;
|
||||
|
||||
JSR::ResultCode resultParentEntityId = ContinueStoringToJsonObjectField(
|
||||
outputValue, "Child Entity Order", childEntityOrderArray, defaultChildEntityOrderArray,
|
||||
azrtti_typeid<decltype(sortComponentInstance->m_childEntityOrderArray)>(), context);
|
||||
|
||||
result.Combine(resultParentEntityId);
|
||||
}
|
||||
|
||||
return context.Report(
|
||||
result,
|
||||
result.GetProcessing() != JSR::Processing::Halted ? "Successfully stored EditorEntitySortComponent information."
|
||||
: "Failed to store EditorEntitySortComponent information.");
|
||||
}
|
||||
} // namespace AzToolsFramework::Components
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
|
||||
|
||||
namespace AzToolsFramework::Components
|
||||
{
|
||||
class JsonEditorEntitySortComponentSerializer
|
||||
: public AZ::BaseJsonSerializer
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(JsonEditorEntitySortComponentSerializer, "{5104782E-B34F-4D87-B1DF-BDFB1AF20D58}", BaseJsonSerializer);
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
|
||||
AZ::JsonSerializationResult::Result Load(
|
||||
void* outputValue, const AZ::Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
|
||||
AZ::JsonDeserializerContext& context) override;
|
||||
|
||||
AZ::JsonSerializationResult::Result Store(
|
||||
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const AZ::Uuid& valueTypeId,
|
||||
AZ::JsonSerializerContext& context) override;
|
||||
};
|
||||
} // namespace AzToolsFramework::Components
|
||||
+3
-2
@@ -20,6 +20,7 @@
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicNotificationBus.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
|
||||
#include <AzToolsFramework/Prefab/Template/Template.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicRequestBus.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
@@ -244,10 +245,10 @@ namespace AzToolsFramework
|
||||
selectedEntityIds.erase(entityIdIterator--);
|
||||
}
|
||||
}
|
||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetSelectedEntities, selectedEntityIds);
|
||||
|
||||
// Notify Propagation has ended
|
||||
// Notify Propagation has ended, then update selection (which is frozen during propagation, so this order matters)
|
||||
PrefabPublicNotificationBus::Broadcast(&PrefabPublicNotifications::OnPrefabInstancePropagationEnd);
|
||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetSelectedEntities, selectedEntityIds);
|
||||
}
|
||||
|
||||
m_updatingTemplateInstancesInQueue = false;
|
||||
|
||||
@@ -28,6 +28,9 @@ namespace AzToolsFramework
|
||||
inline static const char* EntityIdName = "Id";
|
||||
inline static const char* EntitiesName = "Entities";
|
||||
inline static const char* ContainerEntityName = "ContainerEntity";
|
||||
inline static const char* ComponentsName = "Components";
|
||||
inline static const char* EntityOrderName = "Child Entity Order";
|
||||
inline static const char* TypeName = "$type";
|
||||
|
||||
/**
|
||||
* Find Prefab value from given parent value and target value's name.
|
||||
|
||||
@@ -212,7 +212,17 @@ namespace AzToolsFramework::Prefab
|
||||
|
||||
AZ::EntityId PrefabFocusHandler::GetFocusedPrefabContainerEntityId([[maybe_unused]] AzFramework::EntityContextId entityContextId) const
|
||||
{
|
||||
return m_focusedInstanceContainerEntityId;
|
||||
if (m_focusedInstanceContainerEntityId.IsValid())
|
||||
{
|
||||
return m_focusedInstanceContainerEntityId;
|
||||
}
|
||||
|
||||
if (auto instance = GetReferenceFromContainerEntityId(m_focusedInstanceContainerEntityId); instance.has_value())
|
||||
{
|
||||
return instance->get().GetContainerEntityId();
|
||||
}
|
||||
|
||||
return AZ::EntityId();
|
||||
}
|
||||
|
||||
bool PrefabFocusHandler::IsOwningPrefabBeingFocused(AZ::EntityId entityId) const
|
||||
@@ -366,7 +376,7 @@ namespace AzToolsFramework::Prefab
|
||||
size_t index = 0;
|
||||
size_t maxIndex = m_instanceFocusHierarchy.size() - 1;
|
||||
|
||||
for (const AZ::EntityId containerEntityId : m_instanceFocusHierarchy)
|
||||
for (const AZ::EntityId& containerEntityId : m_instanceFocusHierarchy)
|
||||
{
|
||||
InstanceOptionalReference instance = GetReferenceFromContainerEntityId(containerEntityId);
|
||||
if (instance.has_value())
|
||||
@@ -404,7 +414,7 @@ namespace AzToolsFramework::Prefab
|
||||
return;
|
||||
}
|
||||
|
||||
for (const AZ::EntityId containerEntityId : instances)
|
||||
for (const AZ::EntityId& containerEntityId : instances)
|
||||
{
|
||||
InstanceOptionalReference instance = GetReferenceFromContainerEntityId(containerEntityId);
|
||||
|
||||
@@ -423,7 +433,7 @@ namespace AzToolsFramework::Prefab
|
||||
return;
|
||||
}
|
||||
|
||||
for (const AZ::EntityId containerEntityId : instances)
|
||||
for (const AZ::EntityId& containerEntityId : instances)
|
||||
{
|
||||
InstanceOptionalReference instance = GetReferenceFromContainerEntityId(containerEntityId);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/JSON/stringbuffer.h>
|
||||
#include <AzCore/JSON/writer.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <AzCore/Utils/TypeHash.h>
|
||||
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
@@ -29,6 +30,7 @@
|
||||
#include <AzToolsFramework/Prefab/PrefabUndo.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabUndoHelpers.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntitySortComponent.h>
|
||||
|
||||
#include <QString>
|
||||
|
||||
@@ -595,8 +597,41 @@ namespace AzToolsFramework
|
||||
|
||||
Instance& entityOwningInstance = owningInstanceOfParentEntity->get();
|
||||
|
||||
// Get the template for our owning instance from the root prefab DOM and use that to generate our patch
|
||||
AZStd::vector<InstanceOptionalConstReference> pathOfInstances;
|
||||
|
||||
InstanceOptionalReference rootInstance = owningInstanceOfParentEntity;
|
||||
while (rootInstance->get().GetParentInstance() != AZStd::nullopt)
|
||||
{
|
||||
pathOfInstances.emplace_back(rootInstance);
|
||||
rootInstance = rootInstance->get().GetParentInstance();
|
||||
}
|
||||
|
||||
AZStd::string aliasPathResult = "";
|
||||
for (auto instanceIter = pathOfInstances.rbegin(); instanceIter != pathOfInstances.rend(); ++instanceIter)
|
||||
{
|
||||
aliasPathResult.append("/Instances/");
|
||||
aliasPathResult.append((*instanceIter)->get().GetInstanceAlias());
|
||||
}
|
||||
|
||||
PrefabDomPath rootPrefabDomPath(aliasPathResult.c_str());
|
||||
|
||||
PrefabDom& rootPrefabTemplateDom = m_prefabSystemComponentInterface->FindTemplateDom(rootInstance->get().GetTemplateId());
|
||||
|
||||
auto instanceDomFromRootValue = rootPrefabDomPath.Get(rootPrefabTemplateDom);
|
||||
if (!instanceDomFromRootValue)
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("Could not load Instance DOM from the top level ancestor's DOM.");
|
||||
}
|
||||
|
||||
PrefabDomValueReference instanceDomFromRoot = *instanceDomFromRootValue;
|
||||
if (!instanceDomFromRoot.has_value())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("Could not load Instance DOM from the top level ancestor's DOM.");
|
||||
}
|
||||
|
||||
PrefabDom instanceDomBeforeUpdate;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomBeforeUpdate, entityOwningInstance);
|
||||
instanceDomBeforeUpdate.CopyFrom(instanceDomFromRoot.value().get(), instanceDomBeforeUpdate.GetAllocator());
|
||||
|
||||
ScopedUndoBatch undoBatch("Add Entity");
|
||||
|
||||
@@ -674,6 +709,9 @@ namespace AzToolsFramework
|
||||
bool isInstanceContainerEntity = IsInstanceContainerEntity(entityId) && !IsLevelInstanceContainerEntity(entityId);
|
||||
bool isNewParentOwnedByDifferentInstance = false;
|
||||
|
||||
bool isInFocusTree = m_prefabFocusPublicInterface->IsOwningPrefabInFocusHierarchy(entityId);
|
||||
bool isOwnedByFocusedPrefabInstance = m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId);
|
||||
|
||||
if (beforeParentId != afterParentId)
|
||||
{
|
||||
// If the entity parent changed, verify if the owning instance changed too
|
||||
@@ -727,7 +765,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
if (isInstanceContainerEntity)
|
||||
if (isInFocusTree && !isOwnedByFocusedPrefabInstance)
|
||||
{
|
||||
if (isNewParentOwnedByDifferentInstance)
|
||||
{
|
||||
@@ -1648,6 +1686,144 @@ namespace AzToolsFramework
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::AddNewEntityToSortOrder(
|
||||
Instance& owningInstance,
|
||||
PrefabDom& domToAddEntityUnder,
|
||||
const EntityAlias& parentEntityAlias,
|
||||
const EntityAlias& entityToAddAlias)
|
||||
{
|
||||
// Find the parent entity to get its sort order component
|
||||
auto findParentEntity = [&]() -> rapidjson::Value*
|
||||
{
|
||||
if (auto containerEntityIter = domToAddEntityUnder.FindMember(PrefabDomUtils::ContainerEntityName);
|
||||
containerEntityIter != domToAddEntityUnder.MemberEnd())
|
||||
{
|
||||
if (parentEntityAlias == containerEntityIter->value[PrefabDomUtils::EntityIdName].GetString())
|
||||
{
|
||||
return &containerEntityIter->value;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto entitiesIter = domToAddEntityUnder.FindMember(PrefabDomUtils::EntitiesName);
|
||||
entitiesIter != domToAddEntityUnder.MemberEnd())
|
||||
{
|
||||
for (auto entityIter = entitiesIter->value.MemberBegin(); entityIter != entitiesIter->value.MemberEnd(); ++entityIter)
|
||||
{
|
||||
if (parentEntityAlias == entityIter->value[PrefabDomUtils::EntityIdName].GetString())
|
||||
{
|
||||
return &entityIter->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
rapidjson::Value* parentEntityValue = findParentEntity();
|
||||
if (parentEntityValue == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the list of selected entities, we'll insert our duplicated entities after the last selected
|
||||
// sibling in their parent's list, e.g. for:
|
||||
// - Entity1
|
||||
// - Entity2 (selected)
|
||||
// - Entity3
|
||||
// - Entity4 (selected)
|
||||
// - Entity5
|
||||
// Our duplicate selection command would create duplicate Entity2 and Entity4 and insert them after Entity4:
|
||||
// - Entity1
|
||||
// - Entity2
|
||||
// - Entity3
|
||||
// - Entity4
|
||||
// - Entity2 (new, selected after duplicate)
|
||||
// - Entity4 (new, selected after duplicate)
|
||||
// - Entity5
|
||||
AzToolsFramework::EntityIdList selectedEntities;
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
|
||||
selectedEntities, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities);
|
||||
|
||||
// Find the EditorEntitySortComponent DOM
|
||||
auto componentsIter = parentEntityValue->FindMember(PrefabDomUtils::ComponentsName);
|
||||
if (componentsIter == parentEntityValue->MemberEnd())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto componentIter = componentsIter->value.MemberBegin(); componentIter != componentIter->value.MemberEnd();
|
||||
++componentIter)
|
||||
{
|
||||
// Check the component type
|
||||
auto typeFieldIter = componentIter->value.FindMember(PrefabDomUtils::TypeName);
|
||||
if (typeFieldIter == componentIter->value.MemberEnd())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AZ::JsonDeserializerSettings jsonDeserializerSettings;
|
||||
AZ::Uuid typeId = AZ::Uuid::CreateNull();
|
||||
AZ::JsonSerialization::LoadTypeId(typeId, typeFieldIter->value);
|
||||
|
||||
if (typeId != azrtti_typeid<Components::EditorEntitySortComponent>())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for the entity order field
|
||||
auto orderMembersIter = componentIter->value.FindMember(PrefabDomUtils::EntityOrderName);
|
||||
if (orderMembersIter == componentIter->value.MemberEnd() || !orderMembersIter->value.IsArray())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Scan for the last selected entity in the list (if any) to determine where to add our entries
|
||||
rapidjson::Value newOrder(rapidjson::kArrayType);
|
||||
auto insertValuesAfter = orderMembersIter->value.End();
|
||||
for (auto orderMemberIter = orderMembersIter->value.Begin(); orderMemberIter != orderMembersIter->value.End();
|
||||
++orderMemberIter)
|
||||
{
|
||||
if (!orderMemberIter->IsString())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const char* value = orderMemberIter->GetString();
|
||||
for (AZ::EntityId selectedEntity : selectedEntities)
|
||||
{
|
||||
auto alias = owningInstance.GetEntityAlias(selectedEntity);
|
||||
if (alias.has_value() && alias.value().get() == value)
|
||||
{
|
||||
insertValuesAfter = orderMemberIter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct our new array with the new order - insertion may happen at end, so check for that in the loop itself
|
||||
for (auto orderMemberIter = orderMembersIter->value.Begin();; ++orderMemberIter)
|
||||
{
|
||||
if (orderMemberIter != orderMembersIter->value.End())
|
||||
{
|
||||
newOrder.PushBack(orderMemberIter->Move(), domToAddEntityUnder.GetAllocator());
|
||||
}
|
||||
if (orderMemberIter == insertValuesAfter)
|
||||
{
|
||||
newOrder.PushBack(
|
||||
rapidjson::Value(entityToAddAlias.c_str(), domToAddEntityUnder.GetAllocator()),
|
||||
domToAddEntityUnder.GetAllocator());
|
||||
}
|
||||
if (orderMemberIter == orderMembersIter->value.End())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace the order with our newly constructed one
|
||||
orderMembersIter->value.Swap(newOrder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::DuplicateNestedEntitiesInInstance(Instance& commonOwningInstance,
|
||||
const AZStd::vector<AZ::Entity*>& entities, PrefabDom& domToAddDuplicatedEntitiesUnder,
|
||||
EntityIdList& duplicatedEntityIds, AZStd::unordered_map<EntityAlias, EntityAlias>& oldAliasToNewAliasMap)
|
||||
@@ -1705,6 +1881,73 @@ namespace AzToolsFramework
|
||||
PrefabDom entityDomAfter(&domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
entityDomAfter.Parse(newEntityDomString.toUtf8().constData());
|
||||
|
||||
EntityAlias parentEntityAlias;
|
||||
if (auto componentsIter = entityDomAfter.FindMember(PrefabDomUtils::ComponentsName);
|
||||
componentsIter != entityDomAfter.MemberEnd())
|
||||
{
|
||||
auto checkComponent = [&](const rapidjson::Value& value) -> bool
|
||||
{
|
||||
if (!value.IsObject())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the component type
|
||||
auto typeFieldIter = value.FindMember(PrefabDomUtils::TypeName);
|
||||
if (typeFieldIter == value.MemberEnd())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AZ::JsonDeserializerSettings jsonDeserializerSettings;
|
||||
AZ::Uuid typeId = AZ::Uuid::CreateNull();
|
||||
AZ::JsonSerialization::LoadTypeId(typeId, typeFieldIter->value);
|
||||
|
||||
// Prefabs get serialized with the Editor transform component type, check for that
|
||||
if (typeId != azrtti_typeid<Components::TransformComponent>())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (auto parentEntityIter = value.FindMember("Parent Entity");
|
||||
parentEntityIter != value.MemberEnd())
|
||||
{
|
||||
parentEntityAlias = parentEntityIter->value.GetString();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (componentsIter->value.IsObject())
|
||||
{
|
||||
for (auto componentIter = componentsIter->value.MemberBegin(); componentIter != componentsIter->value.MemberEnd();
|
||||
++componentIter)
|
||||
{
|
||||
if (checkComponent(componentIter->value))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (componentsIter->value.IsArray())
|
||||
{
|
||||
for (auto componentIter = componentsIter->value.Begin(); componentIter != componentsIter->value.End();
|
||||
++componentIter)
|
||||
{
|
||||
if (checkComponent(*componentIter))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert our entity into its parent's sort order
|
||||
if (!parentEntityAlias.empty())
|
||||
{
|
||||
AddNewEntityToSortOrder(commonOwningInstance, domToAddDuplicatedEntitiesUnder, parentEntityAlias, newEntityAlias);
|
||||
}
|
||||
|
||||
// Add the new Entity DOM to the Entities member of the instance
|
||||
rapidjson::Value aliasName(newEntityAlias.c_str(), static_cast<rapidjson::SizeType>(newEntityAlias.length()), domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
entitiesIter->value.AddMember(AZStd::move(aliasName), entityDomAfter, domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
|
||||
@@ -78,6 +78,8 @@ namespace AzToolsFramework
|
||||
|
||||
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const;
|
||||
bool EntitiesBelongToSameInstance(const EntityIdList& entityIds) const;
|
||||
void AddNewEntityToSortOrder(Instance& owningInstance, PrefabDom& domToAddEntityUnder,
|
||||
const EntityAlias& parentEntityAlias, const EntityAlias& entityToAddAlias);
|
||||
|
||||
/**
|
||||
* Duplicate a list of entities owned by a common owning instance by directly
|
||||
|
||||
-1
@@ -1599,7 +1599,6 @@ namespace AzToolsFramework
|
||||
for (size_t entityIndex = 1; entityIndex < m_selectedEntityIds.size(); ++entityIndex)
|
||||
{
|
||||
entity = GetSelectedEntityById(m_selectedEntityIds[entityIndex]);
|
||||
AZ_Assert(entity, "Entity id selected for display but no such entity exists");
|
||||
if (!entity)
|
||||
{
|
||||
continue;
|
||||
|
||||
+1
-4
@@ -150,10 +150,7 @@ namespace AzToolsFramework
|
||||
TypeBeingHandled actualValue = instance;
|
||||
for (int idx = 0; idx < m_common.GetElementCount(); ++idx)
|
||||
{
|
||||
if (elements[idx]->wasValueEditedByUser())
|
||||
{
|
||||
actualValue.SetElement(idx, static_cast<float>(elements[idx]->getValue()));
|
||||
}
|
||||
actualValue.SetElement(idx, static_cast<float>(elements[idx]->getValue()));
|
||||
}
|
||||
instance = actualValue;
|
||||
}
|
||||
|
||||
+41
-31
@@ -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);
|
||||
}
|
||||
|
||||
+18
-1
@@ -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.
|
||||
|
||||
@@ -148,6 +148,8 @@ set(FILES
|
||||
Entity/EditorEntitySortBus.h
|
||||
Entity/EditorEntitySortComponent.cpp
|
||||
Entity/EditorEntitySortComponent.h
|
||||
Entity/EditorEntitySortComponentSerializer.cpp
|
||||
Entity/EditorEntitySortComponentSerializer.h
|
||||
Entity/EditorEntityTransformBus.h
|
||||
Entity/PrefabEditorEntityOwnershipInterface.h
|
||||
Entity/PrefabEditorEntityOwnershipService.h
|
||||
|
||||
+3
-3
@@ -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),
|
||||
[¤tEntityIdAccentAdded, 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),
|
||||
[¤tEntityIdAccentAdded, 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, ¤tEntityIdAccentAdded, 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,7 +19,7 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
// Attempt to use the Ninja build system if it is installed (described in the o3de documentation) if possible,
|
||||
// otherwise default to the the default for Linux (Unix Makefiles)
|
||||
auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"}, QProcessEnvironment::systemEnvironment());
|
||||
auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"});
|
||||
QString cmakeGenerator = (whichNinjaResult.IsSuccess()) ? "Ninja Multi-Config" : "Unix Makefiles";
|
||||
bool compileProfileOnBuild = (whichNinjaResult.IsSuccess());
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace O3DE::ProjectManager
|
||||
|
||||
AZ::Outcome<QStringList, QString> ProjectBuilderWorker::ConstructCmakeBuildCommandArguments() const
|
||||
{
|
||||
auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"}, QProcessEnvironment::systemEnvironment());
|
||||
auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"});
|
||||
bool compileProfileOnBuild = (whichNinjaResult.IsSuccess());
|
||||
QString targetBuildPath = QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix);
|
||||
QString launcherTargetName = m_projectInfo.m_projectName + ".GameLauncher";
|
||||
|
||||
@@ -19,16 +19,15 @@ namespace O3DE::ProjectManager
|
||||
// The list of clang C/C++ compiler command lines to validate on the host Linux system
|
||||
const QStringList SupportedClangVersions = {"13", "12", "11", "10", "9", "8", "7", "6.0"};
|
||||
|
||||
AZ::Outcome<QProcessEnvironment, QString> GetCommandLineProcessEnvironment()
|
||||
AZ::Outcome<void, QString> SetupCommandLineProcessEnvironment()
|
||||
{
|
||||
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment());
|
||||
return AZ::Success(currentEnvironment);
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform()
|
||||
{
|
||||
// Validate that cmake is installed and is in the command line
|
||||
auto whichCMakeResult = ProjectUtils::ExecuteCommandResult("which", QStringList{ProjectCMakeCommand}, QProcessEnvironment::systemEnvironment());
|
||||
auto whichCMakeResult = ProjectUtils::ExecuteCommandResult("which", QStringList{ProjectCMakeCommand});
|
||||
if (!whichCMakeResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(QObject::tr("CMake not found. <br><br>"
|
||||
@@ -39,8 +38,8 @@ namespace O3DE::ProjectManager
|
||||
// Look for the first compatible version of clang. The list below will contain the known clang compilers that have been tested for O3DE.
|
||||
for (const QString& supportClangVersion : SupportedClangVersions)
|
||||
{
|
||||
auto whichClangResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang-%1").arg(supportClangVersion)}, QProcessEnvironment::systemEnvironment());
|
||||
auto whichClangPPResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang++-%1").arg(supportClangVersion)}, QProcessEnvironment::systemEnvironment());
|
||||
auto whichClangResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang-%1").arg(supportClangVersion)});
|
||||
auto whichClangPPResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang++-%1").arg(supportClangVersion)});
|
||||
if (whichClangResult.IsSuccess() && whichClangPPResult.IsSuccess())
|
||||
{
|
||||
return AZ::Success(QString("clang-%1").arg(supportClangVersion));
|
||||
@@ -54,7 +53,7 @@ namespace O3DE::ProjectManager
|
||||
|
||||
AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath)
|
||||
{
|
||||
AZ::Outcome processEnvResult = GetCommandLineProcessEnvironment();
|
||||
AZ::Outcome processEnvResult = SetupCommandLineProcessEnvironment();
|
||||
if (!processEnvResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(processEnvResult.GetError());
|
||||
@@ -68,7 +67,6 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
QProcess process;
|
||||
process.setProcessEnvironment(processEnvResult.GetValue());
|
||||
|
||||
// if the project build path is relative, it should be relative to the project path
|
||||
process.setWorkingDirectory(projectPath);
|
||||
@@ -88,7 +86,6 @@ namespace O3DE::ProjectManager
|
||||
return ExecuteCommandResultModalDialog(
|
||||
QString("%1/python/get_python.sh").arg(engineRoot),
|
||||
{},
|
||||
QProcessEnvironment::systemEnvironment(),
|
||||
QObject::tr("Running get_python script..."));
|
||||
}
|
||||
|
||||
|
||||
@@ -19,16 +19,14 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
AZ::Outcome<QString, QString> QueryInstalledCmakeFullPath()
|
||||
{
|
||||
auto environmentRequest = ProjectUtils::GetCommandLineProcessEnvironment();
|
||||
auto environmentRequest = ProjectUtils::SetupCommandLineProcessEnvironment();
|
||||
if (!environmentRequest.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(environmentRequest.GetError());
|
||||
}
|
||||
auto currentEnvironment = environmentRequest.GetValue();
|
||||
|
||||
auto queryCmakeInstalled = ProjectUtils::ExecuteCommandResult("which",
|
||||
QStringList{ProjectCMakeCommand},
|
||||
currentEnvironment);
|
||||
QStringList{ProjectCMakeCommand});
|
||||
if (!queryCmakeInstalled.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(QObject::tr("Unable to detect CMake on this host."));
|
||||
|
||||
@@ -18,28 +18,36 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
namespace ProjectUtils
|
||||
{
|
||||
AZ::Outcome<QProcessEnvironment, QString> GetCommandLineProcessEnvironment()
|
||||
AZ::Outcome<void, QString> SetupCommandLineProcessEnvironment()
|
||||
{
|
||||
// For CMake on Mac, if its installed through home-brew, then it will be installed
|
||||
// under /usr/local/bin, which may not be in the system PATH environment.
|
||||
// Add that path for the command line process so that it will be able to locate
|
||||
// a home-brew installed version of CMake
|
||||
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment());
|
||||
QString pathValue = currentEnvironment.value("PATH");
|
||||
pathValue += ":/usr/local/bin";
|
||||
currentEnvironment.insert("PATH", pathValue);
|
||||
return AZ::Success(currentEnvironment);
|
||||
QString pathEnv = qEnvironmentVariable("PATH");
|
||||
QStringList pathEnvList = pathEnv.split(":");
|
||||
if (!pathEnvList.contains("/usr/local/bin"))
|
||||
{
|
||||
pathEnv += ":/usr/local/bin";
|
||||
if (!qputenv("PATH", pathEnv.toStdString().c_str()))
|
||||
{
|
||||
return AZ::Failure(QObject::tr("Failed to set PATH environment variable"));
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform()
|
||||
{
|
||||
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment());
|
||||
QString pathValue = currentEnvironment.value("PATH");
|
||||
pathValue += ":/usr/local/bin";
|
||||
currentEnvironment.insert("PATH", pathValue);
|
||||
AZ::Outcome processEnvResult = SetupCommandLineProcessEnvironment();
|
||||
if (!processEnvResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(processEnvResult.GetError());
|
||||
}
|
||||
|
||||
// Validate that we have cmake installed first
|
||||
auto queryCmakeInstalled = ExecuteCommandResult("which", QStringList{ProjectCMakeCommand}, currentEnvironment);
|
||||
auto queryCmakeInstalled = ExecuteCommandResult("which", QStringList{ProjectCMakeCommand});
|
||||
if (!queryCmakeInstalled.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(QObject::tr("Unable to detect CMake on this host."));
|
||||
@@ -47,7 +55,7 @@ namespace O3DE::ProjectManager
|
||||
QString cmakeInstalledPath = queryCmakeInstalled.GetValue().split("\n")[0];
|
||||
|
||||
// Query the version of the installed cmake
|
||||
auto queryCmakeVersionQuery = ExecuteCommandResult(cmakeInstalledPath, QStringList{"-version"}, currentEnvironment);
|
||||
auto queryCmakeVersionQuery = ExecuteCommandResult(cmakeInstalledPath, QStringList{"-version"});
|
||||
if (!queryCmakeVersionQuery.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(QObject::tr("Unable to determine the version of CMake on this host."));
|
||||
@@ -55,7 +63,7 @@ namespace O3DE::ProjectManager
|
||||
AZ_TracePrintf("Project Manager", "Cmake version %s detected.", queryCmakeVersionQuery.GetValue().split("\n")[0].toUtf8().constData());
|
||||
|
||||
// Query for the version of xcodebuild (if installed)
|
||||
auto queryXcodeBuildVersion = ExecuteCommandResult("xcodebuild", QStringList{"-version"}, currentEnvironment);
|
||||
auto queryXcodeBuildVersion = ExecuteCommandResult("xcodebuild", QStringList{"-version"});
|
||||
if (!queryCmakeInstalled.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(QObject::tr("Unable to detect XCodeBuilder on this host."));
|
||||
@@ -104,7 +112,6 @@ namespace O3DE::ProjectManager
|
||||
return ExecuteCommandResultModalDialog(
|
||||
QString("%1/python/get_python.sh").arg(engineRoot),
|
||||
{},
|
||||
QProcessEnvironment::systemEnvironment(),
|
||||
QObject::tr("Running get_python script..."));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
namespace ProjectUtils
|
||||
{
|
||||
AZ::Outcome<QProcessEnvironment, QString> GetCommandLineProcessEnvironment()
|
||||
AZ::Outcome<void, QString> SetupCommandLineProcessEnvironment()
|
||||
{
|
||||
// Use the engine path to insert a path for cmake
|
||||
auto engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
|
||||
@@ -31,26 +31,34 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
auto engineInfo = engineInfoResult.GetValue();
|
||||
|
||||
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment());
|
||||
|
||||
// Append cmake path to PATH incase it is missing
|
||||
// Append cmake path to the current environment PATH incase it is missing, since if
|
||||
// we are starting CMake itself the current application needs to find it using Path
|
||||
// This also takes affect for all child processes.
|
||||
QDir cmakePath(engineInfo.m_path);
|
||||
cmakePath.cd("cmake/runtime/bin");
|
||||
QString pathValue = currentEnvironment.value("PATH");
|
||||
pathValue += ";" + cmakePath.path();
|
||||
currentEnvironment.insert("PATH", pathValue);
|
||||
return AZ::Success(currentEnvironment);
|
||||
QString pathEnv = qEnvironmentVariable("Path");
|
||||
QStringList pathEnvList = pathEnv.split(";");
|
||||
if (!pathEnvList.contains(cmakePath.path()))
|
||||
{
|
||||
pathEnv += ";" + cmakePath.path();
|
||||
if (!qputenv("Path", pathEnv.toStdString().c_str()))
|
||||
{
|
||||
return AZ::Failure(QObject::tr("Failed to set Path environment variable"));
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform()
|
||||
{
|
||||
// Validate that cmake is installed
|
||||
auto cmakeProcessEnvResult = GetCommandLineProcessEnvironment();
|
||||
auto cmakeProcessEnvResult = SetupCommandLineProcessEnvironment();
|
||||
if (!cmakeProcessEnvResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(cmakeProcessEnvResult.GetError());
|
||||
}
|
||||
auto cmakeVersionQueryResult = ExecuteCommandResult("cmake", QStringList{"--version"}, cmakeProcessEnvResult.GetValue());
|
||||
auto cmakeVersionQueryResult = ExecuteCommandResult("cmake", QStringList{"--version"});
|
||||
if (!cmakeVersionQueryResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(QObject::tr("CMake not found. \n\n"
|
||||
@@ -104,7 +112,7 @@ namespace O3DE::ProjectManager
|
||||
|
||||
AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath)
|
||||
{
|
||||
AZ::Outcome processEnvResult = GetCommandLineProcessEnvironment();
|
||||
AZ::Outcome processEnvResult = SetupCommandLineProcessEnvironment();
|
||||
if (!processEnvResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(processEnvResult.GetError());
|
||||
@@ -118,7 +126,6 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
QProcess process;
|
||||
process.setProcessEnvironment(processEnvResult.GetValue());
|
||||
|
||||
// if the project build path is relative, it should be relative to the project path
|
||||
process.setWorkingDirectory(projectPath);
|
||||
@@ -139,7 +146,6 @@ namespace O3DE::ProjectManager
|
||||
return ExecuteCommandResultModalDialog(
|
||||
"cmd.exe",
|
||||
QStringList{"/c", batPath},
|
||||
QProcessEnvironment::systemEnvironment(),
|
||||
QObject::tr("Running get_python script..."));
|
||||
}
|
||||
|
||||
@@ -157,7 +163,7 @@ namespace O3DE::ProjectManager
|
||||
.arg(shortcutPath)
|
||||
.arg(targetPath)
|
||||
.arg(arguments.join(' '));
|
||||
auto createShortcutResult = ExecuteCommandResult(cmd, QStringList{"-Command", arg}, QProcessEnvironment::systemEnvironment());
|
||||
auto createShortcutResult = ExecuteCommandResult(cmd, QStringList{"-Command", arg});
|
||||
if (!createShortcutResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(QObject::tr("Failed to create desktop shortcut %1 <br><br>"
|
||||
|
||||
@@ -117,18 +117,16 @@ namespace O3DE::ProjectManager
|
||||
// Show some kind of progress with very approximate estimates
|
||||
UpdateProgress(++m_progressEstimate);
|
||||
|
||||
auto currentEnvironmentRequest = ProjectUtils::GetCommandLineProcessEnvironment();
|
||||
auto currentEnvironmentRequest = ProjectUtils::SetupCommandLineProcessEnvironment();
|
||||
if (!currentEnvironmentRequest.IsSuccess())
|
||||
{
|
||||
QStringToAZTracePrint(currentEnvironmentRequest.GetError());
|
||||
return AZ::Failure(currentEnvironmentRequest.GetError());
|
||||
}
|
||||
QProcessEnvironment currentEnvironment = currentEnvironmentRequest.GetValue();
|
||||
|
||||
m_configProjectProcess = new QProcess(this);
|
||||
m_configProjectProcess->setProcessChannelMode(QProcess::MergedChannels);
|
||||
m_configProjectProcess->setWorkingDirectory(m_projectInfo.m_path);
|
||||
m_configProjectProcess->setProcessEnvironment(currentEnvironment);
|
||||
|
||||
auto cmakeGenerateArgumentsResult = ConstructCmakeGenerateProjectArguments(engineInfo.m_thirdPartyPath);
|
||||
if (!cmakeGenerateArgumentsResult.IsSuccess())
|
||||
@@ -181,7 +179,6 @@ namespace O3DE::ProjectManager
|
||||
m_buildProjectProcess = new QProcess(this);
|
||||
m_buildProjectProcess->setProcessChannelMode(QProcess::MergedChannels);
|
||||
m_buildProjectProcess->setWorkingDirectory(m_projectInfo.m_path);
|
||||
m_buildProjectProcess->setProcessEnvironment(currentEnvironment);
|
||||
|
||||
auto cmakeBuildArgumentsResult = ConstructCmakeBuildCommandArguments();
|
||||
if (!cmakeBuildArgumentsResult.IsSuccess())
|
||||
|
||||
@@ -520,12 +520,10 @@ namespace O3DE::ProjectManager
|
||||
AZ::Outcome<QString, QString> ExecuteCommandResultModalDialog(
|
||||
const QString& cmd,
|
||||
const QStringList& arguments,
|
||||
const QProcessEnvironment& processEnv,
|
||||
const QString& title)
|
||||
{
|
||||
QString resultOutput;
|
||||
QProcess execProcess;
|
||||
execProcess.setProcessEnvironment(processEnv);
|
||||
execProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
QProgressDialog dialog(title, QObject::tr("Cancel"), /*minimum=*/0, /*maximum=*/0);
|
||||
@@ -611,11 +609,9 @@ namespace O3DE::ProjectManager
|
||||
AZ::Outcome<QString, QString> ExecuteCommandResult(
|
||||
const QString& cmd,
|
||||
const QStringList& arguments,
|
||||
const QProcessEnvironment& processEnv,
|
||||
int commandTimeoutSeconds /*= ProjectCommandLineTimeoutSeconds*/)
|
||||
{
|
||||
QProcess execProcess;
|
||||
execProcess.setProcessEnvironment(processEnv);
|
||||
execProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||
execProcess.start(cmd, arguments);
|
||||
if (!execProcess.waitForStarted())
|
||||
|
||||
@@ -47,7 +47,6 @@ namespace O3DE::ProjectManager
|
||||
AZ::Outcome<QString, QString> ExecuteCommandResult(
|
||||
const QString& cmd,
|
||||
const QStringList& arguments,
|
||||
const QProcessEnvironment& processEnv,
|
||||
int commandTimeoutSeconds = ProjectCommandLineTimeoutSeconds);
|
||||
|
||||
/**
|
||||
@@ -61,10 +60,9 @@ namespace O3DE::ProjectManager
|
||||
AZ::Outcome<QString, QString> ExecuteCommandResultModalDialog(
|
||||
const QString& cmd,
|
||||
const QStringList& arguments,
|
||||
const QProcessEnvironment& processEnv,
|
||||
const QString& title);
|
||||
|
||||
AZ::Outcome<QProcessEnvironment, QString> GetCommandLineProcessEnvironment();
|
||||
AZ::Outcome<void, QString> SetupCommandLineProcessEnvironment();
|
||||
AZ::Outcome<QString, QString> GetProjectBuildPath(const QString& projectPath);
|
||||
AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath);
|
||||
AZ::Outcome<QString, QString> RunGetPythonScript(const QString& enginePath);
|
||||
|
||||
@@ -60,6 +60,9 @@ ly_create_alias(
|
||||
)
|
||||
|
||||
if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/Platform/${PAL_PLATFORM_NAME}/PAL_traits_editor_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
|
||||
|
||||
ly_add_target(
|
||||
NAME AWSCore.Editor.Static STATIC
|
||||
NAMESPACE Gem
|
||||
@@ -97,22 +100,31 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
Gem::AWSCore.Editor.Static
|
||||
)
|
||||
|
||||
# This target is not a real gem module
|
||||
# It is not meant to be loaded by the ModuleManager in C++
|
||||
ly_add_target(
|
||||
NAME AWSCore.ResourceMappingTool MODULE
|
||||
NAMESPACE Gem
|
||||
OUTPUT_SUBDIRECTORY AWSCoreEditorQtBin
|
||||
FILES_CMAKE
|
||||
awscore_resourcemappingtool_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Include/Private
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
Gem::AWSCore.Editor.Static
|
||||
)
|
||||
ly_add_dependencies(AWSCore.Editor AWSCore.ResourceMappingTool)
|
||||
if (PAL_TRAIT_ENABLE_RESOURCE_MAPPING_TOOL)
|
||||
|
||||
# This target is not a real gem module
|
||||
# It is not meant to be loaded by the ModuleManager in C++
|
||||
ly_add_target(
|
||||
NAME AWSCore.ResourceMappingTool MODULE
|
||||
NAMESPACE Gem
|
||||
OUTPUT_SUBDIRECTORY AWSCoreEditorQtBin
|
||||
FILES_CMAKE
|
||||
awscore_resourcemappingtool_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Include/Private
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
Gem::AWSCore.Editor.Static
|
||||
RUNTIME_DEPENDENCIES
|
||||
3rdParty::pyside2
|
||||
|
||||
)
|
||||
ly_add_dependencies(AWSCore.Editor AWSCore.ResourceMappingTool)
|
||||
|
||||
ly_install_directory(DIRECTORIES Tools/ResourceMappingTool)
|
||||
|
||||
endif()
|
||||
|
||||
# Builders and Tools (such as the Editor use AWSCore.Editor) use the .Editor module above.
|
||||
ly_create_alias(
|
||||
@@ -154,10 +166,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 +211,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)
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <QAction>
|
||||
#include <QObject>
|
||||
|
||||
#include "AWSCoreEditor_Traits_Platform.h"
|
||||
|
||||
namespace AWSCore
|
||||
{
|
||||
class AWSCoreResourceMappingToolAction
|
||||
@@ -22,7 +24,7 @@ namespace AWSCore
|
||||
static constexpr const char AWSCoreResourceMappingToolActionName[] = "AWSCoreResourceMappingToolAction";
|
||||
static constexpr const char ResourceMappingToolDirectoryPath[] = "Gems/AWSCore/Code/Tools/ResourceMappingTool";
|
||||
static constexpr const char ResourceMappingToolLogDirectoryPath[] = "user/log/";
|
||||
static constexpr const char EngineWindowsPythonEntryScriptPath[] = "python/python.cmd";
|
||||
static constexpr const char EngineWindowsPythonEntryScriptPath[] = AWSCORE_EDITOR_PYTHON_COMMAND;
|
||||
|
||||
AWSCoreResourceMappingToolAction(const QString& text, QObject* parent = nullptr);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -7,4 +7,6 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED 0
|
||||
#define AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED 1
|
||||
#define AWSCORE_EDITOR_PYTHON_DEBUG_ARGUMENT ""
|
||||
#define AWSCORE_EDITOR_PYTHON_COMMAND "python/python.sh"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_ENABLE_RESOURCE_MAPPING_TOOL TRUE)
|
||||
@@ -8,3 +8,5 @@
|
||||
#pragma once
|
||||
|
||||
#define AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED 0
|
||||
#define AWSCORE_EDITOR_PYTHON_DEBUG_ARGUMENT ""
|
||||
#define AWSCORE_EDITOR_PYTHON_COMMAND "python/python.sh"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_ENABLE_RESOURCE_MAPPING_TOOL FALSE)
|
||||
@@ -8,3 +8,5 @@
|
||||
#pragma once
|
||||
|
||||
#define AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED 1
|
||||
#define AWSCORE_EDITOR_PYTHON_DEBUG_ARGUMENT "debug "
|
||||
#define AWSCORE_EDITOR_PYTHON_COMMAND "python/python.cmd"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_ENABLE_RESOURCE_MAPPING_TOOL TRUE)
|
||||
@@ -58,7 +58,7 @@ namespace AWSCore
|
||||
if (m_isDebug)
|
||||
{
|
||||
return AZStd::string::format(
|
||||
"\"%s\" debug -B \"%s\" --binaries-path \"%s\" --debug --profile \"%s\" --config-path \"%s\" --log-path \"%s\"",
|
||||
"\"%s\" " AWSCORE_EDITOR_PYTHON_DEBUG_ARGUMENT "-B \"%s\" --binaries-path \"%s\" --debug --profile \"%s\" --config-path \"%s\" --log-path \"%s\"",
|
||||
m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(),
|
||||
profileName.c_str(), m_toolConfigDirectoryPath.c_str(), m_toolLogDirectoryPath.c_str());
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -39,6 +39,16 @@ Follow cmake instructions to configure your project, for example:
|
||||
```
|
||||
$ python\python.cmd debug Gems\AWSCore\Code\Tools\ResourceMappingTool\resource_mapping_tool.py --binaries_path <PATH_TO_BUILD_FOLDER>\bin\debug\AWSCoreEditorQtBin
|
||||
```
|
||||
* Linux
|
||||
* release mode
|
||||
```
|
||||
$ python/python.sh Gems/AWSCore/Code/Tools/ResourceMappingTool/resource_mapping_tool.py --binaries_path <PATH_TO_BUILD_FOLDER>/bin/profile/AWSCoreEditorQtBin
|
||||
```
|
||||
* debug mode
|
||||
```
|
||||
$ python/python.sh Gems/AWSCore/Code/Tools/ResourceMappingTool/resource_mapping_tool.py --binaries_path <PATH_TO_BUILD_FOLDER>/bin/debug/AWSCoreEditorQtBin
|
||||
```
|
||||
|
||||
* Note - Editor is integrated with the same engine python environment to launch Resource Mapping Tool. If it is failed to launch the tool
|
||||
in Editor, please follow above steps to make sure expected scripts/binaries are present.
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -20,6 +21,7 @@ argument_parser.add_argument('--debug', action='store_true', help='Execute on de
|
||||
argument_parser.add_argument('--log-path', help='Path to resource mapping tool logging directory '
|
||||
'(if not provided, logging file will be located at tool directory)')
|
||||
argument_parser.add_argument('--profile', default='default', help='Named AWS profile to use for querying AWS resources')
|
||||
|
||||
arguments: Namespace = argument_parser.parse_args()
|
||||
|
||||
# logging setup
|
||||
@@ -74,6 +76,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)
|
||||
|
||||
+13
-2
@@ -5,6 +5,7 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
import platform
|
||||
from typing import List
|
||||
from unittest import TestCase
|
||||
from unittest.mock import (ANY, call, MagicMock, patch)
|
||||
@@ -27,14 +28,24 @@ class TestEnvironmentUtils(TestCase):
|
||||
self.addCleanup(os_pathsep_patcher.stop)
|
||||
self._mock_os_pathsep: MagicMock = os_pathsep_patcher.start()
|
||||
|
||||
def test_setup_qt_environment_global_flag_is_set(self) -> None:
|
||||
@patch('os.path.exists')
|
||||
@patch('ctypes.CDLL')
|
||||
def test_setup_qt_environment_global_flag_is_set(self, mock_os_path_exists, mock_ctype_cdll) -> None:
|
||||
mock_os_path_exists.return_value = True
|
||||
environment_utils.setup_qt_environment("dummy")
|
||||
self._mock_os_environ.copy.assert_called_once()
|
||||
self._mock_os_pathsep.join.assert_called_once()
|
||||
assert environment_utils.is_qt_linked() is True
|
||||
if platform.system() == 'Linux':
|
||||
mock_os_path_exists.assert_called()
|
||||
|
||||
def test_cleanup_qt_environment_global_flag_is_set(self) -> None:
|
||||
@patch('os.path.exists')
|
||||
@patch('ctypes.CDLL')
|
||||
def test_cleanup_qt_environment_global_flag_is_set(self, mock_os_path_exists, mock_ctype_cdll) -> None:
|
||||
mock_os_path_exists.return_value = True
|
||||
environment_utils.setup_qt_environment("dummy")
|
||||
assert environment_utils.is_qt_linked() is True
|
||||
environment_utils.cleanup_qt_environment()
|
||||
assert environment_utils.is_qt_linked() is False
|
||||
if platform.system() == 'Linux':
|
||||
mock_os_path_exists.assert_called()
|
||||
|
||||
@@ -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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user