Browse Source

Merge branch 'development' into PR_AP_UuidManagerHookup

# Conflicts:
#	Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp
amzn-mike 2 years ago
parent
commit
2dae24c830
100 changed files with 1888 additions and 1116 deletions
  1. 3 0
      AutomatedTesting/Gem/AssetProcessorGemConfig.setreg
  2. 6 0
      AutomatedTesting/Gem/PythonTests/Atom/tests/MaterialCanvas_Atom_BasicTests.py
  3. 2 2
      AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyAssetEditor.py
  4. 0 0
      AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyCommon.py
  5. 3 3
      AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyO3DEEditor.py
  6. 4 4
      AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyScriptCanvasEditor.py
  7. 2 2
      AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyScriptCanvasNodeInspector.py
  8. 0 0
      AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyScriptCanvasNodePalette.py
  9. 0 0
      AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyScriptCanvasVariableManager.py
  10. 6 0
      AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/__init__.py
  11. 2 1
      AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py
  12. 1 1
      AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_config_backup_fixture.py
  13. 143 100
      AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py
  14. 43 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/CMakeLists.txt
  15. 7 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/__init__.py
  16. 213 190
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/asset_bundler_batch_tests.py
  17. 547 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/Levels/TestDependenciesLevel/TestDependenciesLevel.prefab
  18. 12 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/Levels/TestDependenciesLevel/tags.txt
  19. 3 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/SeedWithDependencies/AMA_Green_01.tif
  20. 3 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/SeedWithDependencies/AMA_Grey_01.tif
  21. 3 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/SeedWithDependencies/AMA_White_01.tif
  22. 564 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/SeedWithDependencies/Canvas1.uicanvas
  23. 3 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/SeedWithDependencies/default1024.font
  24. 3 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/SeedWithDependencies/default2048.font
  25. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/multiple_corrupted_prefab/corrupted_prefab1.prefab
  26. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/multiple_corrupted_prefab/corrupted_prefab2.prefab
  27. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/multiple_working_prefab/working_prefab1.prefab
  28. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/multiple_working_prefab/working_prefab2.prefab
  29. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/single_corrupted_prefab/corrupted_prefab.prefab
  30. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/single_working_prefab/working_prefab.prefab
  31. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/single_working_prefab_override/working_prefab.prefab
  32. 3 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/datfile_0.dat
  33. 3 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/datfile_1.dat
  34. 3 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/datfile_2.dat
  35. 3 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/datfile_3.dat
  36. 3 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/datfile_4.dat
  37. 3 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/datfile_5.dat
  38. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/txtfile_0.txt
  39. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/txtfile_1.txt
  40. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/txtfile_2.txt
  41. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/txtfile_3.txt
  42. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/txtfile_4.txt
  43. 1 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/txtfile_5.txt
  44. 0 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/bundle_mode_in_editor_tests.py
  45. 4 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/bundle_mode_tests.py
  46. 0 0
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/conftest.py
  47. 0 22
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt
  48. 1 1
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests_2.py
  49. 1 1
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/missing_dependency_tests.py
  50. 2 2
      AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/fbx_tests.py
  51. 7 11
      AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/pythonassetbuildertests.py
  52. 1 1
      AutomatedTesting/Gem/PythonTests/scripting/EditMenu_Default_UndoRedo.py
  53. 1 1
      AutomatedTesting/Gem/PythonTests/scripting/NodePalette_HappyPath_ClearSelection.py
  54. 1 1
      AutomatedTesting/Gem/PythonTests/scripting/ScriptEvent_AddRemoveMethod_UpdatesInSC.py
  55. 2 2
      AutomatedTesting/Gem/PythonTests/scripting/VariableManager_ExposeVarsToComponent.py
  56. 1 1
      AutomatedTesting/Gem/PythonTests/scripting/VariableManager_UnpinVariableType_Works.py
  57. 1 1
      CMakeLists.txt
  58. 117 12
      Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp
  59. 0 3
      Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.h
  60. 1 26
      Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui
  61. 2 2
      Code/Editor/CMakeLists.txt
  62. 13 6
      Code/Editor/Controls/FolderTreeCtrl.cpp
  63. 2 14
      Code/Editor/CryEdit.cpp
  64. 0 1
      Code/Editor/CryEdit.h
  65. 0 17
      Code/Editor/Lib/Tests/test_Main.cpp
  66. 1 0
      Code/Editor/LyViewPaneNames.h
  67. 0 1
      Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp
  68. 0 2
      Code/Editor/Plugins/ComponentEntityEditorPlugin/Tests/test_Main.cpp
  69. 6 9
      Code/Editor/PythonEditorFuncs.cpp
  70. 0 3
      Code/Editor/main.cpp
  71. 0 4
      Code/Framework/AtomCore/Tests/InstanceDatabase.cpp
  72. 0 4
      Code/Framework/AtomCore/Tests/Main.cpp
  73. 0 2
      Code/Framework/AzCore/AzCore/AzCoreModule.cpp
  74. 13 69
      Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
  75. 2 12
      Code/Framework/AzCore/AzCore/Component/ComponentApplication.h
  76. 9 6
      Code/Framework/AzCore/AzCore/Component/ComponentApplicationLifecycle.cpp
  77. 7 1
      Code/Framework/AzCore/AzCore/Component/ComponentApplicationLifecycle.h
  78. 9 3
      Code/Framework/AzCore/AzCore/Debug/PerformanceCollector.cpp
  79. 11 3
      Code/Framework/AzCore/AzCore/Debug/PerformanceCollector.h
  80. 0 1
      Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp
  81. 4 5
      Code/Framework/AzCore/AzCore/Memory/AllocationRecords.cpp
  82. 2 1
      Code/Framework/AzCore/AzCore/Memory/AllocatorBase.h
  83. 0 37
      Code/Framework/AzCore/AzCore/Memory/AllocatorInstance.h
  84. 0 131
      Code/Framework/AzCore/AzCore/Memory/MemoryComponent.cpp
  85. 0 58
      Code/Framework/AzCore/AzCore/Memory/MemoryComponent.h
  86. 5 9
      Code/Framework/AzCore/AzCore/Serialization/SerializeContext.cpp
  87. 0 19
      Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h
  88. 0 6
      Code/Framework/AzCore/AzCore/UserSettings/UserSettingsComponent.cpp
  89. 0 2
      Code/Framework/AzCore/AzCore/UserSettings/UserSettingsComponent.h
  90. 0 2
      Code/Framework/AzCore/AzCore/azcore_files.cmake
  91. 0 6
      Code/Framework/AzCore/Tests/AZStd/VariantSerialization.cpp
  92. 0 12
      Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp
  93. 3 14
      Code/Framework/AzCore/Tests/Components.cpp
  94. 0 2
      Code/Framework/AzCore/Tests/DOM/DomFixtures.cpp
  95. 27 0
      Code/Framework/AzCore/Tests/Debug/PerformanceCollectorTests.cpp
  96. 0 4
      Code/Framework/AzCore/Tests/EBus.cpp
  97. 0 12
      Code/Framework/AzCore/Tests/Jobs.cpp
  98. 0 72
      Code/Framework/AzCore/Tests/Memory.cpp
  99. 28 166
      Code/Framework/AzCore/Tests/Memory/AllocatorBenchmarks.cpp
  100. 0 10
      Code/Framework/AzCore/Tests/Memory/HphaAllocator.cpp

+ 3 - 0
AutomatedTesting/Gem/AssetProcessorGemConfig.setreg

@@ -17,6 +17,9 @@
                 "Exclude Restricted AssetProcessorTestAssets": {
                     "glob": "*/asset_processor_tests/restricted/*"
                 },
+                "Exclude AssetBundlerTestAssets": {
+                    "glob": "*/asset_bundler_tests/assets/*"
+                },
                 "Exclude Scene Tests": {
                     "glob": "*/scene_tests/assets/*"
                 }

+ 6 - 0
AutomatedTesting/Gem/PythonTests/Atom/tests/MaterialCanvas_Atom_BasicTests.py

@@ -53,11 +53,17 @@ def MaterialCanvas_BasicFunctionalityChecks_AllChecksPass():
 
     import os
 
+    import azlmbr.atomtools.util
     import Atom.atom_utils.atom_tools_utils as atom_tools_utils
     import Atom.atom_utils.material_canvas_utils as material_canvas_utils
     from editor_python_test_tools.utils import Report, Tracer, TestHelper
 
     with Tracer() as error_tracer:
+        # Disable automatic material and shader generation when opening graphs.
+        azlmbr.atomtools.util.SetSettingsValue_bool("/O3DE/AtomToolsFramework/GraphCompiler/CompileOnOpen", False)
+        azlmbr.atomtools.util.SetSettingsValue_bool("/O3DE/AtomToolsFramework/GraphCompiler/CompileOnSave", False)
+        azlmbr.atomtools.util.SetSettingsValue_bool("/O3DE/AtomToolsFramework/GraphCompiler/CompileOnEdit", False)
+
         # Set constants before starting test steps.
         test_1_material_graph = os.path.join(atom_tools_utils.MATERIALCANVAS_GRAPH_PATH, "test1.materialgraph")
         test_2_material_graph = os.path.join(atom_tools_utils.MATERIALCANVAS_GRAPH_PATH, "test2.materialgraph")

+ 2 - 2
AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPyAssetEditor.py → AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyAssetEditor.py

@@ -8,12 +8,12 @@ Object to house all the Qt Objects and behavior used in testing the asset editor
 """
 
 from editor_python_test_tools.utils import TestHelper as helper
-from PySide2 import QtWidgets, QtCore, QtTest
+from PySide2 import QtWidgets
 import pyside_utils
 import azlmbr.editor as editor
 import azlmbr.bus as bus
 import os
-from editor_python_test_tools.QtPyCommon import QtPyCommon
+from editor_python_test_tools.QtPy.QtPyCommon import QtPyCommon
 from consts.asset_editor import (ASSET_EDITOR_UI, EVENTS_QT, DEFAULT_SCRIPT_EVENT, DEFAULT_METHOD_NAME)
 from consts.general import (WAIT_TIME_SEC_3, SAVE_STRING)
 

+ 0 - 0
AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPyCommon.py → AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyCommon.py


+ 3 - 3
AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPyO3DEEditor.py → AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyO3DEEditor.py

@@ -7,9 +7,9 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
 Object to house all the Qt Objects used when testing and manipulating the O3DE UI
 """
 import pyside_utils
-from editor_python_test_tools.QtPyCommon import QtPyCommon
-from editor_python_test_tools.QtPyScriptCanvasEditor import QtPyScriptCanvasEditor
-from editor_python_test_tools.QtPyAssetEditor import QtPyAssetEditor
+from editor_python_test_tools.QtPy.QtPyCommon import QtPyCommon
+from editor_python_test_tools.QtPy.QtPyScriptCanvasEditor import QtPyScriptCanvasEditor
+from editor_python_test_tools.QtPy.QtPyAssetEditor import QtPyAssetEditor
 import azlmbr.legacy.general as general
 from editor_python_test_tools.utils import TestHelper
 from consts.asset_editor import (ASSET_EDITOR_UI)

+ 4 - 4
AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPyScriptCanvasEditor.py → AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyScriptCanvasEditor.py

@@ -8,10 +8,10 @@ Object to house all the Qt Objects used when testing and manipulating the Script
 """
 from PySide2 import QtWidgets
 import pyside_utils
-from editor_python_test_tools.QtPyCommon import QtPyCommon
-from editor_python_test_tools.QtPyScriptCanvasVariableManager import QtPyScriptCanvasVariableManager
-from editor_python_test_tools.QtPyScriptCanvasNodePalette import QtPyScriptCanvasNodePalette
-from editor_python_test_tools.QtPyScriptCanvasNodeInspector import QtPyScriptCanvasNodeInspector
+from editor_python_test_tools.QtPy.QtPyCommon import QtPyCommon
+from editor_python_test_tools.QtPy.QtPyScriptCanvasVariableManager import QtPyScriptCanvasVariableManager
+from editor_python_test_tools.QtPy.QtPyScriptCanvasNodePalette import QtPyScriptCanvasNodePalette
+from editor_python_test_tools.QtPy.QtPyScriptCanvasNodeInspector import QtPyScriptCanvasNodeInspector
 from consts.scripting import (SCRIPT_CANVAS_UI)
 
 

+ 2 - 2
AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPyScriptCanvasNodeInspector.py → AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyScriptCanvasNodeInspector.py

@@ -10,8 +10,8 @@ Object to house all the Qt Objects and behavior used in testing the script canva
 """
 
 from editor_python_test_tools.utils import TestHelper as helper
-from PySide2 import QtWidgets, QtTest, QtCore
-from editor_python_test_tools.QtPyCommon import CheckBoxStates
+from PySide2 import QtWidgets
+from editor_python_test_tools.QtPy.QtPyCommon import CheckBoxStates
 from consts.scripting import (PROPERTY_EDITOR_QT, INITIAL_VALUE_SOURCE_QT, NODE_INSPECTOR_QT)
 from consts.general import (WAIT_TIME_SEC_3)
 from enum import IntEnum

+ 0 - 0
AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPyScriptCanvasNodePalette.py → AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyScriptCanvasNodePalette.py


+ 0 - 0
AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPyScriptCanvasVariableManager.py → AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/QtPyScriptCanvasVariableManager.py


+ 6 - 0
AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/QtPy/__init__.py

@@ -0,0 +1,6 @@
+"""
+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
+"""

+ 2 - 1
AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py

@@ -190,6 +190,7 @@ class TestHelper:
         with MultiplayerHelper() as multiplayer_helper:
             # enter game-mode. 
             # game-mode in multiplayer will also launch ServerLauncher.exe and connect to the editor
+            general.set_cvar_integer('editorsv_max_connection_attempts', 15)
             multiplayer.PythonEditorFuncs_enter_game_mode()
 
             # make sure the server launcher is running
@@ -200,7 +201,7 @@ class TestHelper:
             TestHelper.wait_for_condition(lambda : multiplayer_helper.editorConnectionAttemptCount > 0, 10.0)
             Report.critical_result(("Multiplayer Editor attempting server connection.", "Multiplayer Editor never tried connecting to the server."), multiplayer_helper.editorConnectionAttemptCount > 0)
 
-            TestHelper.wait_for_condition(lambda : multiplayer_helper.editorSendingLevelData, 10.0)
+            TestHelper.wait_for_condition(lambda : multiplayer_helper.editorSendingLevelData, 106.0)
             Report.critical_result(("Multiplayer Editor sent level data to the server.", "Multiplayer Editor never sent the level to the server."), multiplayer_helper.editorSendingLevelData)
 
             TestHelper.wait_for_condition(lambda : multiplayer_helper.connectToSimulationSuccess, 10.0)

+ 1 - 1
AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_config_backup_fixture.py

@@ -4,7 +4,7 @@ For complete copyright and license terms please see the LICENSE at the root of t
 
 SPDX-License-Identifier: Apache-2.0 OR MIT
 
-Fixture for backing up and restoring dev/AssetProcessorPlatformConfig.ini
+Fixture for backing up and restoring <EngineRoot>\Registry\AssetProcessorPlatformConfig.setreg
 
 """
 

+ 143 - 100
AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py

@@ -17,9 +17,10 @@ import logging
 import zipfile
 from typing import Any, Dict, List
 
-from . import asset_processor_fixture as asset_processor
-from . import timeout_option_fixture as timeout
-from . import ap_config_backup_fixture as config_backup
+from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor
+from assetpipeline.ap_fixtures.timeout_option_fixture import timeout_option_fixture as timeout
+from assetpipeline.ap_fixtures.ap_config_backup_fixture import ap_config_backup_fixture as config_backup
+from assetpipeline.ap_fixtures.ap_setup_fixture import ap_setup_fixture
 
 import ly_test_tools.environment.file_system as fs
 import ly_test_tools.o3de.pipeline_utils as utils
@@ -30,67 +31,102 @@ logger = logging.getLogger(__name__)
 
 @pytest.fixture
 @pytest.mark.usefixtures("config_backup")
-def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) -> Any:
-
-    ALL_PLATFORMS = []
-    for _, value in ASSET_PROCESSOR_PLATFORM_MAP.items():
-        ALL_PLATFORMS.append(value)
-
-    # Set up temporary directory to use for tests
-    tempDir = os.path.join(TF.gettempdir(), "AssetBundlerTempDirectory")
-    if os.path.exists(tempDir):
-        fs.delete([tempDir], True, True)
-    if not os.path.exists(tempDir):
-        os.mkdir(tempDir)
-
-    # Get platforms to build for bundle tests
-    platforms = request.config.getoption("--bundle_platforms")
-    if platforms is not None:
-        # Remove whitespace and split at commas if platforms provided
-        platforms = [platform.strip() for platform in platforms.split(",")]
-    else:
-        # No commandline argument provided, default to mac and pc
-        platforms = ["pc", "mac"]
-
-    class BundlerBatchFixture:
[email protected]("asset_processor")
[email protected]("ap_setup_fixture")
+def bundler_batch_setup_fixture(request, workspace, ap_setup_fixture, asset_processor, timeout) -> Any:
+
+    def get_all_platforms() -> list[str]:
+        """Helper: This function generates a list of all platforms to be built for testing Asset Bundler."""
+        ALL_PLATFORMS = []
+        for _, value in ASSET_PROCESSOR_PLATFORM_MAP.items():
+            ALL_PLATFORMS.append(value)
+        return ALL_PLATFORMS
+
+    def platforms_to_build() -> list | list[str]:
+        """Helper: Gets the platforms to build for bundle tests."""
+        platforms = request.config.getoption("--bundle_platforms")
+        if platforms is not None:
+            # Remove whitespace and split at commas if platforms provided
+            platforms = [platform.strip() for platform in platforms.split(",")]
+        else:
+            # No commandline argument provided, default to mac and pc
+            platforms = ["pc", "mac"]
+        return platforms
+
+    def setup_temp_workspace() -> None:
+        """Helper: Sets up the temp workspace for asset bundling tests."""
+        asset_processor.create_temp_asset_root()
+
+    def setup_temp_dir() -> Any:
+        """Helper: Sets up a temp directory for use in bundling tests that can't use the temp workspace."""
+        tempDir = os.path.join(TF.gettempdir(), "AssetBundlerTempDirectory")
+        if os.path.exists(tempDir):
+            fs.delete([tempDir], True, True)
+        if not os.path.exists(tempDir):
+            os.mkdir(tempDir)
+        return tempDir
+
+    class WorkSpaceBundlerBatchFixture:
         """
         Houses useful variables and functions for running Asset Bundler Batch Tests
         """
-
         def __init__(self):
             self.bin_dir = workspace.paths.build_directory()
             self.bundler_batch = os.path.join(self.bin_dir, "AssetBundlerBatch")
-            self.test_dir = tempDir
-            self.asset_alias = workspace.paths.platform_cache()
-            self.tools_dir = os.path.join(workspace.paths.engine_root(), "Tools")
             self.seed_list_file_name = "testSeedListFile.seed"
-            self.seed_list_file = os.path.join(self.test_dir, self.seed_list_file_name)
             self.asset_info_file_name = "assetFileInfo.assetlist"
-            self.asset_info_file_request = os.path.join(self.test_dir, self.asset_info_file_name)
-            self.bundle_settings_file_request = os.path.join(self.test_dir, "bundleSettingsFile.bundlesettings")
             self.bundle_file_name = "bundle.pak"
-            self.bundle_file = os.path.join(self.test_dir, self.bundle_file_name)
-            self.asset_info_file_result = os.path.join(
-                self.test_dir, self.platform_file_name(self.asset_info_file_name,
-                                                       workspace.asset_processor_platform)
-            )
-            self.bundle_settings_file_result = os.path.join(
-                self.test_dir, self.platform_file_name("bundleSettingsFile.bundlesettings",
-                                                       workspace.asset_processor_platform)
-            )
+            self.bundle_settings_file_name = "bundleSettingsFile.bundlesettings"
+            self.workspace = workspace
+            self.platforms = platforms_to_build()
+            self.platforms_as_string = ",".join(self.platforms)
+
             # Useful sizes
             self.max_bundle_size_in_mib = 35
             self.number_of_bytes_in_mib = 1024 * 1024
-            self.workspace = workspace
-            self.platforms = platforms
-            self.platforms_as_string = ",".join(platforms)
-
-        # *** Bundler-batch-calling helpers ***
 
-        def call_asset_bundler(self, arg_list):                 
-            # Print out the call to asset bundler, so if an error occurs, the commands that were run can be repeated.
-            # Split out the list to something that can be easily copy and pasted. Printing a list by default will put it in,
-            # [comma, separated, braces], this join will instead print each arg in the list with only a space between them.
+            # Checks whether or not the fixture was parametrized to use the temp workspace. Defaults to True.
+            self.use_temp_workspace = request.param if hasattr(request, "param") else True
+
+            if self.use_temp_workspace:
+                setup_temp_workspace()
+                self.project_path = os.path.join(asset_processor.temp_asset_root(), workspace.project)
+                self.cache = asset_processor.temp_project_cache_path()
+                self.seed_list_file = os.path.join(self.project_path, self.seed_list_file_name)
+                self.asset_info_file_request = os.path.join(self.project_path, self.asset_info_file_name)
+                self.bundle_settings_file_request = os.path.join(self.project_path, self.bundle_settings_file_name)
+                self.bundle_file = os.path.join(self.project_path, self.bundle_file_name)
+                self.asset_info_file_result = os.path.join(
+                    self.project_path, self.platform_file_name(self.asset_info_file_name,
+                                                               workspace.asset_processor_platform)
+                )
+                self.bundle_settings_file_result = os.path.join(
+                    self.project_path, self.platform_file_name(self.bundle_settings_file_name,
+                                                               workspace.asset_processor_platform)
+                )
+
+            else:
+                self.project_path = workspace.paths.project()
+                self.cache = workspace.paths.project_cache()
+                self.test_dir = setup_temp_dir()
+                self.seed_list_file = os.path.join(self.test_dir, self.seed_list_file_name)
+                self.asset_info_file_request = os.path.join(self.test_dir, self.asset_info_file_name)
+                self.bundle_settings_file_request = os.path.join(self.test_dir, self.bundle_settings_file_name)
+                self.bundle_file = os.path.join(self.test_dir, self.bundle_file_name)
+                self.asset_info_file_result = os.path.join(
+                    self.test_dir, self.platform_file_name(self.asset_info_file_name,
+                                                           workspace.asset_processor_platform)
+                )
+                self.bundle_settings_file_result = os.path.join(
+                    self.test_dir, self.platform_file_name(self.bundle_settings_file_name,
+                                                           workspace.asset_processor_platform)
+                )
+
+        @staticmethod
+        def call_asset_bundler(arg_list):
+            """
+            Prints out the call to asset bundler, so if an error occurs, the commands that were run can be repeated.
+            """
             logger.info(f"{' '.join(f'arg_list{x}' for x in arg_list)}")
             try:
                 output = subprocess.check_output(arg_list).decode()
@@ -103,48 +139,48 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
                 logger.error(f"File Not Found - Failed to call AssetBundlerBatch with args {arg_list} with error {e}")
                 raise e
 
-        def call_bundlerbatch(self, **kwargs: Dict[str, str]):
+        def call_bundlerbatch(self, **kwargs: Dict[str, str]) -> tuple[bool, str] | tuple[bool, Any]:
             """Helper function for calling assetbundlerbatch with no sub-command"""
             cmd = [self.bundler_batch]
             return self.call_asset_bundler(self._append_arguments(cmd, kwargs))
 
-        def call_seeds(self, **kwargs: Dict[str, str]) -> None:
+        def call_seeds(self, **kwargs: Dict[str, str]) -> tuple[bool, str] | tuple[bool, Any]:
             """Helper function for calling assetbundlerbatch with 'seeds' sub-command"""
 
             cmd = [self.bundler_batch, "seeds"]
             return self.call_asset_bundler(self._append_arguments(cmd, kwargs))
 
-        def call_assetLists(self, **kwargs: Dict) -> None:
+        def call_assetLists(self, **kwargs: Dict) -> tuple[bool, str] | tuple[bool, Any]:
             """Helper function for calling assetbundlerbatch with 'assetLists' sub-command"""
 
             cmd = [self.bundler_batch, "assetLists"]
             return self.call_asset_bundler(self._append_arguments(cmd, kwargs))
 
-        def call_comparisonRules(self, **kwargs: Dict) -> None:
+        def call_comparisonRules(self, **kwargs: Dict) -> tuple[bool, str] | tuple[bool, Any]:
             """Helper function for calling assetbundlerbatch with 'comparisonRules' sub-command"""
 
             cmd = [self.bundler_batch, "comparisonRules"]
             return self.call_asset_bundler(self._append_arguments(cmd, kwargs))
 
-        def call_compare(self, **kwargs: Dict) -> None:
+        def call_compare(self, **kwargs: Dict) -> tuple[bool, str] | tuple[bool, Any]:
             """Helper function for calling assetbundlerbatch with 'compare' sub-command"""
 
             cmd = [self.bundler_batch, "compare"]
             return self.call_asset_bundler(self._append_arguments(cmd, kwargs))
 
-        def call_bundleSettings(self, **kwargs: Dict) -> None:
+        def call_bundleSettings(self, **kwargs: Dict) -> tuple[bool, str] | tuple[bool, Any]:
             """Helper function for calling assetbundlerbatch with 'bundleSettings' sub-command"""
 
             cmd = [self.bundler_batch, "bundleSettings"]
             return self.call_asset_bundler(self._append_arguments(cmd, kwargs))
 
-        def call_bundles(self, **kwargs: Dict) -> None:
+        def call_bundles(self, **kwargs: Dict) -> tuple[bool, str] | tuple[bool, Any]:
             """Helper function for calling assetbundlerbatch with 'bundles' sub-command"""
 
             cmd = [self.bundler_batch, "bundles"]
             return self.call_asset_bundler(self._append_arguments(cmd, kwargs))
 
-        def call_bundleSeed(self, **kwargs: Dict) -> None:
+        def call_bundleSeed(self, **kwargs: Dict) -> tuple[bool, str] | tuple[bool, Any]:
             """Helper function for calling assetbundlerbatch with 'bundleSeed' sub-command"""
 
             cmd = [self.bundler_batch, "bundleSeed"]
@@ -153,17 +189,22 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
         def _append_arguments(self, cmd: List[str], kwargs: Dict, append_defaults: bool = True) -> List[str]:
             """Appends and returns all keyword arguments to the list of string [cmd]"""
             for key, value in kwargs.items():
-                if value:
-                    cmd.append(f"--{key}={value}")
-                else:
+                if not value:
                     cmd.append(f"--{key}")
+
+                else:
+                    if type(value) != list:
+                        cmd.append(f"--{key}={value}")
+                    else:
+                        for item in value:
+                            cmd.append(f"--{key}={item}")
+
             if append_defaults:
-                cmd.append(f"--project-path={workspace.paths.project()}")
+                cmd.append(f"--project-path={self.project_path}")
             return cmd
 
-        # ******
-
-        def get_seed_relative_paths(self, seed_file: str) -> str:
+        @staticmethod
+        def get_seed_relative_paths(seed_file: str) -> str:
             """Iterates all asset relative paths in the [seed_file]."""
             assert seed_file.endswith(".seed"), f"file {seed_file} is not a seed file"
             # Get value from all XML nodes who are grandchildren of all Class tags and have
@@ -171,7 +212,8 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
             for node in ET.parse(seed_file).getroot().findall(r"./Class/Class/*[@field='pathHint']"):
                 yield node.attrib["value"]
 
-        def get_seed_relative_paths_for_platform(self, seed_file: str, platform_flags : int) -> str:
+        @staticmethod
+        def get_seed_relative_paths_for_platform(seed_file: str, platform_flags: int) -> list[str]:
             """Iterates all asset relative paths in the [seed_file] which match the platform flags"""
             assert seed_file.endswith(".seed"), f"file {seed_file} is not a seed file"
             # Get value from all XML nodes who are grandchildren of all Class tags and have
@@ -182,30 +224,32 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
             root = data.getroot()
             seedFileRootNode = root.find("Class")
             for seedFileInfoNode in seedFileRootNode.findall("*"):
-                if (int(seedFileInfoNode.find('./Class[@field="platformFlags"]').attrib["value"]) & platform_flags ):
+                if (int(seedFileInfoNode.find('./Class[@field="platformFlags"]').attrib["value"]) & platform_flags):
                     pathHint = seedFileInfoNode.find('./Class[@field="pathHint"]').attrib["value"]
                     seedFileListContents.append(pathHint)
             return seedFileListContents
 
-        def get_asset_relative_paths(self, asset_list_file: str) -> str:
+        @staticmethod
+        def get_asset_relative_paths(asset_list_file: str) -> str:
             """Iterates all asset relative paths in the [asset_list_file]."""
             assert asset_list_file.endswith(".assetlist"), f"file {asset_list_file} is not an assetlist file"
             # Get value from all XML nodes who are great-grandchildren of all Class tags and have
             # a field attr. equal to "assetRelativePath"
-            # fmt:off
+
             for node in (ET.parse(asset_list_file).getroot().findall(
                     r"./Class/Class/Class/*[@field='assetRelativePath']")):
                 yield node.attrib["value"]
-            # fmt:on
 
-        def get_dependent_bundle_names(self, manifest_file: str) -> str:
+        @staticmethod
+        def get_dependent_bundle_names(manifest_file: str) -> str:
             """Iterates all dependent bundle names in the [manifest_file]"""
             assert manifest_file.endswith(".xml"), f"File {manifest_file} does not have an XML extension"
             # Get value from all XML nodes whose parent field attr. is "DependentBundleNames" and whose tag is Class
             for node in ET.parse(manifest_file).getroot().findall(r".//*[@field='DependentBundleNames']/Class"):
                 yield node.attrib["value"]
 
-        def platform_file_name(self, file_name: str, platform: str) -> str:
+        @staticmethod
+        def platform_file_name(file_name: str, platform: str) -> str:
             """Converts the standard [file_name] to a platform specific file name"""
             split = file_name.split(".", 1)
             platform_name = ASSET_PROCESSOR_PLATFORM_MAP.get(platform)
@@ -214,14 +258,16 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
                 return file_name
             return f'{split[0]}_{platform_name}.{split[1]}'
 
-        def extract_file_content(self, bundle_file: str, file_name_to_extract: str) -> str:
-            """Extract the contents of a single file from a bundle"""
+        @staticmethod
+        def extract_file_content(bundle_file: str, file_name_to_extract: str) -> bytes:
+            """Extract the contents of a single file from a bundle as a ByteString."""
 
             with zipfile.ZipFile(bundle_file) as bundle_zip:
                 with bundle_zip.open(file_name_to_extract, "r") as extracted_file:
                     return extracted_file.read()
 
-        def get_crc_of_files_in_archive(self, archive_name: str) -> Dict[str, int]:
+        @staticmethod
+        def get_crc_of_files_in_archive(archive_name: str) -> Dict[str, int]:
             """
             Extracts the CRC-32 'checksum' for all files in the archive as dictionary.
             The returned dictionary will have:
@@ -234,17 +280,20 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
                 file_crcs[info.filename] = info.CRC
             return file_crcs
 
-        def get_platform_flag(self, platform_name: str) -> int:
-            if (platform_name == "pc"):
-                return 1
-            elif (platform_name == "android"):
-                return 2
-            elif (platform_name == "ios"):
-                return 4
-            elif (platform_name == "mac"):
-                return 8
-            elif (platform_name == "server"):
-                return 128
+        @staticmethod
+        def get_platform_flag(platform_name: str) -> int:
+            """ Helper to fetch the platform flag from a provided platform name. """
+            platform_flags = {
+                "pc": 1,
+                "android": 2,
+                "ios": 4,
+                "mac": 8,
+                "server": 128
+            }
+            if platform_name in platform_flags:
+                return platform_flags.get(platform_name)
+            raise ValueError(f"{platform_name} not found within expected platform flags. "
+                             f"Expected: {platform_flags.keys()}")
 
         def extract_and_check(self, extract_dir: str, bundle_file: str) -> None:
             """
@@ -287,7 +336,8 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
             # Ensure that all assets were present in the bundles
             assert sorted(assets_from_file) == sorted(assets_in_disk)
 
-        def _get_platform_flags(self) -> Dict[str, int]:
+        @staticmethod
+        def _get_platform_flags() -> Dict[str, int]:
             """
             Extract platform numeric values from the file that declares them (PlatformDefaults.h):
             Platform Flags are defined in the C header file, where ORDER MATTERS.
@@ -324,7 +374,10 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
 
         def teardown(self) -> None:
             """Destroys the temporary directory used in this test"""
-            fs.delete([self.test_dir], True, True)
+            if self.use_temp_workspace:
+                fs.delete([asset_processor.temp_asset_root()], True, True)
+            else:
+                fs.delete([self.test_dir], True, True)
 
         def __getitem__(self, item: str) -> str:
             """Get Item overload to use the object like a dictionary.
@@ -333,19 +386,9 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
 
     # End class BundlerBatchFixture
 
-    bundler_batch_fixture = BundlerBatchFixture()
+    bundler_batch_fixture = WorkSpaceBundlerBatchFixture()
     request.addfinalizer(bundler_batch_fixture.teardown)
 
     bundler_batch_fixture.platform_values = bundler_batch_fixture._get_platform_flags()
 
-    # Enable platforms accepted from command line
-    platforms_list = [platform for platform in platforms if platform in ALL_PLATFORMS]
-
-    # Run a full scan to ENSURE that both caches (pc and osx) are COMPLETELY POPULATED
-    # Needed for asset bundling
-    # fmt:off
-    assert asset_processor.batch_process(fastscan=True, timeout=timeout * len(platforms), platforms=platforms_list), \
-        "AP Batch failed to process in bundler_batch_fixture"
-    # fmt:on
-
     return bundler_batch_fixture  # Return the fixture

+ 43 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/CMakeLists.txt

@@ -0,0 +1,43 @@
+#
+# 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
+#
+#
+
+if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
+## AP Python Tests ##
+
+## Non-Linux Tests ##
+
+    set(SUPPORTED_PLATFORMS "Windows" "Mac")
+    if (NOT "${PAL_PLATFORM_NAME}" IN_LIST SUPPORTED_PLATFORMS)
+        return()
+    endif()
+
+## Periodic Tests ##
+
+    ly_add_pytest(
+        NAME APTests.AssetBundler
+        PATH ${CMAKE_CURRENT_LIST_DIR}/asset_bundler_batch_tests.py
+        TEST_SERIAL 
+        TEST_SUITE periodic
+        RUNTIME_DEPENDENCIES
+            AZ::AssetProcessor
+            AZ::AssetBundlerBatch
+    )
+
+    ly_add_pytest(
+        NAME APTests.BundleMode
+        PATH ${CMAKE_CURRENT_LIST_DIR}/bundle_mode_tests.py
+        TEST_SERIAL
+        TEST_SUITE periodic
+        RUNTIME_DEPENDENCIES
+            AZ::AssetProcessor
+            AZ::AssetBundlerBatch
+            Legacy::Editor
+            AutomatedTesting.Assets
+    )
+
+endif()

+ 7 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/__init__.py

@@ -0,0 +1,7 @@
+#
+# 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
+#
+#

+ 213 - 190
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py → AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/asset_bundler_batch_tests.py

@@ -4,7 +4,7 @@ For complete copyright and license terms please see the LICENSE at the root of t
 
 SPDX-License-Identifier: Apache-2.0 OR MIT
 
-General Asset Bundler Batch Tests
+Asset Bundler Batch Tests that can be run in the temp workspace.
 """
 
 # Import builtin libraries
@@ -25,10 +25,10 @@ from ..ap_fixtures.ap_setup_fixture import ap_setup_fixture as ap_setup_fixture
 from ..ap_fixtures.asset_processor_fixture import asset_processor
 from ..ap_fixtures.timeout_option_fixture import timeout_option_fixture as timeout
 
-# fmt:off
+
 from ..ap_fixtures.bundler_batch_setup_fixture \
     import bundler_batch_setup_fixture as bundler_batch_helper
-# fmt:on
+
 from ..ap_fixtures.ap_config_backup_fixture import ap_config_backup_fixture as config_backup
 
 # Import LyShared
@@ -54,7 +54,7 @@ targetProjects = ["AutomatedTesting"]
 
 @pytest.fixture
 def local_resources(request, workspace, ap_setup_fixture):
-    # Test-level asset folder. Directory contains a subfolder for each test (i.e. C1234567)
+    """ Test-level asset folder. Directory contains a sub-folder for each test (i.e. C1234567) """
     ap_setup_fixture["tests_dir"] = os.path.dirname(os.path.realpath(__file__))
 
 
@@ -67,6 +67,13 @@ class TestsAssetBundlerBatch(object):
     Asset Bundler Batch Tests for all platforms
     """
 
+    @staticmethod
+    def ap_prepare_test_environment(test_folder_name, asset_processor, ap_setup_fixture):
+        """Helper: Prepares the test environment; copies test files to the project in the current root, then runs AP."""
+        asset_processor.prepare_test_environment(ap_setup_fixture["tests_dir"], test_folder_name, use_current_root=True)
+        ap_result, _ = asset_processor.batch_process(platforms="pc,mac")
+        assert ap_result, "Asset Processor failed to process test assets."
+
     @pytest.mark.BAT
     @pytest.mark.assetpipeline
     @pytest.mark.test_case_id("C16877174")
@@ -92,7 +99,7 @@ class TestsAssetBundlerBatch(object):
     @pytest.mark.BAT
     @pytest.mark.assetpipeline
     @pytest.mark.test_case_id("C16877175")
-    def test_GenerateDebugInfo_DoesNotEffectOutputFile(self, workspace, bundler_batch_helper):
+    def test_GenerateDebugInfo_DoesNotEffectOutputFile(self, workspace, asset_processor, ap_setup_fixture, bundler_batch_helper):
         """
         Validates destructive overwriting for asset lists and
         that generating debug information does not affect asset list creation
@@ -106,17 +113,28 @@ class TestsAssetBundlerBatch(object):
         7. Attempt to create a new asset list without debug while allowing overwrites
         8. Verify that file contents of the originally created asset list changed from what was stored in memory
         """
+        # Test Setup:
+        test_folder_name = "asset_bundler_test_assets"
         helper = bundler_batch_helper
-        seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed")  # Engine seed list
-        asset = r"levels\testdependencieslevel\testdependencieslevel.spawnable"
+        self.ap_prepare_test_environment(test_folder_name, asset_processor, ap_setup_fixture)
+        seed_asset = os.path.join(asset_processor.project_test_cache_folder(), "txtfile_0.txt")
+        additional_seed_asset = os.path.join(asset_processor.project_test_cache_folder(), "txtfile_1.txt")
+        # Test Setup Ends
 
-        # Create Asset list
+        #Create a seedlist file to use in the test.
+        helper.call_seeds(
+            seedListFile=helper["seed_list_file"],
+            addSeed=seed_asset,
+            platform="pc"
+        )
+
+        #Create an assetlist using the previously created seedlist
         helper.call_assetLists(
-            seedListFile=seed_list,
-            assetListFile=helper['asset_info_file_request'],
+            seedListFile=helper["seed_list_file"],
+            assetListFile=helper["asset_info_file_request"]
         )
 
-        # Validate file was created
+        # Validate the assetlist file was created
         assert os.path.isfile(helper["asset_info_file_result"])
 
         # Read asset list contents to compare before and after destructive overwrite
@@ -125,30 +143,29 @@ class TestsAssetBundlerBatch(object):
 
         # Make sure destructive overwrite will fail without --allowOverwrites
         # Try overwriting the existing file without --allowOverwrites (should fail)
-        result, _ = helper.call_assetLists(seedListFile=seed_list, addSeed=asset,
-                                           assetListFile=helper["asset_info_file_request"])
+        result, _ = helper.call_assetLists(
+            seedListFile=helper["seed_list_file"],
+            addSeed=additional_seed_asset,
+            assetListFile=helper["asset_info_file_request"]
+        )
         assert result is False, "Destructive overwrite without override DID NOT fail"
 
         # Make sure file contents DID NOT change
-        # fmt:off
         with open(helper["asset_info_file_result"], "r") as asset_list_file:
             assert file_contents == asset_list_file.read(), \
                 "File was changed even though the Destructive overwrite failed without override."
-        # fmt:on
 
         # Create the asset list file without generating debug info (and overwriting existing file)
         helper.call_assetLists(
-            addSeed=asset,
+            addSeed=additional_seed_asset,
             assetListFile=helper["asset_info_file_request"],
             allowOverwrites=""
         )
 
         # Make sure file contents DID change
-        # fmt:off
         with open(helper["asset_info_file_result"], "r") as asset_list_file:
             assert file_contents != asset_list_file.read(), \
                 "File was NOT changed even though the Destructive overwrite was allowed."
-        # fmt:on
 
         # Get list of all files (relative paths) in generated asset list (no debug file created)
         assets_generated_without_debug_info = []
@@ -157,7 +174,7 @@ class TestsAssetBundlerBatch(object):
 
         # Create the asset list file while also generating debug info
         helper.call_assetLists(
-            addSeed=asset,
+            addSeed=additional_seed_asset,
             allowOverwrites="",
             generateDebugFile="",
             assetListFile=helper["asset_info_file_request"]
@@ -176,7 +193,7 @@ class TestsAssetBundlerBatch(object):
     @pytest.mark.assetpipeline
     @pytest.mark.test_case_id("C16877175")
     @pytest.mark.test_case_id("C16877177")
-    def test_BundlesAndBundleSettings_EquivalentOutput(self, workspace, bundler_batch_helper):
+    def test_BundlesAndBundleSettings_EquivalentOutput(self, workspace, asset_processor, ap_setup_fixture, bundler_batch_helper):
         """
         Validates bundle creation both through the 'bundles' and 'bundlesettings'
         subcommands.
@@ -186,31 +203,31 @@ class TestsAssetBundlerBatch(object):
         2. Create a bundle with the asset list and without a bundle settings file
         3. Create a bundle with the asset list and a bundle settings file
         4. Validate calling bundle doesn't perform destructive overwrite without --allowOverwrites
-        5. Calling bundle again with --alowOverwrites performs destructive overwrite
+        5. Calling bundle again with --allowOverwrites performs destructive overwrite
         6. Validate contents of original bundle and overwritten bundle
         """
+        test_folder_name = "asset_bundler_test_assets"
         helper = bundler_batch_helper
+        self.ap_prepare_test_environment(test_folder_name, asset_processor, ap_setup_fixture)
+        seed_asset = os.path.join(asset_processor.project_test_cache_folder(), "txtfile_0.txt")
         seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed")  # Engine seed list
-        asset = r"levels\testdependencieslevel\testdependencieslevel.spawnable"
 
         # Useful bundle locations / names (2 for comparing contents)
-        # fmt:off
         platform_bundle_file_1 = os.path.join(
-            helper["test_dir"],
+            helper["project_path"],
             helper.platform_file_name(helper["bundle_file_name"], workspace.asset_processor_platform))
 
-        second_bundle_file_request = os.path.join(helper["test_dir"], "bundle_2.pak")
+        second_bundle_file_request = os.path.join(helper["project_path"], "bundle_2.pak")
         platform_bundle_file_2 = os.path.join(
-            helper["test_dir"], helper.platform_file_name("bundle_2.pak", workspace.asset_processor_platform))
-        # fmt:on
+            helper["project_path"], helper.platform_file_name("bundle_2.pak", workspace.asset_processor_platform))
 
         # Extraction directories
-        extract_dir_1 = os.path.join(helper["test_dir"], "ExtractDir1")
-        extract_dir_2 = os.path.join(helper["test_dir"], "ExtractDir2")
+        extract_dir_1 = os.path.join(helper["project_path"], "ExtractDir1")
+        extract_dir_2 = os.path.join(helper["project_path"], "ExtractDir2")
 
         # Create asset list to test bundles on
         helper.call_assetLists(
-            addSeed=asset,
+            addSeed=seed_asset,
             seedListFile=seed_list,
             assetListFile=helper["asset_info_file_request"],
         )
@@ -266,8 +283,11 @@ class TestsAssetBundlerBatch(object):
     @pytest.mark.assetpipeline
     @pytest.mark.test_case_id("C16877175")
     @pytest.mark.test_case_id("C16877177")
-    def test_CreateMultiPlatformBundles_ValidContents(self, workspace, bundler_batch_helper):
+    @pytest.mark.skip(reason="https://github.com/o3de/o3de/issues/14062")
+    def test_CreateMultiPlatformBundles_ValidContents(self, workspace, bundler_batch_helper, asset_processor, ap_setup_fixture):
         """
+        Skip reason: O3DE/O3DE#14062 and O3DE/O3DE#14060
+
         Creates bundles using the same asset list and compares that they are created equally. Also
         validates that platform bundles exclude/include an expected file. (excluded for WIN, included for MAC)
 
@@ -281,45 +301,57 @@ class TestsAssetBundlerBatch(object):
         7. Verify that files were generated
         8. Verify original bundle checksums are equal to new bundle checksums
         """
+        # Test Setup Start
+        test_folder_name = "asset_bundler_test_assets"
         helper = bundler_batch_helper
-        # fmt:off
-        assert "pc" in helper["platforms"] and "mac" in helper["platforms"], \
-            "This test requires both PC and MAC platforms to be enabled. " \
-            "Please rerun with commandline option: '--bundle_platforms=pc,mac'"
-        # fmt:on
-
-        # Engine seed list
-        seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed")
-
-        # Useful bundle / asset list locations
+        self.ap_prepare_test_environment(test_folder_name, asset_processor, ap_setup_fixture)
+        seed_assets = [os.path.join(asset_processor.project_test_cache_folder(), seed_file) for seed_file in
+                       os.listdir(asset_processor.project_test_cache_folder())]
+        asset_list = helper["asset_info_file_request"]
+        seed_list = helper["seed_list_file"]
         bundle_dir = os.path.dirname(helper["bundle_file"])
         bundle_files = {}
         duplicate_bundle_files = {}
         for platform in helper["platforms"]:
             bundle_files[platform] = os.path.join(
-                bundle_dir,
-                helper.platform_file_name("bundle.pak", platforms[platform])
-            )
+                bundle_dir, helper.platform_file_name("bundle.pak", platforms[platform]))
             duplicate_bundle_files[platform] = os.path.join(
-                bundle_dir,
-                helper.platform_file_name("duplicateBundle.pak", platforms[platform])
-            )
+                bundle_dir, helper.platform_file_name("duplicateBundle.pak", platforms[platform]))
 
-        duplicate_asset_info_file_request = os.path.join(helper["test_dir"], "duplicateAssetFileInfo.assetlist")
-        duplicate_bundle_file = os.path.join(helper["test_dir"], "duplicateBundle.pak")
+        duplicate_asset_info_file_request = os.path.join(
+            helper["project_path"], "duplicateAssetFileInfo.assetlist")
+        duplicate_bundle_file = os.path.join(
+            helper["project_path"], "duplicateBundle.pak")
+        # Test Setup Ends
+
+        assert "pc" in helper["platforms"] and "mac" in helper["platforms"], \
+            "This test requires both PC and MAC platforms to be enabled. " \
+            "Please rerun with commandline option: '--bundle_platforms=pc,mac'"
 
-        # Create an asset list to work with
+        helper.call_seeds(
+            seedListFile=seed_list,
+            addSeed=seed_assets,
+            platform="pc,mac"
+        )
         helper.call_assetLists(
             seedListFile=seed_list,
-            assetListFile=helper["asset_info_file_request"],
-            platform=helper["platforms_as_string"],
+            assetListFile=asset_list,
+            platform="pc",
+        )
+        helper.call_assetLists(
+            seedListFile=seed_list,
+            assetListFile=asset_list,
+            platform="mac",
         )
-
-        # Create bundles for both pc and mac
         helper.call_bundles(
-            assetListFile=helper["asset_info_file_request"],
+            assetListFile=asset_list,
             outputBundlePath=helper["bundle_file"],
-            platform=helper["platforms_as_string"],
+            platform="pc",
+        )
+        helper.call_bundles(
+            assetListFile=asset_list,
+            outputBundlePath=helper["bundle_file"],
+            platform="mac",
         )
 
         # Ensure that the bundles were created
@@ -327,21 +359,21 @@ class TestsAssetBundlerBatch(object):
             assert os.path.isfile(bundle_file)
 
         # This asset is created both on mac and windows platform
-        file_to_check = b"engineassets/textures/Cubemap/default_level_cubemap.tif"  # [use byte str because file is in binary]
+        file_to_check = b"asset_bundler_test_assets/txtfile_0.txt"  # [use byte str because file is in binary]
 
         # Extract the delta catalog file from pc archive. {file_to_check} SHOULD NOT be present for PC
         file_contents = helper.extract_file_content(bundle_files["pc"], "DeltaCatalog.xml")
-        # fmt:off
+
         assert file_contents.find(file_to_check), \
             f"{file_to_check} was found in DeltaCatalog.xml in pc bundle file {bundle_files['pc']}"
-        # fmt:on
+
 
         # Extract the delta catalog file from mac archive. {file_to_check} SHOULD be present for MAC
         file_contents = helper.extract_file_content(bundle_files["mac"], "DeltaCatalog.xml")
-        # fmt:off
+
         assert file_contents.find(file_to_check), \
             f"{file_to_check} was not found in DeltaCatalog.xml in darwin bundle file {bundle_files['mac']}"
-        # fmt:on
+
 
         # Gather checksums for first set of bundles
         check_sums_before = {}
@@ -367,10 +399,9 @@ class TestsAssetBundlerBatch(object):
         # Make sure all files were created as expected
         for platform in helper["platforms"]:
             assert os.path.isfile(bundle_files[platform]), f"File: {bundle_files[platform]} was not created"
-            # fmt:off
+
             assert os.path.isfile(duplicate_bundle_files[platform]), \
                 f"File: {duplicate_bundle_files[platform]} was not created"
-            # fmt:on
 
         # Get original bundles' contents again
         check_sums_after = {}
@@ -381,17 +412,17 @@ class TestsAssetBundlerBatch(object):
 
         # Make sure original bundles' contents did not change during operation
         for platform in helper["platforms"]:
-            # fmt:off
+
             assert check_sums_before[platform] == check_sums_after[platform], \
                 f"Before and after check sum for {platform} did not match"
             assert check_sums_before[platform] == check_sums_duplicates[platform], \
                 f"Before and duplicated check sum for {platform} did not match"
-            # fmt:on
+
 
     @pytest.mark.BAT
     @pytest.mark.assetpipeline
     @pytest.mark.test_case_id("C16877174")
-    def test_AddAndRemoveSeedPlatform_Success(self, workspace, bundler_batch_helper):
+    def test_AddAndRemoveSeedPlatform_Success(self, workspace, bundler_batch_helper, asset_processor, ap_setup_fixture):
         """
         Validates that the 'seeds' subcommand can add and remove seeds and seed platforms properly.
         Also checks that destructive overwrites require the --allowOverwrites flag
@@ -414,13 +445,15 @@ class TestsAssetBundlerBatch(object):
         14. Remove seed
         15. Validate that seed was removed from the seed list
         """
+        test_folder_name = "asset_bundler_test_assets"
         helper = bundler_batch_helper
+        self.ap_prepare_test_environment(test_folder_name, asset_processor, ap_setup_fixture)
+        seed_asset = os.path.join(asset_processor.project_test_cache_folder(), "txtfile_0.txt")
 
         # Make sure asset list file does not exist entering the test
         if os.path.exists(helper["asset_info_file_request"]):
             fs.delete([helper["asset_info_file_request"]], True, True)
 
-        test_asset = r"fonts/open_sans/license.txt"
         re_pattern = re.compile(r"""field="platformFlags" value="(\d+)" """)
         all_lines = ""
 
@@ -432,10 +465,10 @@ class TestsAssetBundlerBatch(object):
             re_match = re_pattern.search(lines)
             assert re_match, f"PlatformFlags were not found in seed file {seed_file}"
             platform_flag = int(re_match.group(1))
-            # fmt:off
+
             assert platform_flag == expected_platform_flag, \
                 f"Expected platform flag to be {expected_platform_flag}. Actual {platform_flag}"
-            # fmt:on
+
             return lines
 
         # End check_seed_platform()
@@ -443,26 +476,25 @@ class TestsAssetBundlerBatch(object):
         # Create seed list file
         helper.call_seeds(
             seedListFile=helper["seed_list_file"],
-            addSeed=test_asset,
+            addSeed=seed_asset,
             platform="pc",
         )
 
         # Validate file exists and has proper platform flag
         assert os.path.exists(helper["seed_list_file"]), f"seed list file was not created at {helper['seed_list_file']}"
-        check_seed_platform(helper["seed_list_file"], test_asset, helper["platform_values"]["pc"])
+        check_seed_platform(helper["seed_list_file"], seed_asset, helper["platform_values"]["pc"])
 
         # Add Mac and pc as platform for seed
         helper.call_seeds(
             seedListFile=helper["seed_list_file"],
-            addSeed=test_asset,
+            addSeed=seed_asset,
             platform="pc,mac",
         )
 
         # Validate both mac and pc are activated for seed
-        # fmt:off
-        check_seed_platform(helper["seed_list_file"], test_asset,
+
+        check_seed_platform(helper["seed_list_file"], seed_asset,
                             helper["platform_values"]["pc"] + helper["platform_values"]["mac"])
-        # fmt:on
 
         # Remove MAC platform
         helper.call_seeds(
@@ -471,18 +503,17 @@ class TestsAssetBundlerBatch(object):
             platform="mac",
         )
         # Validate only pc platform for seed. Save file contents to variable
-        all_lines = check_seed_platform(helper["seed_list_file"], test_asset, helper["platform_values"]["pc"])
+        all_lines = check_seed_platform(helper["seed_list_file"], seed_asset, helper["platform_values"]["pc"])
 
         result, _ = helper.call_seeds(seedListFile=helper["seed_list_file"], addPlatformToSeeds="", )
 
         assert result is False, "Calling --addPlatformToSeeds did not fail when not specifying the --platform argument"
 
         # Make sure the file contents did not change
-        # fmt:off
+
         with open(helper["seed_list_file"], "r") as asset_list_file:
             assert all_lines == asset_list_file.read(), \
                 "Calling --addPlatformToSeeds without --platform failed but changed the seed file"
-        # fmt:on
 
         # Add MAC platform via --addPlatformToSeeds
         helper.call_seeds(
@@ -491,10 +522,9 @@ class TestsAssetBundlerBatch(object):
             platform="mac",
         )
         # Validate Mac platform was added back on. Save file contents
-        # fmt:off
-        all_lines = check_seed_platform(helper["seed_list_file"], test_asset,
+
+        all_lines = check_seed_platform(helper["seed_list_file"], seed_asset,
                                         helper["platform_values"]["pc"] + helper["platform_values"]["mac"])
-        # fmt:on
 
         # Try to remove platform without specifying a platform to remove (should fail)
         result, _ = helper.call_seeds(seedListFile=helper["seed_list_file"], removePlatformFromSeeds="", )
@@ -502,25 +532,24 @@ class TestsAssetBundlerBatch(object):
         assert result is False, "Calling --removePlatformFromSeeds did not fail when not specifying the --platform argument"
 
         # Make sure file contents did not change
-        # fmt:off
+
         with open(helper["seed_list_file"], "r") as asset_list_file:
             assert all_lines == asset_list_file.read(), \
                 "Calling --removePlatformFromSeeds without --platform failed but changed the seed file"
-        # fmt:on
 
         # Remove the seed
         helper.call_seeds(
             seedListFile=helper["seed_list_file"],
-            removeSeed=test_asset,
+            removeSeed=seed_asset,
             platform="pc,mac",
         )
 
         # Validate seed was removed from file
-        # fmt:off
+
         with open(helper["seed_list_file"], "r") as seed_list_file:
-            assert test_asset not in seed_list_file.read(), \
+            assert seed_asset not in seed_list_file.read(), \
                 f"Seed was not removed from asset list file {helper['seed_list_file']}"
-        # fmt:on
+
 
     @pytest.mark.BAT
     @pytest.mark.assetpipeline
@@ -528,10 +557,10 @@ class TestsAssetBundlerBatch(object):
     @pytest.mark.test_case_id("C16877174")
     @pytest.mark.test_case_id("C16877175")
     @pytest.mark.test_case_id("C16877178")
-    # fmt:off
+
     def test_ComparisonOperations_Success(self, workspace, bundler_batch_helper, ap_setup_fixture,
                                                         asset_processor, timeout):
-        # fmt:on
+
         """
         Tests asset list comparison, both by file and by comparison type. Uses a set
         of controlled test assets to compare resulting output asset lists
@@ -542,14 +571,14 @@ class TestsAssetBundlerBatch(object):
         4. Validate assetlists were created properly
         5. Compare using comparison rules files and just command line arguments
         """
+        test_folder_name = "asset_bundler_test_assets"
         helper = bundler_batch_helper
-        env = ap_setup_fixture
+        self.ap_prepare_test_environment(test_folder_name, asset_processor, ap_setup_fixture)
 
-        # fmt:off
         assert "pc" in helper["platforms"] and "mac" in helper["platforms"], \
             "This test requires both PC and MAC platforms to be enabled. " \
             "Please rerun with commandline option: '--bundle_platforms=pc,mac'"
-        # fmt:on
+
 
         # Test assets arranged in common lists: six (0-5) .txt files and .dat files
         even_txt = ["txtfile_0.txt", "txtfile_2.txt", "txtfile_4.txt"]
@@ -588,26 +617,20 @@ class TestsAssetBundlerBatch(object):
             ("combined.rules", "2,0"),
         ]
 
-        # Get our test assets ready and processed
-        utils.prepare_test_assets(env["tests_dir"], "C16877178", env["project_test_assets_dir"])
-        asset_processor.batch_process(timeout=timeout, fastscan=False, platforms="pc,mac")
-
-        # *** Some helper functions *** #
-
         def create_seed_file(asset_names: List[str], seed_file_name: str) -> None:
-            """Adds the [asset_names] to the seed file [seed_file_name] with their specific platform"""
+            """Helper: Adds the [asset_names] to the seed file [seed_file_name] with their specific platform"""
             for asset_file_name in asset_names:
                 helper.call_seeds(
-                    seedListFile=os.path.join(helper["test_dir"], seed_file_name),
-                    addSeed=os.path.join(env["test_asset_dir_name"], asset_file_name),
+                    seedListFile=os.path.join(helper["project_path"], seed_file_name),
+                    addSeed=os.path.join(asset_processor.project_test_cache_folder(), asset_file_name),
                     platform=file_platforms[asset_file_name],
                 )
 
         def create_asset_list_file(seed_file_name: str, asset_list_file_name: str) -> None:
-            """Simple wrapper for calling the Bundler Batch for a [seed_file_name] and [asset_list_file_name]"""
+            """Helper: Simple wrapper for calling the Bundler Batch for a [seed_file_name] and [asset_list_file_name]"""
             helper.call_assetLists(
-                assetListFile=os.path.join(helper["test_dir"], asset_list_file_name),
-                seedListFile=os.path.join(helper["test_dir"], seed_file_name),
+                assetListFile=os.path.join(helper["project_path"], asset_list_file_name),
+                seedListFile=os.path.join(helper["project_path"], seed_file_name),
                 platform="pc,mac",
             )
 
@@ -625,7 +648,7 @@ class TestsAssetBundlerBatch(object):
         def validate_asset_list(asset_list_file: str, asset_list: List[str]) -> None:
             """Validates that the [asset_list_file] contains exactly the assets in [asset_list]"""
             assets_to_find = list(asset_list)  # Make copy of list. We will be removing elements as we go
-            for rel_path in helper.get_asset_relative_paths(os.path.join(helper["test_dir"], asset_list_file)):
+            for rel_path in helper.get_asset_relative_paths(os.path.join(helper["project_path"], asset_list_file)):
                 asset = os.path.split(rel_path)[1]  # Get just the asset's file name
                 try:
                     assets_to_find.remove(asset)  # Attempt to remove
@@ -684,7 +707,7 @@ class TestsAssetBundlerBatch(object):
                         out += asset_list + ","
                     else:
                         # Get absolute file path
-                        out += os.path.join(helper["test_dir"], asset_list) + ","
+                        out += os.path.join(helper["project_path"], asset_list) + ","
                 return out[:-1]  # Trim off extra comma
 
             # End asset_lists_to_string()
@@ -703,7 +726,7 @@ class TestsAssetBundlerBatch(object):
                 if second_input_arg is not None:
                     cmd.append(f"--secondAssetFile={second_input_arg}")
                 if use_file:
-                    file_name = os.path.join(helper["test_dir"], rule + ".rules")
+                    file_name = os.path.join(helper["project_path"], rule + ".rules")
                     cmd.append("--comparisonRulesFile=" + file_name)
                 else:
                     comp_type = [i for r, i in comparison_files if r.startswith(rule)][0]  # Get comparisonType flag
@@ -717,21 +740,21 @@ class TestsAssetBundlerBatch(object):
             # End generate_compare_command()
 
             def verify_asset_list_contents(expected: str, output_asset_list: str) -> None:
-                # Compare relative paths from inside 'expected' and 'output_asset_list' (last output file from cmd)
+                """Helper: Compare relative paths from inside 'expected' and 'output_asset_list' (last output file from cmd)"""
                 expected_paths = []
                 actual_paths = []
                 for rel_path in helper.get_asset_relative_paths(expected):
                     expected_paths.append(rel_path)
                 for rel_path in helper.get_asset_relative_paths(output_asset_list):
                     actual_paths.append(rel_path)
-                # fmt:off
+
                 assert sorted(expected_paths) == sorted(actual_paths), \
                     "Asset list comparison did not yield expected results"
-                # fmt:on
+
             # End verify_asset_list_contents()
 
             def run_compare_command_and_verify(platform_arg: str, expect_pc_output: bool, expect_mac_output: bool) -> None:
-
+                """Helper: Adds the platform suffixes to each expected output, builds and runs the compare commands. """
                 # Expected asset list to equal result of comparison
                 expected_pc_asset_list = None
                 expected_mac_asset_list = None
@@ -744,12 +767,12 @@ class TestsAssetBundlerBatch(object):
                 last_output_arg = output_arg.split(",")[-1]
                 if expect_pc_output:
                     platform = platforms["pc"]
-                    expected_pc_asset_list = os.path.join(helper["test_dir"], helper.platform_file_name(expected_asset_list, platform))
+                    expected_pc_asset_list = os.path.join(helper["project_path"], helper.platform_file_name(expected_asset_list, platform))
                     output_pc_asset_list = helper.platform_file_name(last_output_arg, platform)
 
                 if expect_mac_output:
                     platform = platforms["mac"]
-                    expected_mac_asset_list = os.path.join(helper["test_dir"], helper.platform_file_name(expected_asset_list, platform))
+                    expected_mac_asset_list = os.path.join(helper["project_path"], helper.platform_file_name(expected_asset_list, platform))
                     output_mac_asset_list = helper.platform_file_name(last_output_arg, platform)
 
                 # Build execution command
@@ -780,7 +803,7 @@ class TestsAssetBundlerBatch(object):
 
         # Create comparison (.rules) files
         for args in comparison_files:
-            rule_file = os.path.join(helper["test_dir"], args[0])
+            rule_file = os.path.join(helper["project_path"], args[0])
             logger.info(f"Creating rule file: {rule_file}")
             cmd = [
                 helper["bundler_batch"],
@@ -871,7 +894,7 @@ class TestsAssetBundlerBatch(object):
     @pytest.mark.assetpipeline
     @pytest.mark.test_case_id("C16877174")
     @pytest.mark.test_case_id("C16877175")
-    def test_AssetListCreation_OutputMatchesResult(self, workspace, bundler_batch_helper):
+    def test_AssetListCreation_OutputMatchesResult(self, workspace, bundler_batch_helper, asset_processor, ap_setup_fixture):
         """
         Tests that assetlists are created equivalent to the output while being created, and
         makes sure overwriting an existing file without the --allowOverwrites fails
@@ -886,17 +909,18 @@ class TestsAssetBundlerBatch(object):
         7. Specifying platform but not "add" or "remove" should fail
         8. Verify file Has changed
         """
+        test_folder_name = "asset_bundler_test_assets"
         helper = bundler_batch_helper
+        self.ap_prepare_test_environment(test_folder_name, asset_processor, ap_setup_fixture)
+        seed_asset = os.path.join(asset_processor.project_test_cache_folder(), "txtfile_0.txt")
 
-        # fmt:off
         assert "pc" in helper["platforms"], \
             "This test requires the PC platform to be enabled. " \
             "Please rerun with commandline option: '--bundle_platforms=pc'"
-        # fmt:on
 
         # Assetlist result file (pc platform)
         al_file_path = os.path.join(
-            helper["test_dir"],
+            helper["project_path"],
             helper.platform_file_name(helper["asset_info_file_name"], platforms["pc"])
         )
         seed_files_pattern = re.compile("Loading Seed List file ( ([^)]*) )")
@@ -925,7 +949,7 @@ class TestsAssetBundlerBatch(object):
         # Create a seed file
         helper.call_seeds(
             seedListFile=helper["seed_list_file"],
-            addSeed=r"levels\testdependencieslevel\testdependencieslevel.spawnable",
+            addSeed=seed_asset,
             platform="pc",
         )
 
@@ -962,10 +986,8 @@ class TestsAssetBundlerBatch(object):
     @pytest.mark.assetpipeline
     @pytest.mark.test_case_id("C16877175")
     @pytest.mark.test_case_id("C16877177")
-    # fmt:off
-    def test_AP_BundleProcessing_BundleProcessedAtRuntime(self, workspace, bundler_batch_helper,
-                                                                        asset_processor, request):
-        # fmt:on
+    def test_AP_BundleProcessing_BundleProcessedAtRuntime(self, workspace, bundler_batch_helper, asset_processor,
+                                                          ap_setup_fixture, request):
         """
         Test to make sure the AP GUI will process a newly created bundle file
 
@@ -977,18 +999,20 @@ class TestsAssetBundlerBatch(object):
         5. Make sure bundle now exists in cache
         """
         # Set up helpers and variables
+        test_folder_name = "asset_bundler_test_assets"
         helper = bundler_batch_helper
+        self.ap_prepare_test_environment(test_folder_name, asset_processor, ap_setup_fixture)
+        seed_asset = os.path.join(asset_processor.project_test_cache_folder(), "txtfile_0.txt")
 
         # Make sure file gets deleted on teardown
         request.addfinalizer(lambda: fs.delete([bundle_result_path], True, False))
 
-        bundles_folder = os.path.join(workspace.paths.project(), "Bundles")
-        level_pak = r"levels\testdependencieslevel\testdependencieslevel.spawnable"
+        bundles_folder = os.path.join(bundler_batch_helper["project_path"], "Bundles")
         bundle_request_path = os.path.join(bundles_folder, "bundle.pak")
         bundle_result_path = os.path.join(bundles_folder,
                                           helper.platform_file_name("bundle.pak", workspace.asset_processor_platform))
 
-        bundle_cache_path = os.path.join(workspace.paths.platform_cache(),
+        bundle_cache_path = os.path.join(asset_processor.temp_project_cache(asset_platform="pc"),
                                          "Bundles",
                                          helper.platform_file_name("bundle.pak", workspace.asset_processor_platform))
 
@@ -1001,7 +1025,7 @@ class TestsAssetBundlerBatch(object):
 
         # Make asset list file (used for bundle creation)
         helper.call_assetLists(
-            addSeed=level_pak,
+            addSeed=seed_asset,
             assetListFile=helper["asset_info_file_request"],
         )
 
@@ -1009,7 +1033,7 @@ class TestsAssetBundlerBatch(object):
         result, _ = asset_processor.gui_process()
         assert result, "AP GUI failed"
 
-        time.sleep(5)
+        asset_processor.wait_for_idle(timeout=5)
 
         # Make bundle in <project_folder>/Bundles
         helper.call_bundles(
@@ -1028,35 +1052,29 @@ class TestsAssetBundlerBatch(object):
 
     @pytest.mark.BAT
     @pytest.mark.assetpipeline
-    # fmt:off
-    def test_FilesMarkedSkip_FilesAreSkipped(self, workspace, bundler_batch_helper):
+    def test_FilesMarkedSkip_FilesAreSkipped(self, workspace, asset_processor, ap_setup_fixture, bundler_batch_helper):
         """
         Test Steps:
         1. Create an asset list with a file marked as skip
         2. Verify file was created
         3. Verify that only the expected assets are present in the created asset list
         """
+        test_folder_name = "SeedWithDependencies"
+        self.ap_prepare_test_environment(test_folder_name, asset_processor, ap_setup_fixture)
+        seed_asset = os.path.join(asset_processor.project_test_cache_folder(), "canvas1.uicanvas")
+
         expected_assets = sorted([
-            "ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas",
-            "ui/textures/prefab/button_disabled.tif.streamingimage",
-            "ui/textures/prefab/tooltip_sliced.tif.streamingimage",
-            "ui/textures/prefab/button_normal.tif.streamingimage"
+            "seedwithdependencies/ama_green_01.tif.streamingimage",
+            "seedwithdependencies/ama_grey_01.tif.streamingimage",
+            "seedwithdependencies/ama_white_01.tif.streamingimage",
+            "seedwithdependencies/canvas1.uicanvas"
         ])
         # Printing these lists out can save a step in debugging if this test fails on Jenkins.
         logger.info(f"expected_assets: {expected_assets}")
 
         skip_assets = sorted([
-            "ui/scripts/lyshineexamples/animation/multiplesequences.luac",
-            "ui/scripts/lyshineexamples/unloadthiscanvasbutton.luac",
-            "fonts/vera.fontfamily",
-            "fonts/vera-italic.font",
-            "fonts/vera.font",
-            "fonts/vera-bold.font",
-            "fonts/vera-bold-italic.font",
-            "fonts/vera-italic.ttf",
-            "fonts/vera.ttf",
-            "fonts/vera-bold.ttf",
-            "fonts/vera-bold-italic.ttf"
+            "seedwithdependencies/default1024.font",
+            "seedwithdependencies/default2048.font"
         ])
         logger.info(f"skip_assets: {skip_assets}")
 
@@ -1068,7 +1086,7 @@ class TestsAssetBundlerBatch(object):
         # the files were actually skipped, and not just missing.
         bundler_batch_helper.call_assetLists(
             assetListFile=bundler_batch_helper['asset_info_file_request'],
-            addSeed="ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas"
+            addSeed=seed_asset
         )
         assert os.path.isfile(bundler_batch_helper["asset_info_file_result"])
         assets_in_no_skip_list = []
@@ -1081,7 +1099,7 @@ class TestsAssetBundlerBatch(object):
         # Now generate an asset info file using the skip command, and verify the skip files are not in the list.
         bundler_batch_helper.call_assetLists(
             assetListFile=bundler_batch_helper['asset_info_file_request'],
-            addSeed="ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas",
+            addSeed=seed_asset,
             allowOverwrites="",
             skip=','.join(skip_assets)
         )
@@ -1094,48 +1112,9 @@ class TestsAssetBundlerBatch(object):
         logger.info(f"assets_in_list: {assets_in_list}")
         assert assets_in_list == expected_assets
 
-
     @pytest.mark.BAT
     @pytest.mark.assetpipeline
-    # fmt:off
-    def test_AssetListSkipOneOfTwoParents_SharedDependencyIsIncluded(self, workspace,
-                                                                                   bundler_batch_helper):
-        """
-        Test Steps:
-        1. Create Asset List with multiple parent assets that are skipped
-        2. Verify that Asset List was created
-        3. Verify that only the expected assets are present in the asset list
-        """
-        expected_assets = [
-            "objects/cube_lod0.azlod",
-            "objects/cube_lod0_index.azbuffer",
-            "resourcepools/defaultvertexbufferpool.pool"
-        ]
-        # Test Asset Structure:
-        #          Grandparent
-        #      /        |        \
-        #   ParentA  ParentB  ParentC
-        #      \        |        /
-        #          CommonChild
-
-        # Even if we exclude all parents besides "ParentA", we should still have "CommonChild" since it is a product dependency of "ParentA"
-        bundler_batch_helper.call_assetLists(
-            assetListFile=bundler_batch_helper['asset_info_file_request'],
-            addSeed="objects/cube_lod0.azlod",
-            skip="objects/cube_lod0_position0.azbuffer, objects/cube_lod0_tangent0.azbuffer,"
-                 "objects/cube_lod0_normal0.azbuffer, objects/cube_lod0_bitangent0.azbuffer,"
-                 "objects/cube_lod0_uv0.azbuffer"
-        )
-        assert os.path.isfile(bundler_batch_helper["asset_info_file_result"])
-        assets_in_list = []
-        for rel_path in bundler_batch_helper.get_asset_relative_paths(bundler_batch_helper["asset_info_file_result"]):
-            assets_in_list.append(rel_path)
-        assert sorted(assets_in_list) == sorted(expected_assets)
-
-    @pytest.mark.BAT
-    @pytest.mark.assetpipeline
-    # fmt:off
-    def test_AssetLists_SkipRoot_ExcludesAll(self, workspace, bundler_batch_helper):
+    def test_AssetLists_SkipRoot_ExcludesAll(self, workspace, asset_processor, ap_setup_fixture, bundler_batch_helper):
         """
         Negative scenario test that skips the same file being used as the parent seed.
 
@@ -1143,6 +1122,9 @@ class TestsAssetBundlerBatch(object):
         1. Create an asset list that skips the root asset
         2. Verify that asset list was not generated
         """
+        test_folder_name = os.path.join(workspace.project, "libs\\particles")
+        asset_processor.add_source_folder_assets(test_folder_name)
+        asset_processor.batch_process()
 
         result, _ = bundler_batch_helper.call_assetLists(
             assetListFile=bundler_batch_helper['asset_info_file_request'],
@@ -1157,8 +1139,8 @@ class TestsAssetBundlerBatch(object):
 
     @pytest.mark.BAT
     @pytest.mark.assetpipeline
-    # fmt:off
-    def test_AssetLists_SkipUniversalWildcard_ExcludesAll(self, workspace, bundler_batch_helper):
+
+    def test_AssetLists_SkipUniversalWildcard_ExcludesAll(self, workspace, asset_processor, ap_setup_fixture, bundler_batch_helper):
         """
         Negative scenario test that uses the all wildcard when generating an asset list.
 
@@ -1166,6 +1148,9 @@ class TestsAssetBundlerBatch(object):
         1. Create an Asset List while using the universal all wildcard "*"
         2. Verify that asset list was not generated
         """
+        test_folder_name = os.path.join(workspace.project, "libs\\particles")
+        asset_processor.add_source_folder_assets(test_folder_name)
+        asset_processor.batch_process()
 
         result, _ = bundler_batch_helper.call_assetLists(
             assetListFile=bundler_batch_helper['asset_info_file_request'],
@@ -1180,7 +1165,6 @@ class TestsAssetBundlerBatch(object):
 
     @pytest.mark.BAT
     @pytest.mark.assetpipeline
-    # fmt:off
     def test_Bundles_InvalidAssetList_ReportsError(self, workspace, bundler_batch_helper):
         """
         Verifies that when the bundles command is used, with an invalid asset list, the command fails and prints a useful error message.
@@ -1201,3 +1185,42 @@ class TestsAssetBundlerBatch(object):
             return
         logger.error("AssetBundlerBatch was expected to fail when given an invalid asset list to bundle, but did not.")
         assert False
+
+    @pytest.mark.BAT
+    @pytest.mark.assetpipeline
+    @pytest.mark.parametrize("bundler_batch_helper", [False], indirect=True)
+    def test_AssetListSkipOneOfTwoParents_SharedDependencyIsIncluded(self, workspace, asset_processor, bundler_batch_helper):
+        """
+        Test Steps:
+        1. Create Asset List with multiple parent assets that are skipped
+        2. Verify that Asset List was created
+        3. Verify that only the expected assets are present in the asset list
+        """
+
+        asset_processor.batch_process()
+        expected_assets = [
+            "objects/cube_lod0.azlod",
+            "objects/cube_lod0_index.azbuffer",
+            "resourcepools/defaultvertexbufferpool.pool"
+        ]
+        # Test Asset Structure:
+        #          Grandparent
+        #      /        |        \
+        #   ParentA  ParentB  ParentC
+        #      \        |        /
+        #          CommonChild
+
+        # Even if we exclude all parents besides "ParentA", we should still have "CommonChild" since it is a product dependency of "ParentA"
+        bundler_batch_helper.call_assetLists(
+            assetListFile=bundler_batch_helper['asset_info_file_request'],
+            addSeed="objects/cube_lod0.azlod",
+            skip="objects/cube_lod0_position0.azbuffer, objects/cube_lod0_tangent0.azbuffer,"
+                 "objects/cube_lod0_normal0.azbuffer, objects/cube_lod0_bitangent0.azbuffer,"
+                 "objects/cube_lod0_uv0.azbuffer"
+        )
+        assert os.path.isfile(bundler_batch_helper["asset_info_file_result"])
+        assets_in_list = []
+        for rel_path in bundler_batch_helper.get_asset_relative_paths(
+                bundler_batch_helper["asset_info_file_result"]):
+            assets_in_list.append(rel_path)
+        assert sorted(assets_in_list) == sorted(expected_assets)

+ 547 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/Levels/TestDependenciesLevel/TestDependenciesLevel.prefab

@@ -0,0 +1,547 @@
+{
+    "ContainerEntity": {
+        "Id": "Entity_[1146574390643]",
+        "Name": "Level",
+        "Components": {
+            "Component_[10641544592923449938]": {
+                "$type": "EditorInspectorComponent",
+                "Id": 10641544592923449938
+            },
+            "Component_[12039882709170782873]": {
+                "$type": "EditorOnlyEntityComponent",
+                "Id": 12039882709170782873
+            },
+            "Component_[12265484671603697631]": {
+                "$type": "EditorPendingCompositionComponent",
+                "Id": 12265484671603697631
+            },
+            "Component_[14126657869720434043]": {
+                "$type": "EditorEntitySortComponent",
+                "Id": 14126657869720434043
+            },
+            "Component_[15230859088967841193]": {
+                "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                "Id": 15230859088967841193,
+                "Parent Entity": ""
+            },
+            "Component_[16239496886950819870]": {
+                "$type": "EditorDisabledCompositionComponent",
+                "Id": 16239496886950819870
+            },
+            "Component_[5688118765544765547]": {
+                "$type": "EditorEntityIconComponent",
+                "Id": 5688118765544765547
+            },
+            "Component_[6545738857812235305]": {
+                "$type": "SelectionComponent",
+                "Id": 6545738857812235305
+            },
+            "Component_[7247035804068349658]": {
+                "$type": "EditorPrefabComponent",
+                "Id": 7247035804068349658
+            },
+            "Component_[9307224322037797205]": {
+                "$type": "EditorLockComponent",
+                "Id": 9307224322037797205
+            },
+            "Component_[9562516168917670048]": {
+                "$type": "EditorVisibilityComponent",
+                "Id": 9562516168917670048
+            }
+        }
+    },
+    "Entities": {
+        "Entity_[1155164325235]": {
+            "Id": "Entity_[1155164325235]",
+            "Name": "Sun",
+            "Components": {
+                "Component_[10440557478882592717]": {
+                    "$type": "SelectionComponent",
+                    "Id": 10440557478882592717
+                },
+                "Component_[13620450453324765907]": {
+                    "$type": "EditorLockComponent",
+                    "Id": 13620450453324765907
+                },
+                "Component_[2134313378593666258]": {
+                    "$type": "EditorInspectorComponent",
+                    "Id": 2134313378593666258
+                },
+                "Component_[234010807770404186]": {
+                    "$type": "EditorVisibilityComponent",
+                    "Id": 234010807770404186
+                },
+                "Component_[2970359110423865725]": {
+                    "$type": "EditorEntityIconComponent",
+                    "Id": 2970359110423865725
+                },
+                "Component_[3722854130373041803]": {
+                    "$type": "EditorOnlyEntityComponent",
+                    "Id": 3722854130373041803
+                },
+                "Component_[5992533738676323195]": {
+                    "$type": "EditorDisabledCompositionComponent",
+                    "Id": 5992533738676323195
+                },
+                "Component_[7378860763541895402]": {
+                    "$type": "AZ::Render::EditorDirectionalLightComponent",
+                    "Id": 7378860763541895402,
+                    "Controller": {
+                        "Configuration": {
+                            "Intensity": 1.0,
+                            "CameraEntityId": "",
+                            "ShadowFilterMethod": 1
+                        }
+                    }
+                },
+                "Component_[7892834440890947578]": {
+                    "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                    "Id": 7892834440890947578,
+                    "Parent Entity": "Entity_[1176639161715]",
+                    "Transform Data": {
+                        "Translate": [
+                            0.0,
+                            0.0,
+                            13.487043380737305
+                        ],
+                        "Rotate": [
+                            -76.13099670410156,
+                            -0.847000002861023,
+                            -15.8100004196167
+                        ]
+                    }
+                },
+                "Component_[8599729549570828259]": {
+                    "$type": "EditorEntitySortComponent",
+                    "Id": 8599729549570828259
+                },
+                "Component_[952797371922080273]": {
+                    "$type": "EditorPendingCompositionComponent",
+                    "Id": 952797371922080273
+                }
+            }
+        },
+        "Entity_[1159459292531]": {
+            "Id": "Entity_[1159459292531]",
+            "Name": "Ground",
+            "Components": {
+                "Component_[11701138785793981042]": {
+                    "$type": "SelectionComponent",
+                    "Id": 11701138785793981042
+                },
+                "Component_[12260880513256986252]": {
+                    "$type": "EditorEntityIconComponent",
+                    "Id": 12260880513256986252
+                },
+                "Component_[13711420870643673468]": {
+                    "$type": "EditorDisabledCompositionComponent",
+                    "Id": 13711420870643673468
+                },
+                "Component_[138002849734991713]": {
+                    "$type": "EditorOnlyEntityComponent",
+                    "Id": 138002849734991713
+                },
+                "Component_[16578565737331764849]": {
+                    "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                    "Id": 16578565737331764849,
+                    "Parent Entity": "Entity_[1176639161715]"
+                },
+                "Component_[16919232076966545697]": {
+                    "$type": "EditorInspectorComponent",
+                    "Id": 16919232076966545697
+                },
+                "Component_[5182430712893438093]": {
+                    "$type": "EditorMaterialComponent",
+                    "Id": 5182430712893438093
+                },
+                "Component_[5675108321710651991]": {
+                    "$type": "AZ::Render::EditorMeshComponent",
+                    "Id": 5675108321710651991,
+                    "Controller": {
+                        "Configuration": {
+                            "ModelAsset": {
+                                "assetId": {
+                                    "guid": "{0CD745C0-6AA8-569A-A68A-73A3270986C4}",
+                                    "subId": 277889906
+                                },
+                                "assetHint": "objects/groudplane/groundplane_512x512m.azmodel"
+                            }
+                        }
+                    }
+                },
+                "Component_[5681893399601237518]": {
+                    "$type": "EditorEntitySortComponent",
+                    "Id": 5681893399601237518
+                },
+                "Component_[592692962543397545]": {
+                    "$type": "EditorPendingCompositionComponent",
+                    "Id": 592692962543397545
+                },
+                "Component_[7090012899106946164]": {
+                    "$type": "EditorLockComponent",
+                    "Id": 7090012899106946164
+                },
+                "Component_[9410832619875640998]": {
+                    "$type": "EditorVisibilityComponent",
+                    "Id": 9410832619875640998
+                }
+            }
+        },
+        "Entity_[1163754259827]": {
+            "Id": "Entity_[1163754259827]",
+            "Name": "Camera",
+            "Components": {
+                "Component_[11895140916889160460]": {
+                    "$type": "EditorEntityIconComponent",
+                    "Id": 11895140916889160460
+                },
+                "Component_[16880285896855930892]": {
+                    "$type": "{CA11DA46-29FF-4083-B5F6-E02C3A8C3A3D} EditorCameraComponent",
+                    "Id": 16880285896855930892,
+                    "Controller": {
+                        "Configuration": {
+                            "Field of View": 55.0,
+                            "EditorEntityId": 8929576024571800510
+                        }
+                    }
+                },
+                "Component_[17187464423780271193]": {
+                    "$type": "EditorLockComponent",
+                    "Id": 17187464423780271193
+                },
+                "Component_[17495696818315413311]": {
+                    "$type": "EditorEntitySortComponent",
+                    "Id": 17495696818315413311
+                },
+                "Component_[18086214374043522055]": {
+                    "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                    "Id": 18086214374043522055,
+                    "Parent Entity": "Entity_[1176639161715]",
+                    "Transform Data": {
+                        "Translate": [
+                            -2.3000001907348633,
+                            -3.9368600845336914,
+                            1.0
+                        ],
+                        "Rotate": [
+                            -2.050307512283325,
+                            1.9552897214889526,
+                            -43.623355865478516
+                        ]
+                    }
+                },
+                "Component_[18387556550380114975]": {
+                    "$type": "SelectionComponent",
+                    "Id": 18387556550380114975
+                },
+                "Component_[2654521436129313160]": {
+                    "$type": "EditorVisibilityComponent",
+                    "Id": 2654521436129313160
+                },
+                "Component_[5265045084611556958]": {
+                    "$type": "EditorDisabledCompositionComponent",
+                    "Id": 5265045084611556958
+                },
+                "Component_[7169798125182238623]": {
+                    "$type": "EditorPendingCompositionComponent",
+                    "Id": 7169798125182238623
+                },
+                "Component_[7255796294953281766]": {
+                    "$type": "GenericComponentWrapper",
+                    "Id": 7255796294953281766,
+                    "m_template": {
+                        "$type": "FlyCameraInputComponent"
+                    }
+                },
+                "Component_[8866210352157164042]": {
+                    "$type": "EditorInspectorComponent",
+                    "Id": 8866210352157164042
+                },
+                "Component_[9129253381063760879]": {
+                    "$type": "EditorOnlyEntityComponent",
+                    "Id": 9129253381063760879
+                }
+            }
+        },
+        "Entity_[1168049227123]": {
+            "Id": "Entity_[1168049227123]",
+            "Name": "Grid",
+            "Components": {
+                "Component_[11443347433215807130]": {
+                    "$type": "EditorEntityIconComponent",
+                    "Id": 11443347433215807130
+                },
+                "Component_[11779275529534764488]": {
+                    "$type": "SelectionComponent",
+                    "Id": 11779275529534764488
+                },
+                "Component_[14249419413039427459]": {
+                    "$type": "EditorInspectorComponent",
+                    "Id": 14249419413039427459
+                },
+                "Component_[15448581635946161318]": {
+                    "$type": "AZ::Render::EditorGridComponent",
+                    "Id": 15448581635946161318,
+                    "Controller": {
+                        "Configuration": {
+                            "primarySpacing": 4.0,
+                            "primaryColor": [
+                                0.501960813999176,
+                                0.501960813999176,
+                                0.501960813999176
+                            ],
+                            "secondarySpacing": 0.5,
+                            "secondaryColor": [
+                                0.250980406999588,
+                                0.250980406999588,
+                                0.250980406999588
+                            ]
+                        }
+                    }
+                },
+                "Component_[1843303322527297409]": {
+                    "$type": "EditorDisabledCompositionComponent",
+                    "Id": 1843303322527297409
+                },
+                "Component_[380249072065273654]": {
+                    "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                    "Id": 380249072065273654,
+                    "Parent Entity": "Entity_[1176639161715]"
+                },
+                "Component_[7476660583684339787]": {
+                    "$type": "EditorPendingCompositionComponent",
+                    "Id": 7476660583684339787
+                },
+                "Component_[7557626501215118375]": {
+                    "$type": "EditorEntitySortComponent",
+                    "Id": 7557626501215118375
+                },
+                "Component_[7984048488947365511]": {
+                    "$type": "EditorVisibilityComponent",
+                    "Id": 7984048488947365511
+                },
+                "Component_[8118181039276487398]": {
+                    "$type": "EditorOnlyEntityComponent",
+                    "Id": 8118181039276487398
+                },
+                "Component_[9189909764215270515]": {
+                    "$type": "EditorLockComponent",
+                    "Id": 9189909764215270515
+                }
+            }
+        },
+        "Entity_[1172344194419]": {
+            "Id": "Entity_[1172344194419]",
+            "Name": "Shader Ball",
+            "Components": {
+                "Component_[10789351944715265527]": {
+                    "$type": "EditorOnlyEntityComponent",
+                    "Id": 10789351944715265527
+                },
+                "Component_[12037033284781049225]": {
+                    "$type": "EditorEntitySortComponent",
+                    "Id": 12037033284781049225
+                },
+                "Component_[13759153306105970079]": {
+                    "$type": "EditorPendingCompositionComponent",
+                    "Id": 13759153306105970079
+                },
+                "Component_[14135560884830586279]": {
+                    "$type": "EditorInspectorComponent",
+                    "Id": 14135560884830586279
+                },
+                "Component_[16247165675903986673]": {
+                    "$type": "EditorVisibilityComponent",
+                    "Id": 16247165675903986673
+                },
+                "Component_[18082433625958885247]": {
+                    "$type": "EditorDisabledCompositionComponent",
+                    "Id": 18082433625958885247
+                },
+                "Component_[6472623349872972660]": {
+                    "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                    "Id": 6472623349872972660,
+                    "Parent Entity": "Entity_[1176639161715]",
+                    "Transform Data": {
+                        "Rotate": [
+                            0.0,
+                            0.10000000149011612,
+                            180.0
+                        ]
+                    }
+                },
+                "Component_[6495255223970673916]": {
+                    "$type": "AZ::Render::EditorMeshComponent",
+                    "Id": 6495255223970673916,
+                    "Controller": {
+                        "Configuration": {
+                            "ModelAsset": {
+                                "assetId": {
+                                    "guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
+                                    "subId": 281415304
+                                },
+                                "assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
+                            }
+                        }
+                    }
+                },
+                "Component_[8056625192494070973]": {
+                    "$type": "SelectionComponent",
+                    "Id": 8056625192494070973
+                },
+                "Component_[8550141614185782969]": {
+                    "$type": "EditorEntityIconComponent",
+                    "Id": 8550141614185782969
+                },
+                "Component_[9439770997198325425]": {
+                    "$type": "EditorLockComponent",
+                    "Id": 9439770997198325425
+                }
+            }
+        },
+        "Entity_[1176639161715]": {
+            "Id": "Entity_[1176639161715]",
+            "Name": "Atom Default Environment",
+            "Components": {
+                "Component_[10757302973393310045]": {
+                    "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                    "Id": 10757302973393310045,
+                    "Parent Entity": "Entity_[1146574390643]"
+                },
+                "Component_[14505817420424255464]": {
+                    "$type": "EditorInspectorComponent",
+                    "Id": 14505817420424255464,
+                    "ComponentOrderEntryArray": [
+                        {
+                            "ComponentId": 10757302973393310045
+                        }
+                    ]
+                },
+                "Component_[14988041764659020032]": {
+                    "$type": "EditorLockComponent",
+                    "Id": 14988041764659020032
+                },
+                "Component_[15808690248755038124]": {
+                    "$type": "SelectionComponent",
+                    "Id": 15808690248755038124
+                },
+                "Component_[15900837685796817138]": {
+                    "$type": "EditorVisibilityComponent",
+                    "Id": 15900837685796817138
+                },
+                "Component_[3298767348226484884]": {
+                    "$type": "EditorOnlyEntityComponent",
+                    "Id": 3298767348226484884
+                },
+                "Component_[4076975109609220594]": {
+                    "$type": "EditorPendingCompositionComponent",
+                    "Id": 4076975109609220594
+                },
+                "Component_[5679760548946028854]": {
+                    "$type": "EditorDisabledCompositionComponent",
+                    "Id": 5679760548946028854
+                },
+                "Component_[5855590796136709437]": {
+                    "$type": "EditorEntitySortComponent",
+                    "Id": 5855590796136709437,
+                    "Child Entity Order": [
+                        "Entity_[1155164325235]",
+                        "Entity_[1180934129011]",
+                        "Entity_[1172344194419]",
+                        "Entity_[1168049227123]",
+                        "Entity_[1163754259827]",
+                        "Entity_[1159459292531]"
+                    ]
+                },
+                "Component_[9277695270015777859]": {
+                    "$type": "EditorEntityIconComponent",
+                    "Id": 9277695270015777859
+                }
+            }
+        },
+        "Entity_[1180934129011]": {
+            "Id": "Entity_[1180934129011]",
+            "Name": "Global Sky",
+            "Components": {
+                "Component_[11231930600558681245]": {
+                    "$type": "AZ::Render::EditorHDRiSkyboxComponent",
+                    "Id": 11231930600558681245,
+                    "Controller": {
+                        "Configuration": {
+                            "CubemapAsset": {
+                                "assetId": {
+                                    "guid": "{215E47FD-D181-5832-B1AB-91673ABF6399}",
+                                    "subId": 1000
+                                },
+                                "assetHint": "lightingpresets/highcontrast/goegap_4k_skyboxcm.exr.streamingimage"
+                            }
+                        }
+                    }
+                },
+                "Component_[11980494120202836095]": {
+                    "$type": "SelectionComponent",
+                    "Id": 11980494120202836095
+                },
+                "Component_[1428633914413949476]": {
+                    "$type": "EditorLockComponent",
+                    "Id": 1428633914413949476
+                },
+                "Component_[14936200426671614999]": {
+                    "$type": "AZ::Render::EditorImageBasedLightComponent",
+                    "Id": 14936200426671614999,
+                    "Controller": {
+                        "Configuration": {
+                            "diffuseImageAsset": {
+                                "assetId": {
+                                    "guid": "{3FD09945-D0F2-55C8-B9AF-B2FD421FE3BE}",
+                                    "subId": 3000
+                                },
+                                "assetHint": "lightingpresets/highcontrast/goegap_4k_iblglobalcm_ibldiffuse.exr.streamingimage"
+                            },
+                            "specularImageAsset": {
+                                "assetId": {
+                                    "guid": "{3FD09945-D0F2-55C8-B9AF-B2FD421FE3BE}",
+                                    "subId": 2000
+                                },
+                                "assetHint": "lightingpresets/highcontrast/goegap_4k_iblglobalcm_iblspecular.exr.streamingimage"
+                            }
+                        }
+                    }
+                },
+                "Component_[14994774102579326069]": {
+                    "$type": "EditorDisabledCompositionComponent",
+                    "Id": 14994774102579326069
+                },
+                "Component_[15417479889044493340]": {
+                    "$type": "EditorPendingCompositionComponent",
+                    "Id": 15417479889044493340
+                },
+                "Component_[15826613364991382688]": {
+                    "$type": "EditorEntitySortComponent",
+                    "Id": 15826613364991382688
+                },
+                "Component_[1665003113283562343]": {
+                    "$type": "EditorOnlyEntityComponent",
+                    "Id": 1665003113283562343
+                },
+                "Component_[3704934735944502280]": {
+                    "$type": "EditorEntityIconComponent",
+                    "Id": 3704934735944502280
+                },
+                "Component_[5698542331457326479]": {
+                    "$type": "EditorVisibilityComponent",
+                    "Id": 5698542331457326479
+                },
+                "Component_[6644513399057217122]": {
+                    "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                    "Id": 6644513399057217122,
+                    "Parent Entity": "Entity_[1176639161715]"
+                },
+                "Component_[931091830724002070]": {
+                    "$type": "EditorInspectorComponent",
+                    "Id": 931091830724002070
+                }
+            }
+        }
+    }
+}

+ 12 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/Levels/TestDependenciesLevel/tags.txt

@@ -0,0 +1,12 @@
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0

+ 3 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/SeedWithDependencies/AMA_Green_01.tif

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6b857d0dd0d349ce5366612372290a1b9b4085ffc2e235e245739a7a6c76ea11
+size 21752

+ 3 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/SeedWithDependencies/AMA_Grey_01.tif

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:418ed2ae210922737306d653cd18ae970ba72c192bbcf4e8bc9dff005f53ea0a
+size 5020

+ 3 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/SeedWithDependencies/AMA_White_01.tif

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cd91032afab1a93327de4a4b00146340efafd1dda5a2a0b35399427bd511f127
+size 6660

+ 564 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/SeedWithDependencies/Canvas1.uicanvas

@@ -0,0 +1,564 @@
+<ObjectStream version="3">
+	<Class name="UiCanvasFileObject" version="2" type="{1F02632F-F113-49B1-85AD-8CD0FA78B8AA}">
+		<Class name="AZ::Entity" field="CanvasEntity" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
+			<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+				<Class name="AZ::u64" field="id" value="474928432572" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+			</Class>
+			<Class name="AZStd::string" field="Name" value="UiCanvasEntity" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+			<Class name="AZStd::vector&lt;AZ::Component*, allocator&gt;" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
+				<Class name="UiCanvasComponent" field="element" version="4" type="{50B8CF6C-B19A-4D86-AFE9-96EFB820D422}">
+					<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+						<Class name="AZ::u64" field="Id" value="15467960535682957009" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+					</Class>
+					<Class name="AZ::u64" field="UniqueId" value="11774790100548863531" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+					<Class name="EntityId" field="RootElement" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+						<Class name="AZ::u64" field="id" value="487813334460" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+					</Class>
+					<Class name="unsigned int" field="LastElement" value="9" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+					<Class name="Vector2" field="CanvasSize" value="1280.0000000 720.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+					<Class name="bool" field="IsSnapEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+					<Class name="int" field="DrawOrder" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+					<Class name="bool" field="IsPixelAligned" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+					<Class name="bool" field="IsTextPixelAligned" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+					<Class name="bool" field="RenderToTexture" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+					<Class name="Asset&lt;AttachmentImageAsset&gt;" field="AttachmentImageAsset" value="id={00000000-0000-0000-0000-000000000000}:0,type={82CEA86B-E891-4969-8F35-D8017E8902C8},hint={},loadBehavior=1" version="3" type="{61538C1C-2EDA-593B-AA53-701FF7D854E7}"/>
+					<Class name="bool" field="IsPosInputSupported" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+					<Class name="bool" field="IsConsumingAllInput" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+					<Class name="bool" field="IsMultiTouchSupported" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+					<Class name="bool" field="IsNavigationSupported" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+					<Class name="float" field="NavigationThreshold" value="0.4000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+					<Class name="AZ::u64" field="NavigationRepeatDelay" value="300" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+					<Class name="AZ::u64" field="NavigationRepeatPeriod" value="150" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+					<Class name="EntityId" field="FirstHoverElement" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+						<Class name="AZ::u64" field="id" value="4294967295" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+					</Class>
+					<Class name="UiAnimationSystem" field="AnimSystem" version="1" type="{2592269B-EF74-4409-B29F-682DC0B45DAF}">
+						<Class name="AZStd::vector&lt;AZStd::intrusive_ptr&lt;IUiAnimSequence&gt;, allocator&gt;" field="Sequences" type="{9F8D44A9-9731-5314-885E-B958D4216073}"/>
+					</Class>
+					<Class name="AnimationData" field="AnimationData" version="1" type="{FDC58CF7-8109-48F2-8D5D-BCBAF774ABB7}">
+						<Class name="AZStd::string" field="SerializeString" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+					</Class>
+					<Class name="EntityId" field="TooltipDisplayElement" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+						<Class name="AZ::u64" field="id" value="4294967295" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+					</Class>
+					<Class name="float" field="SnapDistance" value="10.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+					<Class name="float" field="SnapRotationDegrees" value="10.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+					<Class name="AZStd::vector&lt;float, allocator&gt;" field="HorizontalGuides" type="{6106BF95-5ACD-5071-8D0E-4F846C2138AD}"/>
+					<Class name="AZStd::vector&lt;float, allocator&gt;" field="VerticalGuides" type="{6106BF95-5ACD-5071-8D0E-4F846C2138AD}"/>
+					<Class name="Color" field="GuideColor" value="0.2500000 1.0000000 0.2500000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
+					<Class name="bool" field="GuidesLocked" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+					<Class name="AZStd::vector&lt;SimpleAssetReference&lt;TextureAtlasAsset&gt;, allocator&gt;" field="TextureAtlases" type="{73F8CC7B-8504-5F80-BD45-1620CD7EF9AB}"/>
+				</Class>
+			</Class>
+			<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+			<Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+		</Class>
+		<Class name="AZ::Entity" field="RootSliceEntity" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
+			<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+				<Class name="AZ::u64" field="id" value="479223399868" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+			</Class>
+			<Class name="AZStd::string" field="Name" value="479223399868" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+			<Class name="AZStd::vector&lt;AZ::Component*, allocator&gt;" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
+				<Class name="SliceComponent" field="element" version="3" type="{AFD304E4-1773-47C8-855A-8B622398934F}">
+					<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+						<Class name="AZ::u64" field="Id" value="2590986407960043829" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+					</Class>
+					<Class name="AZStd::vector&lt;AZ::Entity*, allocator&gt;" field="Entities" type="{21786AF0-2606-5B9A-86EB-0892E2820E6C}">
+						<Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
+							<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+								<Class name="AZ::u64" field="id" value="487813334460" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+							</Class>
+							<Class name="AZStd::string" field="Name" value="_root" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+							<Class name="AZStd::vector&lt;AZ::Component*, allocator&gt;" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
+								<Class name="EditorOnlyEntityComponent" field="element" type="{22A16F1D-6D49-422D-AAE9-91AE45B5D3E7}">
+									<Class name="EditorComponentBase" field="BaseClass1" version="1" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}">
+										<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+											<Class name="AZ::u64" field="Id" value="8296342203764853668" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
+									</Class>
+									<Class name="bool" field="IsEditorOnly" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+								</Class>
+								<Class name="UiTransform2dComponent" field="element" version="3" type="{2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="1417335033688256310" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="Anchors" field="Anchors" type="{65D4346C-FB16-4CB0-9BDC-1185B122C4A9}">
+										<Class name="float" field="left" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Offsets" field="Offsets" type="{F681BA9D-245C-4630-B20E-05DD752FAD57}">
+										<Class name="float" field="left" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Vector2" field="Pivot" value="0.5000000 0.5000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="float" field="Rotation" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="Vector2" field="Scale" value="1.0000000 1.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="int" field="ScaleToDevice" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+								</Class>
+								<Class name="UiElementComponent" field="element" version="3" type="{4A97D63E-CE7A-45B6-AAE4-102DB4334688}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="2955930260092508917" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="unsigned int" field="Id" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="bool" field="IsEnabled" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsVisibleInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;" field="ChildEntityIdOrder" type="{0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62}">
+										<Class name="ChildEntityIdOrderEntry" field="element" version="1" type="{D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2}">
+											<Class name="EntityId" field="ChildEntityId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+												<Class name="AZ::u64" field="id" value="492108301756" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+											</Class>
+											<Class name="AZ::u64" field="SortIndex" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
+										<Class name="ChildEntityIdOrderEntry" field="element" version="1" type="{D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2}">
+											<Class name="EntityId" field="ChildEntityId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+												<Class name="AZ::u64" field="id" value="496403269052" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+											</Class>
+											<Class name="AZ::u64" field="SortIndex" value="1" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
+										<Class name="ChildEntityIdOrderEntry" field="element" version="1" type="{D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2}">
+											<Class name="EntityId" field="ChildEntityId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+												<Class name="AZ::u64" field="id" value="500698236348" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+											</Class>
+											<Class name="AZ::u64" field="SortIndex" value="2" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
+										<Class name="ChildEntityIdOrderEntry" field="element" version="1" type="{D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2}">
+											<Class name="EntityId" field="ChildEntityId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+												<Class name="AZ::u64" field="id" value="504993203644" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+											</Class>
+											<Class name="AZ::u64" field="SortIndex" value="3" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
+										<Class name="ChildEntityIdOrderEntry" field="element" version="1" type="{D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2}">
+											<Class name="EntityId" field="ChildEntityId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+												<Class name="AZ::u64" field="id" value="509288170940" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+											</Class>
+											<Class name="AZ::u64" field="SortIndex" value="4" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
+									</Class>
+								</Class>
+							</Class>
+							<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+							<Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+						</Class>
+						<Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
+							<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+								<Class name="AZ::u64" field="id" value="496403269052" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+							</Class>
+							<Class name="AZStd::string" field="Name" value="Image2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+							<Class name="AZStd::vector&lt;AZ::Component*, allocator&gt;" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
+								<Class name="EditorOnlyEntityComponent" field="element" type="{22A16F1D-6D49-422D-AAE9-91AE45B5D3E7}">
+									<Class name="EditorComponentBase" field="BaseClass1" version="1" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}">
+										<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+											<Class name="AZ::u64" field="Id" value="6090667790069324941" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
+									</Class>
+									<Class name="bool" field="IsEditorOnly" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+								</Class>
+								<Class name="UiTransform2dComponent" field="element" version="3" type="{2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="8387065614562102859" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="Anchors" field="Anchors" type="{65D4346C-FB16-4CB0-9BDC-1185B122C4A9}">
+										<Class name="float" field="left" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Offsets" field="Offsets" type="{F681BA9D-245C-4630-B20E-05DD752FAD57}">
+										<Class name="float" field="left" value="-158.4188843" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="-58.4188919" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Vector2" field="Pivot" value="0.5000000 0.5000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="float" field="Rotation" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="Vector2" field="Scale" value="1.0000000 1.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="int" field="ScaleToDevice" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+								</Class>
+								<Class name="UiElementComponent" field="element" version="3" type="{4A97D63E-CE7A-45B6-AAE4-102DB4334688}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="16657781940265029894" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="unsigned int" field="Id" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="bool" field="IsEnabled" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsVisibleInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;" field="ChildEntityIdOrder" type="{0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62}"/>
+								</Class>
+								<Class name="UiImageComponent" field="element" version="8" type="{BDBEFD23-DBB4-4726-A32D-4FEAC24E51F6}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="8899143841318558907" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="int" field="SpriteType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="SimpleAssetReference&lt;TextureAsset&gt;" field="SpritePath" version="1" type="{6E0B1C86-F66A-5D30-BCBB-0F9EA199E4AF}">
+										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
+											<Class name="AZStd::string" field="AssetPath" value="ama_grey_01.tif" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+										</Class>
+									</Class>
+									<Class name="unsigned int" field="Index" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="Asset&lt;AttachmentImageAsset&gt;" field="AttachmentImageAsset" value="id={00000000-0000-0000-0000-000000000000}:0,type={82CEA86B-E891-4969-8F35-D8017E8902C8},hint={},loadBehavior=1" version="3" type="{61538C1C-2EDA-593B-AA53-701FF7D854E7}"/>
+									<Class name="bool" field="IsRenderTargetSRGB" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="Color" field="Color" value="1.0000000 1.0000000 1.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
+									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="int" field="ImageType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="bool" field="FillCenter" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="StretchSliced" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="int" field="BlendMode" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="FillType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="float" field="FillAmount" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="float" field="FillStartAngle" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="int" field="FillCornerOrigin" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="FillEdgeOrigin" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="bool" field="FillClockwise" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+								</Class>
+							</Class>
+							<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+							<Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+						</Class>
+						<Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
+							<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+								<Class name="AZ::u64" field="id" value="500698236348" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+							</Class>
+							<Class name="AZStd::string" field="Name" value="Image3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+							<Class name="AZStd::vector&lt;AZ::Component*, allocator&gt;" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
+								<Class name="EditorOnlyEntityComponent" field="element" type="{22A16F1D-6D49-422D-AAE9-91AE45B5D3E7}">
+									<Class name="EditorComponentBase" field="BaseClass1" version="1" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}">
+										<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+											<Class name="AZ::u64" field="Id" value="4225407189794244608" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
+									</Class>
+									<Class name="bool" field="IsEditorOnly" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+								</Class>
+								<Class name="UiTransform2dComponent" field="element" version="3" type="{2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="10653913905093048091" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="Anchors" field="Anchors" type="{65D4346C-FB16-4CB0-9BDC-1185B122C4A9}">
+										<Class name="float" field="left" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Offsets" field="Offsets" type="{F681BA9D-245C-4630-B20E-05DD752FAD57}">
+										<Class name="float" field="left" value="60.8829575" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="160.8829651" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Vector2" field="Pivot" value="0.5000000 0.5000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="float" field="Rotation" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="Vector2" field="Scale" value="1.0000000 1.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="int" field="ScaleToDevice" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+								</Class>
+								<Class name="UiElementComponent" field="element" version="3" type="{4A97D63E-CE7A-45B6-AAE4-102DB4334688}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="14510703990579393410" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="unsigned int" field="Id" value="4" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="bool" field="IsEnabled" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsVisibleInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;" field="ChildEntityIdOrder" type="{0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62}"/>
+								</Class>
+								<Class name="UiImageComponent" field="element" version="8" type="{BDBEFD23-DBB4-4726-A32D-4FEAC24E51F6}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="3027781663307535247" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="int" field="SpriteType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="SimpleAssetReference&lt;TextureAsset&gt;" field="SpritePath" version="1" type="{6E0B1C86-F66A-5D30-BCBB-0F9EA199E4AF}">
+										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
+											<Class name="AZStd::string" field="AssetPath" value="ama_white_01.tif" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+										</Class>
+									</Class>
+									<Class name="unsigned int" field="Index" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="Asset&lt;AttachmentImageAsset&gt;" field="AttachmentImageAsset" value="id={00000000-0000-0000-0000-000000000000}:0,type={82CEA86B-E891-4969-8F35-D8017E8902C8},hint={},loadBehavior=1" version="3" type="{61538C1C-2EDA-593B-AA53-701FF7D854E7}"/>
+									<Class name="bool" field="IsRenderTargetSRGB" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="Color" field="Color" value="1.0000000 1.0000000 1.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
+									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="int" field="ImageType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="bool" field="FillCenter" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="StretchSliced" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="int" field="BlendMode" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="FillType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="float" field="FillAmount" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="float" field="FillStartAngle" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="int" field="FillCornerOrigin" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="FillEdgeOrigin" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="bool" field="FillClockwise" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+								</Class>
+							</Class>
+							<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+							<Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+						</Class>
+						<Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
+							<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+								<Class name="AZ::u64" field="id" value="492108301756" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+							</Class>
+							<Class name="AZStd::string" field="Name" value="Image1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+							<Class name="AZStd::vector&lt;AZ::Component*, allocator&gt;" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
+								<Class name="EditorOnlyEntityComponent" field="element" type="{22A16F1D-6D49-422D-AAE9-91AE45B5D3E7}">
+									<Class name="EditorComponentBase" field="BaseClass1" version="1" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}">
+										<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+											<Class name="AZ::u64" field="Id" value="14527494804262531044" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
+									</Class>
+									<Class name="bool" field="IsEditorOnly" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+								</Class>
+								<Class name="UiTransform2dComponent" field="element" version="3" type="{2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="1653241725306964827" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="Anchors" field="Anchors" type="{65D4346C-FB16-4CB0-9BDC-1185B122C4A9}">
+										<Class name="float" field="left" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Offsets" field="Offsets" type="{F681BA9D-245C-4630-B20E-05DD752FAD57}">
+										<Class name="float" field="left" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Vector2" field="Pivot" value="0.5000000 0.5000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="float" field="Rotation" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="Vector2" field="Scale" value="1.0000000 1.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="int" field="ScaleToDevice" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+								</Class>
+								<Class name="UiElementComponent" field="element" version="3" type="{4A97D63E-CE7A-45B6-AAE4-102DB4334688}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="16329198947015742888" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="unsigned int" field="Id" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="bool" field="IsEnabled" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsVisibleInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;" field="ChildEntityIdOrder" type="{0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62}"/>
+								</Class>
+								<Class name="UiImageComponent" field="element" version="8" type="{BDBEFD23-DBB4-4726-A32D-4FEAC24E51F6}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="7841180896507436090" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="int" field="SpriteType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="SimpleAssetReference&lt;TextureAsset&gt;" field="SpritePath" version="1" type="{6E0B1C86-F66A-5D30-BCBB-0F9EA199E4AF}">
+										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
+											<Class name="AZStd::string" field="AssetPath" value="ama_green_01.tif" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+										</Class>
+									</Class>
+									<Class name="unsigned int" field="Index" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="Asset&lt;AttachmentImageAsset&gt;" field="AttachmentImageAsset" value="id={00000000-0000-0000-0000-000000000000}:0,type={82CEA86B-E891-4969-8F35-D8017E8902C8},hint={},loadBehavior=1" version="3" type="{61538C1C-2EDA-593B-AA53-701FF7D854E7}"/>
+									<Class name="bool" field="IsRenderTargetSRGB" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="Color" field="Color" value="1.0000000 1.0000000 1.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
+									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="int" field="ImageType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="bool" field="FillCenter" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="StretchSliced" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="int" field="BlendMode" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="FillType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="float" field="FillAmount" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="float" field="FillStartAngle" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="int" field="FillCornerOrigin" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="FillEdgeOrigin" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="bool" field="FillClockwise" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+								</Class>
+							</Class>
+							<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+							<Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+						</Class>
+						<Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
+							<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+								<Class name="AZ::u64" field="id" value="509288170940" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+							</Class>
+							<Class name="AZStd::string" field="Name" value="StringB" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+							<Class name="AZStd::vector&lt;AZ::Component*, allocator&gt;" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
+								<Class name="EditorOnlyEntityComponent" field="element" type="{22A16F1D-6D49-422D-AAE9-91AE45B5D3E7}">
+									<Class name="EditorComponentBase" field="BaseClass1" version="1" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}">
+										<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+											<Class name="AZ::u64" field="Id" value="11423924478304368427" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
+									</Class>
+									<Class name="bool" field="IsEditorOnly" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+								</Class>
+								<Class name="UiTransform2dComponent" field="element" version="3" type="{2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="3389394107544437620" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="Anchors" field="Anchors" type="{65D4346C-FB16-4CB0-9BDC-1185B122C4A9}">
+										<Class name="float" field="left" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Offsets" field="Offsets" type="{F681BA9D-245C-4630-B20E-05DD752FAD57}">
+										<Class name="float" field="left" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="-32.7515411" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="67.2484589" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Vector2" field="Pivot" value="0.5000000 0.5000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="float" field="Rotation" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="Vector2" field="Scale" value="1.0000000 1.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="int" field="ScaleToDevice" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+								</Class>
+								<Class name="UiElementComponent" field="element" version="3" type="{4A97D63E-CE7A-45B6-AAE4-102DB4334688}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="304592595352478546" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="unsigned int" field="Id" value="6" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="bool" field="IsEnabled" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsVisibleInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;" field="ChildEntityIdOrder" type="{0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62}"/>
+								</Class>
+								<Class name="UiTextComponent" field="element" version="9" type="{5B3FB2A7-5DC4-4033-A970-001CEC85B6C4}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="1428988889681071293" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="AZStd::string" field="Text" value="String 2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+									<Class name="bool" field="MarkupEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="Color" field="Color" value="1.0000000 1.0000000 1.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
+									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
+										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
+											<Class name="AZStd::string" field="AssetPath" value="default2048.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+										</Class>
+									</Class>
+									<Class name="float" field="FontSize" value="32.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="unsigned int" field="EffectIndex" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="int" field="TextHAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="TextVAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="float" field="CharacterSpacing" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="float" field="LineSpacing" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="int" field="OverflowMode" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="WrapTextSetting" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="ShrinkToFit" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="float" field="MinShrinkScale" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+								</Class>
+							</Class>
+							<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+							<Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+						</Class>
+						<Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
+							<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+								<Class name="AZ::u64" field="id" value="504993203644" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+							</Class>
+							<Class name="AZStd::string" field="Name" value="StringA" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+							<Class name="AZStd::vector&lt;AZ::Component*, allocator&gt;" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
+								<Class name="EditorOnlyEntityComponent" field="element" type="{22A16F1D-6D49-422D-AAE9-91AE45B5D3E7}">
+									<Class name="EditorComponentBase" field="BaseClass1" version="1" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}">
+										<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+											<Class name="AZ::u64" field="Id" value="14981437203688256870" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
+									</Class>
+									<Class name="bool" field="IsEditorOnly" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+								</Class>
+								<Class name="UiTransform2dComponent" field="element" version="3" type="{2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="13998432843499002612" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="Anchors" field="Anchors" type="{65D4346C-FB16-4CB0-9BDC-1185B122C4A9}">
+										<Class name="float" field="left" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="0.5000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Offsets" field="Offsets" type="{F681BA9D-245C-4630-B20E-05DD752FAD57}">
+										<Class name="float" field="left" value="-50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="-77.1047211" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="50.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="22.8952770" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Vector2" field="Pivot" value="0.5000000 0.5000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="float" field="Rotation" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="Vector2" field="Scale" value="1.0000000 1.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="int" field="ScaleToDevice" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+								</Class>
+								<Class name="UiElementComponent" field="element" version="3" type="{4A97D63E-CE7A-45B6-AAE4-102DB4334688}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="14496178371394383110" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="unsigned int" field="Id" value="5" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="bool" field="IsEnabled" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsVisibleInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;" field="ChildEntityIdOrder" type="{0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62}"/>
+								</Class>
+								<Class name="UiTextComponent" field="element" version="9" type="{5B3FB2A7-5DC4-4033-A970-001CEC85B6C4}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="6443965789941675950" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="AZStd::string" field="Text" value="String A" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+									<Class name="bool" field="MarkupEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="Color" field="Color" value="1.0000000 1.0000000 1.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
+									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
+										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
+											<Class name="AZStd::string" field="AssetPath" value="default1024.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+										</Class>
+									</Class>
+									<Class name="float" field="FontSize" value="32.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="unsigned int" field="EffectIndex" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="int" field="TextHAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="TextVAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="float" field="CharacterSpacing" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="float" field="LineSpacing" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="int" field="OverflowMode" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="WrapTextSetting" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="ShrinkToFit" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="float" field="MinShrinkScale" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+								</Class>
+							</Class>
+							<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+							<Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+						</Class>
+					</Class>
+					<Class name="AZStd::list&lt;SliceReference, allocator&gt;" field="Prefabs" type="{DAD45EB6-5853-5645-B762-3A37F8775E12}"/>
+					<Class name="bool" field="IsDynamic" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+					<Class name="AZ::Entity" field="MetadataEntity" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
+						<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+							<Class name="AZ::u64" field="id" value="483518367164" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+						</Class>
+						<Class name="AZStd::string" field="Name" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+						<Class name="AZStd::vector&lt;AZ::Component*, allocator&gt;" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
+							<Class name="SliceMetadataInfoComponent" field="element" version="2" type="{25EE4D75-8A17-4449-81F4-E561005BAABD}">
+								<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+									<Class name="AZ::u64" field="Id" value="6119851056583331912" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+								</Class>
+								<Class name="AZStd::set&lt;EntityId, AZStd::less&lt;EntityId&gt;, allocator&gt;" field="AssociatedIds" type="{78E024C3-0143-53FC-B393-0675227839AF}"/>
+								<Class name="EntityId" field="ParentId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+									<Class name="AZ::u64" field="id" value="4294967295" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+								</Class>
+								<Class name="AZStd::unordered_set&lt;EntityId, AZStd::hash&lt;EntityId&gt;, AZStd::equal_to&lt;EntityId&gt;, allocator&gt;" field="ChildrenIds" type="{6C8F8E52-AB4A-5C1F-8E56-9AC390290B94}"/>
+								<Class name="bool" field="PersistenceFlag" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+							</Class>
+						</Class>
+						<Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+						<Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+					</Class>
+					<Class name="DataFlagsPerEntity" field="DataFlagsForNewEntities" version="1" type="{57FE7B9E-B2AF-4F6F-9F8D-87F671E91C99}">
+						<Class name="AZStd::unordered_map&lt;EntityId, AZStd::unordered_map&lt;AddressType, unsigned char, AZStd::hash&lt;AddressType&gt;, AZStd::equal_to&lt;AddressType&gt;, allocator&gt;, AZStd::hash&lt;EntityId&gt;, AZStd::equal_to&lt;EntityId&gt;, allocator&gt;" field="EntityToDataFlags" type="{CAB9E1F5-761E-54B8-916E-E7FB597E5EDE}"/>
+					</Class>
+				</Class>
+			</Class>
+			<Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+			<Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+		</Class>
+	</Class>
+</ObjectStream>
+

+ 3 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/SeedWithDependencies/default1024.font

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ebb0258eb7bdd50e4687d589d8cd7cca0af47ddfdb26d63f53b7e930556b2864
+size 261

+ 3 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/SeedWithDependencies/default2048.font

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:922a3fd98211deab4ba49bf9eacbe1e0d09e1bea435ab2a97b8240b9d78d87c5
+size 262

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/multiple_corrupted_prefab/corrupted_prefab1.prefab

@@ -0,0 +1 @@
+This is a file created to act as a purposely corrupted prefab for use in test.

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/multiple_corrupted_prefab/corrupted_prefab2.prefab

@@ -0,0 +1 @@
+This is a file created to act as a purposely corrupted prefab for use in test.

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/multiple_working_prefab/working_prefab1.prefab

@@ -0,0 +1 @@
+{}

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/multiple_working_prefab/working_prefab2.prefab

@@ -0,0 +1 @@
+{}

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/single_corrupted_prefab/corrupted_prefab.prefab

@@ -0,0 +1 @@
+This is a file created to act as a purposely corrupted prefab for use in test.

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/single_working_prefab/working_prefab.prefab

@@ -0,0 +1 @@
+{}

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/TestAssets/single_working_prefab_override/working_prefab.prefab

@@ -0,0 +1 @@
+{ }

+ 3 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/datfile_0.dat

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:310e481a3de7fdce8565017090acde92f32734e5d0d79945d418ee55af163acf
+size 148

+ 3 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/datfile_1.dat

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:310e481a3de7fdce8565017090acde92f32734e5d0d79945d418ee55af163acf
+size 148

+ 3 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/datfile_2.dat

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:310e481a3de7fdce8565017090acde92f32734e5d0d79945d418ee55af163acf
+size 148

+ 3 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/datfile_3.dat

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:310e481a3de7fdce8565017090acde92f32734e5d0d79945d418ee55af163acf
+size 148

+ 3 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/datfile_4.dat

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:310e481a3de7fdce8565017090acde92f32734e5d0d79945d418ee55af163acf
+size 148

+ 3 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/datfile_5.dat

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:310e481a3de7fdce8565017090acde92f32734e5d0d79945d418ee55af163acf
+size 148

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/txtfile_0.txt

@@ -0,0 +1 @@
+I am a text file! this is my contents. I should be filter-able (if that's a word) by my ".txt" extension.

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/txtfile_1.txt

@@ -0,0 +1 @@
+I am a text file! this is my contents. I should be filter-able (if that's a word) by my ".txt" extension.

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/txtfile_2.txt

@@ -0,0 +1 @@
+I am a text file! this is my contents. I should be filter-able (if that's a word) by my ".txt" extension.

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/txtfile_3.txt

@@ -0,0 +1 @@
+I am a text file! this is my contents. I should be filter-able (if that's a word) by my ".txt" extension.

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/txtfile_4.txt

@@ -0,0 +1 @@
+I am a text file! this is my contents. I should be filter-able (if that's a word) by my ".txt" extension.

+ 1 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/assets/asset_bundler_test_assets/txtfile_5.txt

@@ -0,0 +1 @@
+I am a text file! this is my contents. I should be filter-able (if that's a word) by my ".txt" extension.

+ 0 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/bundle_mode_in_editor_tests.py → AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/bundle_mode_in_editor_tests.py


+ 4 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/bundle_mode_tests.py → AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/bundle_mode_tests.py

@@ -18,10 +18,12 @@ import ly_test_tools.log.log_monitor
 
 from ly_test_tools.o3de.editor_test_utils import compile_test_case_name_from_request
 
+from ..ap_fixtures.ap_setup_fixture import ap_setup_fixture
 from ..ap_fixtures.asset_processor_fixture import asset_processor as asset_processor
 from ..ap_fixtures.bundler_batch_setup_fixture import bundler_batch_setup_fixture as bundler_batch_helper
 from ..ap_fixtures.timeout_option_fixture import timeout_option_fixture as timeout
 
+
 @pytest.mark.SUITE_periodic
 @pytest.mark.parametrize('launcher_platform', ['windows_editor'])
 @pytest.mark.parametrize('project', ['AutomatedTesting'])
@@ -30,6 +32,8 @@ from ..ap_fixtures.timeout_option_fixture import timeout_option_fixture as timeo
 class TestBundleMode(object):
     def test_bundle_mode_with_levels_mounts_bundles_correctly(self, request, editor, level, launcher_platform,
                                                               asset_processor, workspace, bundler_batch_helper):
+        asset_processor.add_source_folder_assets("AutomatedTesting\\Levels\\TestDependenciesLevel")
+        asset_processor.batch_process()
         level_pak = os.path.join("levels", level, "TestDependenciesLevel.spawnable")
         bundles_folder = os.path.join(workspace.paths.project(), "Bundles")
         bundle_request_path = os.path.join(bundles_folder, "bundle.pak")

+ 0 - 0
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/conftest.py → AutomatedTesting/Gem/PythonTests/assetpipeline/asset_bundler_tests/conftest.py


+ 0 - 22
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt

@@ -244,16 +244,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
 
 ## Periodic Tests ##
 
-    ly_add_pytest(
-        NAME APTests.AssetBundler
-        PATH ${CMAKE_CURRENT_LIST_DIR}/asset_bundler_batch_tests.py
-        TEST_SERIAL 
-        TEST_SUITE periodic
-        RUNTIME_DEPENDENCIES
-            AZ::AssetProcessor
-            AZ::AssetBundlerBatch
-    )
-
     ly_add_pytest(
         NAME APTests.MissingDependency
         PATH ${CMAKE_CURRENT_LIST_DIR}/missing_dependency_tests.py
@@ -263,16 +253,4 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
             AZ::AssetProcessorBatch
     )
 
-    ly_add_pytest(
-        NAME APTests.BundleMode
-        PATH ${CMAKE_CURRENT_LIST_DIR}/bundle_mode_tests.py
-        TEST_SERIAL
-        TEST_SUITE periodic
-        RUNTIME_DEPENDENCIES
-            AZ::AssetProcessor
-            AZ::AssetBundlerBatch
-            Legacy::Editor
-            AutomatedTesting.Assets
-    )
-
 endif()

+ 1 - 1
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_gui_tests_2.py

@@ -319,7 +319,7 @@ class TestsAssetProcessorGUI_AllPlatforms(object):
         # Expected test asset sources and products
         # *.assetinfo and *.fbx files are not produced in cache, and file.fbx produces file.actor in cache
         expected_test_assets = ["Jack.fbx", "Jack.fbx.assetinfo"]
-        expected_cache_assets = ["jack.actor"]
+        expected_cache_assets = ["jack.actor", "jack.assetinfo.dbg", "jack.dbgsg", "jack.dbgsg.xml", "jack.dbgsg.json"]
 
         # Copy test assets to project folder and verify test assets folder exists
         test_assets_folder, cache_folder = asset_processor.prepare_test_environment(env["tests_dir"], "C24168802")

+ 1 - 1
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/missing_dependency_tests.py

@@ -60,7 +60,7 @@ class TestsMissingDependencies_WindowsAndMac(object):
         self._missing_dep_helper = missing_dep_helper
         self._asset_processor.create_temp_asset_root()
         self._asset_processor.add_source_folder_assets(f"AutomatedTesting\\TestAssets")
-        missing_dep_helper.asset_db = os.path.join(asset_processor.temp_asset_root(), "Cache",
+        missing_dep_helper.asset_db = os.path.join(asset_processor.temp_asset_root(), self._workspace.project, "Cache",
                                                    "assetdb.sqlite")
         self._asset_processor.add_source_folder_assets(f"{self._workspace.project}\\Prefabs")
         self._asset_processor.add_source_folder_assets(f"{self._workspace.project}\\Materials")

+ 2 - 2
AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/fbx_tests.py

@@ -1090,9 +1090,9 @@ class TestsFBX_AllPlatforms(object):
             f'The following assets were expected to be in, but not found in cache: {str(missing_assets)}'
 
         # Load the asset database.
-        db_path = os.path.join(asset_processor.temp_asset_root(), "Cache",
+        db_path = os.path.join(asset_processor.temp_asset_root(), workspace.project, "Cache",
                                "assetdb.sqlite")
-        cache_root = os.path.dirname(os.path.join(asset_processor.temp_asset_root(), "Cache",
+        cache_root = os.path.dirname(os.path.join(asset_processor.temp_asset_root(), workspace.project, "Cache",
                                                   ASSET_PROCESSOR_PLATFORM_MAP[workspace.asset_processor_platform]))
 
         if blackbox_params.scene_debug_file:

+ 7 - 11
AutomatedTesting/Gem/PythonTests/assetpipeline/fbx_tests/pythonassetbuildertests.py

@@ -103,11 +103,7 @@ class TestsPythonAssetProcessing_APBatch(object):
         assert result, "AP Batch failed"
 
         # compute the cache path
-        platform = workspace.asset_processor_platform
-        cache_folder = asset_processor.temp_asset_root()
-        if platform == 'windows':
-            platform = 'pc'
-        cache_folder = os.path.join(cache_folder, 'Cache', platform)
+        cache_folder = asset_processor.project_test_cache_folder()
 
         # compute the file name to the debug file
         asset_debug_filename = os.path.join(cache_folder, debug_filename)
@@ -119,7 +115,7 @@ class TestsPythonAssetProcessing_APBatch(object):
     def test_ProcessSceneWithMetadata_SupportedMayaDataTypes_Work(self, workspace, ap_setup_fixture, asset_processor):
         # This test loads the debug output file for an FBX exported by Maya that has a few user defined properties
 
-        asset_dbgsg = 'userdefinedproperties/maya_with_attributes.dbgsg'
+        asset_dbgsg = 'maya_with_attributes.dbgsg'
         dbgsg_file = self.compute_udp_asset_debug_file(workspace, asset_processor, asset_dbgsg, ap_setup_fixture)
         assert self.find_user_defined_property(dbgsg_file, 'o3de_atom_lod: false'), "Malformed o3de_atom_lod value"
         assert self.find_user_defined_property(dbgsg_file, 'o3de_atom_material: 0'), "Malformed o3de_atom_material value"
@@ -129,7 +125,7 @@ class TestsPythonAssetProcessing_APBatch(object):
     def test_ProcessSceneWithMetadata_SupportedMaxDataTypes_Work(self, workspace, ap_setup_fixture, asset_processor):
         # This test loads the debug output file for an FBX exported by Max that has a few user defined properties
 
-        asset_dbgsg = 'userdefinedproperties/max_with_attributes.dbgsg'
+        asset_dbgsg = 'max_with_attributes.dbgsg'
         dbgsg_file = self.compute_udp_asset_debug_file(workspace, asset_processor, asset_dbgsg, ap_setup_fixture)
         assert self.find_user_defined_property(dbgsg_file, 'o3de_atom_material: 0'), "Malformed o3de_atom_material value"
         assert self.find_user_defined_property(dbgsg_file, 'o3de_phyx_lodY: 0.000000'), "Malformed o3de_phyx_lodY value"
@@ -140,7 +136,7 @@ class TestsPythonAssetProcessing_APBatch(object):
     def test_ProcessSceneWithMetadata_SupportedBlenderDataTypes_Work(self, workspace, ap_setup_fixture, asset_processor):
         # This test loads the debug output file for an FBX exported by Blender that has a few user defined properties
 
-        asset_dbgsg = 'userdefinedproperties/blender_with_attributes.dbgsg'
+        asset_dbgsg = 'blender_with_attributes.dbgsg'
         dbgsg_file = self.compute_udp_asset_debug_file(workspace, asset_processor, asset_dbgsg, ap_setup_fixture)
         assert self.find_user_defined_property(dbgsg_file, 'o3de_atom_material: 0'), "Malformed o3de_atom_material value"
         assert self.find_user_defined_property(dbgsg_file, 'o3de_default_lod: 0.000000'), "Malformed o3de_default_lod value"
@@ -150,7 +146,7 @@ class TestsPythonAssetProcessing_APBatch(object):
     def test_ProcessSceneWithMetadata_DebugSceneManifest_Work(self, workspace, ap_setup_fixture, asset_processor):
         # This test detects the debug .assetinfo file in the cahce folder
 
-        assetinfo_dbg = 'userdefinedproperties/blender_with_attributes.assetinfo.dbg'
+        assetinfo_dbg = 'blender_with_attributes.assetinfo.dbg'
         assetinfo_dbg_file = self.compute_udp_asset_debug_file(workspace, asset_processor, assetinfo_dbg, ap_setup_fixture)
         assert assetinfo_dbg_file, "The debug assetinfo file is missing"
 
@@ -159,8 +155,8 @@ class TestsPythonAssetProcessing_APBatch(object):
         # of a scene containing mesh nodes that have a common parent transform node
 
         assetinfo_dbg_list = {
-            "meshgroups/blender_with_common_parent.assetinfo.dbg",
-            "meshgroups/maya_with_common_parent.assetinfo.dbg"
+            "blender_with_common_parent.assetinfo.dbg",
+            "maya_with_common_parent.assetinfo.dbg"
         }
 
         expected_mesh_nodes = {

+ 1 - 1
AutomatedTesting/Gem/PythonTests/scripting/EditMenu_Default_UndoRedo.py

@@ -39,7 +39,7 @@ def EditMenu_Default_UndoRedo():
 
     # Preconditions
     import azlmbr.legacy.general as general
-    from editor_python_test_tools.QtPyO3DEEditor import QtPyO3DEEditor
+    from editor_python_test_tools.QtPy.QtPyO3DEEditor import QtPyO3DEEditor
 
     general.idle_enable(True)
 

+ 1 - 1
AutomatedTesting/Gem/PythonTests/scripting/NodePalette_HappyPath_ClearSelection.py

@@ -37,7 +37,7 @@ def NodePalette_HappyPath_ClearSelection():
     #Preconditions
     from editor_python_test_tools.utils import Report
     import azlmbr.legacy.general as general
-    from editor_python_test_tools.QtPyO3DEEditor import QtPyO3DEEditor
+    from editor_python_test_tools.QtPy.QtPyO3DEEditor import QtPyO3DEEditor
     from consts.scripting import (NODE_STRING_TO_NUMBER)
 
     general.idle_enable(True)

+ 1 - 1
AutomatedTesting/Gem/PythonTests/scripting/ScriptEvent_AddRemoveMethod_UpdatesInSC.py

@@ -37,7 +37,7 @@ def ScriptEvent_AddRemoveMethod_UpdatesInSC():
     import azlmbr.paths as paths
     from editor_python_test_tools.utils import Report
     import azlmbr.legacy.general as general
-    from editor_python_test_tools.QtPyO3DEEditor import QtPyO3DEEditor
+    from editor_python_test_tools.QtPy.QtPyO3DEEditor import QtPyO3DEEditor
     from consts.asset_editor import (SCRIPT_EVENT_UI, NODE_TEST_METHOD)
 
     general.idle_enable(True)

+ 2 - 2
AutomatedTesting/Gem/PythonTests/scripting/VariableManager_ExposeVarsToComponent.py

@@ -36,10 +36,10 @@ def VariableManager_ExposeVarsToComponent():
     """
 
     # Preconditions
-    from editor_python_test_tools.QtPyO3DEEditor import QtPyO3DEEditor
+    from editor_python_test_tools.QtPy.QtPyO3DEEditor import QtPyO3DEEditor
     from editor_python_test_tools.editor_component.editor_script_canvas import ScriptCanvasComponent, VariableState
     import editor_python_test_tools.editor_component.editor_component_validation as Validators
-    from editor_python_test_tools.QtPyCommon import CheckBoxStates
+    from editor_python_test_tools.QtPy.QtPyCommon import CheckBoxStates
     import azlmbr.legacy.general as general
     from consts.scripting import (SCRIPT_CANVAS_TEST_FILE_PATH)
     from editor_python_test_tools.editor_entity_utils import EditorEntity

+ 1 - 1
AutomatedTesting/Gem/PythonTests/scripting/VariableManager_UnpinVariableType_Works.py

@@ -26,7 +26,7 @@ def VariableManager_UnpinVariableType_Works():
     """
 
     # Preconditions
-    from editor_python_test_tools.QtPyO3DEEditor import QtPyO3DEEditor
+    from editor_python_test_tools.QtPy.QtPyO3DEEditor import QtPyO3DEEditor
     import azlmbr.legacy.general as general
     from consts.scripting import (SCRIPT_CANVAS_UI, RESTORE_DEFAULT_LAYOUT)
 

+ 1 - 1
CMakeLists.txt

@@ -24,7 +24,7 @@ if(NOT PROJECT_NAME)
     include(cmake/CompilerSettings.cmake)
     project(O3DE
         LANGUAGES C CXX
-        VERSION ${LY_VERSION_STRING}
+        VERSION ${O3DE_VERSION_STRING}
     )
 endif()
 

+ 117 - 12
Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp

@@ -21,9 +21,11 @@
 #include <AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h>
 #include <AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h>
 #include <AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntryUtils.h>
+#include <AzToolsFramework/AssetBrowser/AssetBrowserEntityInspectorWidget.h>
 
 // AzQtComponents
 #include <AzQtComponents/Utilities/QtWindowUtilities.h>
+#include <AzQtComponents/Components/Widgets/AssetFolderThumbnailView.h>
 
 // Editor
 #include "AzAssetBrowser/AzAssetBrowserRequestHandler.h"
@@ -41,6 +43,8 @@ AZ_CVAR(bool, ed_useWIPAssetBrowserDesign, false, nullptr, AZ::ConsoleFunctorFla
 //! the layout changes to accomodate its narrow state better. See AzAssetBrowserWindow::SetNarrowMode
 static constexpr int s_narrowModeThreshold = 700;
 
+using namespace AzToolsFramework::AssetBrowser;
+
 namespace AzToolsFramework
 {
     namespace AssetBrowser
@@ -154,9 +158,93 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent)
             m_ui->m_searchWidget, &AzAssetBrowser::SearchWidget::ClearTypeFilter);
 
         m_ui->m_assetBrowserTableViewWidget->SetName("AssetBrowserTableView_main");
-    }
 
-    m_ui->m_thumbnailView->SetPreviewerFrame(m_ui->m_previewerFrame);
+        connect(
+            m_ui->m_thumbnailView,
+            &AssetBrowserThumbnailView::entryDoubleClicked,
+            this,
+            [this](const AssetBrowserEntry* entry)
+            {
+                if (!m_ui->m_assetBrowserTreeViewWidget)
+                {
+                    return;
+                }
+
+                if (!entry)
+                {
+                    return;
+                }
+
+                if (entry->GetEntryType() != AssetBrowserEntry::AssetEntryType::Folder)
+                {
+                    return;
+                }
+
+                if (!m_assetBrowserModel)
+                {
+                    return;
+                }
+
+                if (!m_filterModel.data())
+                {
+                    return;
+                }
+
+                QModelIndex indexForEntry;
+                m_assetBrowserModel->GetEntryIndex(const_cast<AssetBrowserEntry*>(entry), indexForEntry);
+
+                if (!indexForEntry.isValid())
+                {
+                    return;
+                }
+
+                auto selectionModel = m_ui->m_assetBrowserTreeViewWidget->selectionModel();
+                auto targetIndex = m_filterModel.data()->mapFromSource(indexForEntry);
+
+                selectionModel->select(targetIndex, QItemSelectionModel::ClearAndSelect);
+
+                auto targetIndexAncestor = targetIndex.parent();
+                while (targetIndexAncestor.isValid())
+                {
+                    m_ui->m_assetBrowserTreeViewWidget->expand(targetIndexAncestor);
+                    targetIndexAncestor = targetIndexAncestor.parent();
+                }
+
+                m_ui->m_assetBrowserTreeViewWidget->scrollTo(targetIndex);
+            });
+
+        connect(
+            m_ui->m_thumbnailView,
+            &AssetBrowserThumbnailView::showInFolderTriggered,
+            this,
+            [this](const AssetBrowserEntry* entry)
+            {
+                if (!entry)
+                {
+                    return;
+                }
+
+                if (!entry->GetParent())
+                {
+                    return;
+                }
+
+                m_ui->m_searchWidget->ClearStringFilter();
+
+                QModelIndex indexForEntry;
+                m_assetBrowserModel->GetEntryIndex(const_cast<AssetBrowserEntry*>(entry->GetParent()), indexForEntry);
+
+                if (!indexForEntry.isValid())
+                {
+                    return;
+                }
+
+                auto selectionModel = m_ui->m_assetBrowserTreeViewWidget->selectionModel();
+                auto targetIndex = m_filterModel.data()->mapFromSource(indexForEntry);
+
+                selectionModel->select(targetIndex, QItemSelectionModel::ClearAndSelect);
+            });
+    }
 
     if (!ed_useWIPAssetBrowserDesign)
     {
@@ -228,6 +316,15 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent)
             }
         });
 
+    connect(
+        m_ui->m_assetBrowserTreeViewWidget,
+        &QAbstractItemView::clicked,
+        this,
+        [this](const QModelIndex&)
+        {
+            m_ui->m_searchWidget->ClearStringFilter();
+        });
+
     connect(m_ui->m_assetBrowserTreeViewWidget, &QAbstractItemView::doubleClicked, this, &AzAssetBrowserWindow::DoubleClickedItem);
 
     connect(m_ui->m_assetBrowserTreeViewWidget, &AzAssetBrowser::AssetBrowserTreeView::ClearStringFilter,
@@ -316,6 +413,9 @@ void AzAssetBrowserWindow::RegisterViewClass()
     options.showInMenu = false;
     const QString name = QString("%1 (2)").arg(LyViewPane::AssetBrowser);
     AzToolsFramework::RegisterViewPane<AzAssetBrowserWindow>(qPrintable(name), LyViewPane::CategoryTools, options);
+
+    options.preferedDockingArea = Qt::RightDockWidgetArea;
+    AzToolsFramework::RegisterViewPane<AzToolsFramework::AssetBrowser::AssetBrowserEntityInspectorWidget>(LyViewPane::AssetBrowserInspector, LyViewPane::CategoryTools, options);
 }
 
 QObject* AzAssetBrowserWindow::createListenerForShowAssetEditorEvent(QObject* parent)
@@ -338,10 +438,9 @@ void AzAssetBrowserWindow::resizeEvent(QResizeEvent* resizeEvent)
     // but the resizeEvent holds the new size of the whole widget
     // So we have to save the proportions somehow
     const QWidget* leftLayout = m_ui->m_leftLayout;
-    const QVBoxLayout* rightLayout = m_ui->m_rightLayout;
 
     const float oldLeftLayoutWidth = aznumeric_cast<float>(leftLayout->geometry().width());
-    const float oldWidth = aznumeric_cast<float>(leftLayout->geometry().width() + rightLayout->geometry().width());
+    const float oldWidth = aznumeric_cast<float>(leftLayout->geometry().width());
 
     const float newWidth = oldLeftLayoutWidth * aznumeric_cast<float>(resizeEvent->size().width()) / oldWidth;
 
@@ -489,17 +588,23 @@ void AzAssetBrowserWindow::UpdateWidgetAfterFilter()
         m_ui->m_assetBrowserTableViewWidget->setVisible(hasFilter);
         m_ui->m_assetBrowserTreeViewWidget->setVisible(!hasFilter);
     }
-}
 
-void AzAssetBrowserWindow::UpdatePreview(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* selectedEntry) const
-{
-    if (selectedEntry)
+    if (hasFilter)
     {
-        m_ui->m_previewerFrame->Display(selectedEntry);
+        m_ui->m_assetBrowserTreeViewWidget->selectionModel()->select(
+            m_ui->m_assetBrowserTreeViewWidget->model()->index(0, 0, {}), QItemSelectionModel::ClearAndSelect);
     }
-    else
+
+    if (ed_useNewAssetBrowserTableView)
     {
-        m_ui->m_previewerFrame->Clear();
+        if (hasFilter)
+        {
+            auto thumbnailWidget = m_ui->m_thumbnailView->GetThumbnailViewWidget();
+            if (thumbnailWidget)
+            {
+                thumbnailWidget->setRootIndex(thumbnailWidget->model()->index(0, 0, {}));
+            }
+        }
     }
 }
 
@@ -587,8 +692,8 @@ void AzAssetBrowserWindow::CurrentIndexChangedSlot(const QModelIndex& idx) const
     using namespace AzToolsFramework::AssetBrowser;
     auto* entry = idx.data(AssetBrowserModel::Roles::EntryRole).value<const AssetBrowserEntry*>();
 
-    UpdatePreview(entry);
     UpdateBreadcrumbs(entry);
+    AssetBrowserPreviewRequestBus::Broadcast(&AssetBrowserPreviewRequest::PreviewAsset, entry);
 }
 
 // while its tempting to use Activated here, we don't actually want it to count as activation

+ 0 - 3
Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.h

@@ -89,9 +89,6 @@ private:
     AzToolsFramework::AssetBrowser::AssetBrowserDisplayState m_assetBrowserDisplayState =
         AzToolsFramework::AssetBrowser::AssetBrowserDisplayState::ListViewMode;
 
-    //! Updates the asset preview panel with data about the passed entry.
-    //! Clears the panel if nullptr is passed
-    void UpdatePreview(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* selectedEntry) const;
 
     //! Updates breadcrumbs with the selectedEntry relative path if it's a folder or with the
     //! relative path of the first folder parent of the passed entry.

+ 1 - 26
Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui

@@ -402,20 +402,6 @@
            </layout>
           </widget>
          </widget>
-         <widget class="QWidget" name="previewWidgetWrapper">
-          <layout class="QVBoxLayout" name="m_rightLayout">
-           <item>
-            <widget class="AzToolsFramework::AssetBrowser::PreviewerFrame" name="m_previewerFrame">
-             <property name="frameShape">
-              <enum>QFrame::StyledPanel</enum>
-             </property>
-             <property name="frameShadow">
-              <enum>QFrame::Raised</enum>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </widget>
         </widget>
        </item>
       </layout>
@@ -431,25 +417,14 @@
    <header>AzToolsFramework/AssetBrowser/Search/SearchWidget.h</header>
    <container>1</container>
   </customwidget>
-  <customwidget>
-   <class>AzQtComponents::TableView</class>
-   <extends>QTreeView</extends>
-   <header>AzQtComponents/Components/Widgets/TableView.h</header>
-  </customwidget>
   <customwidget>
    <class>AzToolsFramework::AssetBrowser::AssetBrowserTreeView</class>
    <extends>QTreeView</extends>
    <header>AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h</header>
   </customwidget>
-  <customwidget>
-   <class>AzToolsFramework::AssetBrowser::PreviewerFrame</class>
-   <extends>QFrame</extends>
-   <header>AzToolsFramework/AssetBrowser/Previewer/PreviewerFrame.h</header>
-   <container>1</container>
-  </customwidget>
   <customwidget>
    <class>AzToolsFramework::AssetBrowser::AssetBrowserTableView</class>
-   <extends>AzQtComponents::TableView</extends>
+   <extends>QTableView</extends>
    <header>AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h</header>
   </customwidget>
   <customwidget>

+ 2 - 2
Code/Editor/CMakeLists.txt

@@ -128,8 +128,8 @@ ly_add_source_properties(
     SOURCES CryEdit.cpp
     PROPERTY COMPILE_DEFINITIONS 
     VALUES 
-        O3DE_COPYRIGHT_YEAR=${LY_VERSION_COPYRIGHT_YEAR}
-        LY_VERSION_BUILD_NUMBER=${LY_VERSION_BUILD_NUMBER}
+        O3DE_COPYRIGHT_YEAR=${O3DE_COPYRIGHT_YEAR}
+        O3DE_BUILD_VERSION=${O3DE_BUILD_VERSION}
         ${LY_PAL_TOOLS_DEFINES}
 )
 ly_add_source_properties(

+ 13 - 6
Code/Editor/Controls/FolderTreeCtrl.cpp

@@ -374,15 +374,22 @@ void CFolderTreeCtrl::Edit(const QString& path)
 
 void CFolderTreeCtrl::ShowInExplorer(const QString& path)
 {
-    QString absolutePath = QDir::currentPath();
-
-    CTreeItem* item = GetItem(path);
-    if (item != m_rootTreeItem)
+    if (QFileInfo(path).isAbsolute())
     {
-        absolutePath += QStringLiteral("/%1").arg(path);
+        AzQtComponents::ShowFileOnDesktop(path);
     }
+    else
+    {
+        QString absolutePath = QDir::currentPath();
+
+        CTreeItem* item = GetItem(path);
+        if (item != m_rootTreeItem)
+        {
+            absolutePath += QStringLiteral("/%1").arg(path);
+        }
 
-    AzQtComponents::ShowFileOnDesktop(absolutePath);
+        AzQtComponents::ShowFileOnDesktop(absolutePath);
+    }
 }
 
 QIcon CFolderTreeCtrl::GetItemIcon(IconType image) const

+ 2 - 14
Code/Editor/CryEdit.cpp

@@ -92,7 +92,6 @@ AZ_POP_DISABLE_WARNING
 #include "MainWindow.h"
 
 #include "Core/QtEditorApplication.h"
-#include "StringDlg.h"
 #include "NewLevelDialog.h"
 #include "LayoutConfigDialog.h"
 #include "ViewManager.h"
@@ -853,12 +852,12 @@ namespace
 
 QString FormatVersion([[maybe_unused]] const SFileVersion& v)
 {
-    if (QObject::tr("%1").arg(LY_VERSION_BUILD_NUMBER) == "0")
+    if (QObject::tr("%1").arg(O3DE_BUILD_VERSION) == "0")
     {
         return QObject::tr("Development Build");
     }
 
-    return QObject::tr("Version %1").arg(LY_VERSION_BUILD_NUMBER);
+    return QObject::tr("Version %1").arg(O3DE_BUILD_VERSION);
 }
 
 QString FormatRichTextCopyrightNotice()
@@ -2540,17 +2539,6 @@ void CCryEditApp::OnFileExportToGameNoSurfaceTexture()
     UserExportToGame(false);
 }
 
-//////////////////////////////////////////////////////////////////////////
-void CCryEditApp::DeleteSelectedEntities([[maybe_unused]] bool includeDescendants)
-{
-    GetIEditor()->BeginUndo();
-    CUndo undo("Delete Selected Object");
-    GetIEditor()->GetObjectManager()->DeleteSelection();
-    GetIEditor()->AcceptUndo("Delete Selection");
-    GetIEditor()->SetModifiedFlag();
-    GetIEditor()->SetModifiedModule(eModifiedBrushes);
-}
-
 void CCryEditApp::OnMoveObject()
 {
     ////////////////////////////////////////////////////////////////////////

+ 0 - 1
Code/Editor/CryEdit.h

@@ -203,7 +203,6 @@ public:
     void OnViewSwitchToGame();
     void OnViewSwitchToGameFullScreen();
     void OnViewDeploy();
-    void DeleteSelectedEntities(bool includeDescendants);
     void OnMoveObject();
     void OnRenameObj();
     void OnUndo();

+ 0 - 17
Code/Editor/Lib/Tests/test_Main.cpp

@@ -17,23 +17,6 @@
 class EditorLibTestEnvironment
     : public ::UnitTest::TraceBusHook
 {
-public:
-    ~EditorLibTestEnvironment() override = default;
-
-protected:
-    void SetupEnvironment() override
-    {
-        ::UnitTest::TraceBusHook::SetupEnvironment();
-
-        AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
-    }
-
-    void TeardownEnvironment() override
-    {
-        AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
-
-        ::UnitTest::TraceBusHook::TeardownEnvironment();
-    }
 };
 
 AZTEST_EXPORT int AZ_UNIT_TEST_HOOK_NAME(int argc, char** argv)

+ 1 - 0
Code/Editor/LyViewPaneNames.h

@@ -22,6 +22,7 @@ namespace LyViewPane
     static const char* const SceneSettings = "Scene Settings (PREVIEW)";
     static const char* const AssetBrowser = "Asset Browser";
     static const char* const AssetEditor = "Asset Editor";
+    static const char* const AssetBrowserInspector = "Asset Browser Inspector";
     static const char* const EntityOutliner = "Entity Outliner";
     static const char* const EntityInspector = "Entity Inspector";
     static const char* const EntityInspectorPinned = "Pinned Entity Inspector";

+ 0 - 1
Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp

@@ -78,7 +78,6 @@
 #include <Editor/DisplaySettings.h>
 #include <Editor/IconManager.h>
 #include <Editor/Settings.h>
-#include <Editor/StringDlg.h>
 #include <Editor/QtViewPaneManager.h>
 #include <Editor/EditorViewportSettings.h>
 #include <Editor/EditorViewportCamera.h>

+ 0 - 2
Code/Editor/Plugins/ComponentEntityEditorPlugin/Tests/test_Main.cpp

@@ -18,12 +18,10 @@ class ToolsFrameworkHook
 public:
     void SetupEnvironment() override
     {
-        AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
     }
 
     void TeardownEnvironment() override
     {
-        AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
     }
 };
 

+ 6 - 9
Code/Editor/PythonEditorFuncs.cpp

@@ -12,6 +12,7 @@
 #include "PythonEditorFuncs.h"
 
 // Qt
+#include <QInputDialog>
 #include <QMessageBox>
 #include <QFileDialog>
 
@@ -26,7 +27,6 @@
 #include "CryEdit.h"
 #include "GameEngine.h"
 #include "ViewManager.h"
-#include "StringDlg.h"
 #include "GenericSelectItemDialog.h"
 #include "Objects/BaseObject.h"
 #include "Commands/CommandManager.h"
@@ -336,22 +336,19 @@ namespace
 
     AZStd::string PyEditBox(AZStd::string_view pTitle)
     {
-        StringDlg stringDialog(pTitle.data());
-        if (stringDialog.exec() == QDialog::Accepted)
+        QString stringValue = QInputDialog::getText(AzToolsFramework::GetActiveWindow(), pTitle.data(), QString());
+        if (!stringValue.isEmpty())
         {
-            return stringDialog.GetString().toUtf8().constData();
+            return stringValue.toUtf8().constData();
         }
         return "";
     }
 
     AZStd::any PyEditBoxAndCheckProperty(const char* pTitle)
     {
-        StringDlg stringDialog(pTitle);
-        stringDialog.SetString(QStringLiteral(""));
-        if (stringDialog.exec() == QDialog::Accepted)
+        QString stringValue = QInputDialog::getText(AzToolsFramework::GetActiveWindow(), pTitle, QString());
+        if (!stringValue.isEmpty())
         {
-            const QString stringValue = stringDialog.GetString();
-
             // detect data type
             QString tempString = stringValue;
             int countComa = 0;

+ 0 - 3
Code/Editor/main.cpp

@@ -20,8 +20,6 @@ int main(int argc, char* argv[])
     using CryEditMain = int (*)(int, char*[]);
     constexpr const char CryEditMainName[] = "CryEditMain";
 
-    AZ::AllocatorInstance<AZ::OSAllocator>::Create();
-
     auto handle = AZ::DynamicModuleHandle::Create("EditorLib");
     [[maybe_unused]] const bool loaded = handle->Load(true);
     AZ_Assert(loaded, "EditorLib could not be loaded");
@@ -33,6 +31,5 @@ int main(int argc, char* argv[])
     }
 
     handle = {};
-    AZ::AllocatorInstance<AZ::OSAllocator>::Destroy();
     return ret;
 }

+ 0 - 4
Code/Framework/AtomCore/Tests/InstanceDatabase.cpp

@@ -123,8 +123,6 @@ namespace UnitTest
         void SetUp() override
         {
             LeakDetectionFixture::SetUp();
-            AllocatorInstance<PoolAllocator>::Create();
-            AllocatorInstance<ThreadPoolAllocator>::Create();
 
             // create the asset database
             {
@@ -155,8 +153,6 @@ namespace UnitTest
 
             InstanceDatabase<TestInstanceA>::Destroy();
 
-            AllocatorInstance<ThreadPoolAllocator>::Destroy();
-            AllocatorInstance<PoolAllocator>::Destroy();
             LeakDetectionFixture::TearDown();
         }
     };

+ 0 - 4
Code/Framework/AtomCore/Tests/Main.cpp

@@ -44,16 +44,12 @@ class TestEnvironmentHook
 public:
     void SetupEnvironment() override
     {
-        AllocatorInstance<OSAllocator>::Create(); // used by the bus
-
         BusConnect();
     }
 
     void TeardownEnvironment() override
     {
         BusDisconnect();
-
-        AllocatorInstance<OSAllocator>::Destroy(); // used by the bus
     }
 };
 

+ 0 - 2
Code/Framework/AzCore/AzCore/AzCoreModule.cpp

@@ -13,7 +13,6 @@
 #include <AzCore/IO/Streamer/StreamerComponent.h>
 #include <AzCore/Jobs/JobManagerComponent.h>
 #include <AzCore/Serialization/Json/JsonSystemComponent.h>
-#include <AzCore/Memory/MemoryComponent.h>
 #include <AzCore/Script/ScriptSystemComponent.h>
 #include <AzCore/Slice/SliceComponent.h>
 #include <AzCore/Slice/SliceSystemComponent.h>
@@ -30,7 +29,6 @@ namespace AZ
         : AZ::Module()
     {
         m_descriptors.insert(m_descriptors.end(), {
-            MemoryComponent::CreateDescriptor(),
             StreamerComponent::CreateDescriptor(),
             JobManagerComponent::CreateDescriptor(),
             JsonSystemComponent::CreateDescriptor(),

+ 13 - 69
Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp

@@ -415,8 +415,8 @@ namespace AZ
         m_descriptor.m_recordingMode = AllocatorManager::Instance().GetDefaultTrackingMode();
 
         // Initializes the OSAllocator and SystemAllocator as soon as possible
-        CreateOSAllocator();
-        CreateSystemAllocator();
+        AZ::Debug::Trace::Instance().Init();
+        ConfigureSystemAllocatorTracking();
 
         // Now that the Allocators are initialized, the Command Line parameters can be parsed
         m_commandLine.Parse(m_argC, m_argV);
@@ -515,7 +515,7 @@ namespace AZ
         m_entityActivatedEvent.DisconnectAllHandlers();
         m_entityDeactivatedEvent.DisconnectAllHandlers();
 
-        DestroyAllocator();
+        AZ::Debug::Trace::Instance().Destroy();
     }
 
     void ComponentApplication::InitializeSettingsRegistry()
@@ -741,10 +741,7 @@ namespace AZ
 
         m_descriptor = descriptor;
 
-        // Re-invokes CreateOSAllocator and CreateSystemAllocator function to allow the component application
-        // to use supplied startupParameters and descriptor parameters this time
-        CreateOSAllocator();
-        CreateSystemAllocator();
+        ConfigureSystemAllocatorTracking();
 
 #if !defined(_RELEASE)
         m_budgetTracker.Init();
@@ -911,73 +908,20 @@ namespace AZ
 #endif // defined(AZ_ENABLE_DEBUG_TOOLS)
     }
 
-    void ComponentApplication::DestroyAllocator()
-    {
-        AZ::Debug::Trace::Instance().Destroy();
-
-        // kill the system allocator if we created it
-        if (m_isSystemAllocatorOwner)
-        {
-            AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
-
-            m_isSystemAllocatorOwner = false;
-        }
-
-        if (m_isOSAllocatorOwner)
-        {
-            AZ::AllocatorInstance<AZ::OSAllocator>::Destroy();
-            m_isOSAllocatorOwner = false;
-        }
-
-        m_osAllocator = nullptr;
-    }
-
-    void ComponentApplication::CreateOSAllocator()
-    {
-        if (!m_startupParameters.m_allocator)
-        {
-            if (!AZ::AllocatorInstance<AZ::OSAllocator>::IsReady())
-            {
-                AZ::AllocatorInstance<AZ::OSAllocator>::Create();
-                m_isOSAllocatorOwner = true;
-            }
-            m_osAllocator = &AZ::AllocatorInstance<AZ::OSAllocator>::Get();
-        }
-        else
-        {
-            m_osAllocator = m_startupParameters.m_allocator;
-        }
-    }
-
     //=========================================================================
-    // CreateSystemAllocator
+    // ConfigureSystemAllocatorTracking
     // [5/30/2012]
     //=========================================================================
-    void ComponentApplication::CreateSystemAllocator()
+    void ComponentApplication::ConfigureSystemAllocatorTracking()
     {
-        AZ::Debug::Trace::Instance().Init();
-
-        if (m_descriptor.m_useExistingAllocator || AZ::AllocatorInstance<AZ::SystemAllocator>::IsReady())
+        AZ::Debug::AllocationRecords* records = AllocatorInstance<SystemAllocator>::Get().GetRecords();
+        if (records)
         {
-            AZ_Assert(AZ::AllocatorInstance<AZ::SystemAllocator>::IsReady(), "You must setup AZ::SystemAllocator instance, before you can call Create application with m_useExistingAllocator flag set to true");
-            return;
-        }
-        else
-        {
-            // Create the system allocator
-            AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
-
-            AZ::Debug::AllocationRecords* records = AllocatorInstance<SystemAllocator>::Get().GetRecords();
-            if (records)
-            {
-                records->SetMode(m_descriptor.m_recordingMode);
-                records->SetSaveNames(m_descriptor.m_allocationRecordsSaveNames);
-                records->SetDecodeImmediately(m_descriptor.m_allocationRecordsAttemptDecodeImmediately);
-                records->AutoIntegrityCheck(m_descriptor.m_autoIntegrityCheck);
-                records->MarkUallocatedMemory(m_descriptor.m_markUnallocatedMemory);
-            }
-
-            m_isSystemAllocatorOwner = true;
+            records->SetMode(m_descriptor.m_recordingMode);
+            records->SetSaveNames(m_descriptor.m_allocationRecordsSaveNames);
+            records->SetDecodeImmediately(m_descriptor.m_allocationRecordsAttemptDecodeImmediately);
+            records->AutoIntegrityCheck(m_descriptor.m_autoIntegrityCheck);
+            records->MarkUallocatedMemory(m_descriptor.m_markUnallocatedMemory);
         }
     }
 

+ 2 - 12
Code/Framework/AzCore/AzCore/Component/ComponentApplication.h

@@ -149,10 +149,6 @@ namespace AZ
         {
             StartupParameters() {}
 
-            //! If set, this allocator is used to allocate the temporary bootstrap memory, as well as the main \ref SystemAllocator heap.
-            //! If it's left nullptr (default), the \ref OSAllocator will be used.
-            IAllocator* m_allocator = nullptr;
-
             //! Callback to create AZ::Modules for the static libraries linked by this application.
             //! Leave null if the application uses no static AZ::Modules.
             //! \note Dynamic AZ::Modules are specified in the ComponentApplication::Descriptor.
@@ -187,7 +183,6 @@ namespace AZ
          */
         virtual Entity* Create(const Descriptor& descriptor, const StartupParameters& startupParameters = StartupParameters());
         virtual void Destroy();
-        virtual void DestroyAllocator(); // Called at the end of Destroy(). Applications can override to do tear down work right before allocator is destroyed.
 
         //////////////////////////////////////////////////////////////////////////
         // ComponentApplicationRequests
@@ -313,11 +308,8 @@ namespace AZ
         /// Common logic shared between the multiple Create(...) functions.
         void        CreateCommon();
 
-        /// Create the operating system allocator if not supplied in the StartupParameters
-        void        CreateOSAllocator();
-
-        /// Create the system allocator using the data in the m_descriptor
-        void        CreateSystemAllocator();
+        /// Create the system allocator to track allocations
+        void        ConfigureSystemAllocatorTracking();
 
         virtual void MergeSettingsToRegistry(SettingsRegistryInterface& registry);
 
@@ -369,8 +361,6 @@ namespace AZ
         EntityRemovedEvent                          m_entityDeactivatedEvent;
         Descriptor                                  m_descriptor;
         bool                                        m_isStarted{ false };
-        bool                                        m_isSystemAllocatorOwner{ false };
-        bool                                        m_isOSAllocatorOwner{ false };
         IAllocator*                                 m_osAllocator{ nullptr };
         EntitySetType                               m_entities;
 

+ 9 - 6
Code/Framework/AzCore/AzCore/Component/ComponentApplicationLifecycle.cpp

@@ -33,10 +33,11 @@ namespace AZ::ComponentApplicationLifecycle
                 " or in *.setreg within the project", AZ_STRING_ARG(eventName), AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey));
             return false;
         }
-        auto eventRegistrationKey = FixedValueString::format("%.*s/%.*s", AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey),
+        // The Settings Registry key used to signal the event is a transient runtime key which is separate from the registration key
+        auto eventSignalKey = FixedValueString::format("%.*s/%.*s", AZ_STRING_ARG(ApplicationLifecycleEventSignalKey),
             AZ_STRING_ARG(eventName));
 
-        return settingsRegistry.MergeSettings(eventValue, Format::JsonMergePatch, eventRegistrationKey);
+        return settingsRegistry.MergeSettings(eventValue, Format::JsonMergePatch, eventSignalKey);
     }
 
     bool RegisterEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName)
@@ -74,12 +75,14 @@ namespace AZ::ComponentApplicationLifecycle
                 " or in *.setreg within the project", AZ_STRING_ARG(eventName), AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey));
             return false;
         }
-        auto eventNameRegistrationKey = FixedValueString::format("%.*s/%.*s", AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey),
-            AZ_STRING_ARG(eventName));
-        auto lifecycleCallback = [callback = AZStd::move(callback), eventNameRegistrationKey](
+
+        // The signal key is used for invoking the handler
+        auto lifecycleCallback = [callback = AZStd::move(callback),
+            eventNameSignalKey = FixedValueString::format("%.*s/%.*s",
+                AZ_STRING_ARG(ApplicationLifecycleEventSignalKey), AZ_STRING_ARG(eventName))](
             const AZ::SettingsRegistryInterface::NotifyEventArgs& notifyEventArgs)
         {
-            if (notifyEventArgs.m_jsonKeyPath == eventNameRegistrationKey)
+            if (notifyEventArgs.m_jsonKeyPath == eventNameSignalKey)
             {
                 callback(notifyEventArgs);
             }

+ 7 - 1
Code/Framework/AzCore/AzCore/Component/ComponentApplicationLifecycle.h

@@ -13,9 +13,15 @@
 
 namespace AZ::ComponentApplicationLifecycle
 {
-    //! Root Key where lifecycle events should be registered under
+    //! Root Key used to determine where lifecycle events are registered underneath
     inline constexpr AZStd::string_view ApplicationLifecycleEventRegistrationKey = "/O3DE/Application/LifecycleEvents";
 
+    //! Root Key to use for signaling lifecycle events
+    //! This key section is runtime only and will not be merged into the aggregated setreg file
+    //! produced by the SettingsRegistryBuilder
+    //! It is used to separately from the registration key section, to avoid the scenario
+    //! where registering a lifecycle event would result in signaling the event.
+    inline constexpr AZStd::string_view ApplicationLifecycleEventSignalKey = "/O3DE/Runtime/Application/LifecycleEvents";
 
     //! Validates that the event @eventName is stored in the array at ApplicationLifecycleEventRegistrationKey
     //! @param settingsRegistry registry where @eventName will be searched

+ 9 - 3
Code/Framework/AzCore/AzCore/Debug/PerformanceCollector.cpp

@@ -18,8 +18,14 @@
 
 namespace AZ::Debug
 {
-    PerformanceCollector::PerformanceCollector(const AZStd::string_view logCategory, AZStd::span<const AZStd::string_view> m_metricNames, OnBatchCompleteCallback onBatchCompleteCallback)
-        : m_logCategory(logCategory), m_onBatchCompleteCallback(onBatchCompleteCallback)
+    PerformanceCollector::PerformanceCollector(
+        const AZStd::string_view logCategory,
+        AZStd::span<const AZStd::string_view> m_metricNames,
+        OnBatchCompleteCallback onBatchCompleteCallback,
+        const AZStd::string_view fileExtension)
+        : m_logCategory(logCategory)
+        , m_onBatchCompleteCallback(onBatchCompleteCallback)
+        , m_fileExtension(fileExtension)
     {
         for (const auto& metricName : m_metricNames)
         {
@@ -244,7 +250,7 @@ namespace AZ::Debug
             settingsRegistry->Get(m_outputFilePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath);
             AZ::Date::Iso8601TimestampString utcTimestamp;
             AZ::Date::GetFilenameCompatibleFormatNowWithMicroseconds(utcTimestamp);
-            m_outputFilePath /= AZStd::string::format("Performance_%s_%s.json", m_logCategory.c_str(), utcTimestamp.c_str());
+            m_outputFilePath /= AZStd::string::format("Performance_%s_%s.%s", m_logCategory.c_str(), utcTimestamp.c_str(), m_fileExtension.c_str());
 
             constexpr AZ::IO::OpenMode openMode = AZ::IO::OpenMode::ModeWrite;
             auto stream = AZStd::make_unique<AZ::IO::SystemFileStream>(m_outputFilePath.c_str(), openMode);

+ 11 - 3
Code/Framework/AzCore/AzCore/Debug/PerformanceCollector.h

@@ -44,7 +44,12 @@ namespace AZ::Debug
         //!                    Each output file will be named Performance_<Category>_<CreationTime>.json
         //! @param m_metricNames List of all the metrics that will be recorded. All metrics will be measured in Microseconds.
         //! @param onBatchCompleteCallback See comments above in OnBatchCompleteCallback declaration.
-        PerformanceCollector(const AZStd::string_view logCategory, AZStd::span<const AZStd::string_view> m_metricNames, OnBatchCompleteCallback onBatchCompleteCallback);
+        //! @param m_fileExtension The extension of the output file, to appear after "." Defaults to "json".
+        PerformanceCollector(
+            const AZStd::string_view logCategory,
+            AZStd::span<const AZStd::string_view> m_metricNames,
+            OnBatchCompleteCallback onBatchCompleteCallback,
+            const AZStd::string_view fileExtension = "json");
         ~PerformanceCollector() = default;
 
         static constexpr char LogName[] = "PerformanceCollector";
@@ -94,9 +99,11 @@ namespace AZ::Debug
         //! and performance capture for as many batches.
         void UpdateNumberOfCaptureBatches(AZ::u32 newValue);
 
-        const AZ::IO::Path& GetOutputFilePath() { return m_outputFilePath;  }
+        const AZ::IO::Path& GetOutputFilePath() const { return m_outputFilePath;  }
 
-        const AZStd::string& GetOutputDataBuffer() { return m_outputDataBuffer; }
+        const AZStd::string& GetOutputDataBuffer() const { return m_outputDataBuffer; }
+
+        const AZStd::string& GetFileExtension() const { return m_fileExtension; }
 
     private:
         //! A helper function that loops across all statistics in @m_statisticsManager
@@ -118,6 +125,7 @@ namespace AZ::Debug
         AZStd::chrono::steady_clock::time_point m_startWaitTime;
         bool m_isWaitingBeforeNextBatch = true;
         OnBatchCompleteCallback m_onBatchCompleteCallback; // A notification will be sent each time a batch of frames is performance collected.
+        AZStd::string m_fileExtension = "json";
 
         //! Only used when @m_captureType == CaptureType::LogStatistics.
         AZ::Statistics::StatisticsManager<AZStd::string> m_statisticsManager;

+ 0 - 1
Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp

@@ -115,7 +115,6 @@ namespace AZ
     //=========================================================================
     void JobManagerComponent::GetDependentServices(ComponentDescriptor::DependencyArrayType& dependent)
     {
-        dependent.push_back(AZ_CRC("MemoryService", 0x5c4d473c));
         dependent.push_back(AZ_CRC("ProfilerService", 0x505033c9));
     }
 

+ 4 - 5
Code/Framework/AzCore/AzCore/Memory/AllocationRecords.cpp

@@ -369,21 +369,20 @@ namespace AZ::Debug
             return;
         }
 
-        Debug::AllocationInfo* ai{};
-        const bool addressAlreadyRecorded = [this, address, newAddress, &ai]
+        const auto [addressAlreadyRecorded, ai] = [this, address, newAddress]() -> std::pair<bool, Debug::AllocationInfo*>
         {
             AZStd::scoped_lock lock(m_recordsMutex);
             auto node = m_records.extract(address);
             if (node.empty())
             {
-                return false;
+                return {false, nullptr};
             }
 
             // Make a best effort to avoid reallocations from mutating the
             // records map when recording a reallocation
             node.key() = newAddress;
-            ai = &m_records.insert(AZStd::move(node)).position->second;
-            return true;
+            auto ai = &m_records.insert(AZStd::move(node)).position->second;
+            return {true, ai};
         }();
         if (!addressAlreadyRecorded)
         {

+ 2 - 1
Code/Framework/AzCore/AzCore/Memory/AllocatorBase.h

@@ -31,7 +31,8 @@ namespace AZ
         //---------------------------------------------------------------------
         // IAllocator implementation
         //---------------------------------------------------------------------
-        const Debug::AllocationRecords* GetRecords() const final;
+        using IAllocator::GetRecords;
+        const Debug::AllocationRecords* GetRecords() const override;
         void SetRecords(Debug::AllocationRecords* records) final;
         bool IsReady() const final;
         void PostCreate() override;

+ 0 - 37
Code/Framework/AzCore/AzCore/Memory/AllocatorInstance.h

@@ -49,20 +49,6 @@ namespace AZ::AllocatorStorage
             static AllocatorEnvironmentVariable s_allocator;
             return *s_allocator;
         }
-
-        static void Create()
-        {
-            GetAllocator();
-        }
-
-        static void Destroy()
-        {
-        }
-
-        AZ_FORCE_INLINE static bool IsReady()
-        {
-            return true;
-        }
     };
 } // namespace AZ::AllocatorStorage
 
@@ -75,33 +61,10 @@ namespace AZ::Internal
     class AllocatorInstanceBase
     {
     public:
-        // Maintained for backwards compatibility, prefer to use Get() instead.
-        // Get was previously used to get the the schema, however, that bypasses what the allocators are doing.
-        // If the schema is needed, call Get().GetSchema()
-        AZ_FORCE_INLINE static IAllocator& GetAllocator()
-        {
-            return StoragePolicy::GetAllocator();
-        }
-
         AZ_FORCE_INLINE static IAllocator& Get()
         {
             return StoragePolicy::GetAllocator();
         }
-
-        static void Create()
-        {
-            StoragePolicy::Create();
-        }
-
-        static void Destroy()
-        {
-            StoragePolicy::Destroy();
-        }
-
-        AZ_FORCE_INLINE static bool IsReady()
-        {
-            return StoragePolicy::IsReady();
-        }
     };
 } // namespace AZ::Internal
 

+ 0 - 131
Code/Framework/AzCore/AzCore/Memory/MemoryComponent.cpp

@@ -1,131 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#include <AzCore/Memory/MemoryComponent.h>
-#include <AzCore/Math/Crc.h>
-
-#include <AzCore/Memory/PoolAllocator.h>
-
-#include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/Serialization/EditContext.h>
-
-namespace AZ
-{
-    //=========================================================================
-    // MemoryComponent
-    // [5/29/2012]
-    //=========================================================================
-    MemoryComponent::MemoryComponent()
-    {
-        m_isPoolAllocator = true;
-        m_isThreadPoolAllocator = true;
-
-        m_createdPoolAllocator = false;
-        m_createdThreadPoolAllocator = false;
-    }
-
-    //=========================================================================
-    // ~MemoryComponent
-    // [5/29/2012]
-    //=========================================================================
-    MemoryComponent::~MemoryComponent()
-    {
-        // Normally we will just call destroy destroy in the deactivate function
-        // and create in activate. But memory component is special that
-        // it must be operational after Init so all parts of the engine can be operational.
-        // This is why we must check the destructor (which is symmetrical to Init() anyway)
-        if (m_createdThreadPoolAllocator && AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::IsReady())
-        {
-            AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Destroy();
-        }
-        if (m_createdPoolAllocator && AZ::AllocatorInstance<AZ::PoolAllocator>::IsReady())
-        {
-            AZ::AllocatorInstance<AZ::PoolAllocator>::Destroy();
-        }
-    }
-
-    //=========================================================================
-    // Init
-    // [5/29/2012]
-    //=========================================================================
-    void MemoryComponent::Init()
-    {
-        // IMPORTANT: The SystemAllocator is already operational
-
-        // TODO: add the setting to the serialization layer
-        if (m_isPoolAllocator)
-        {
-            AZ::AllocatorInstance<AZ::PoolAllocator>::Create();
-            m_createdPoolAllocator = true;
-        }
-        if (m_isThreadPoolAllocator)
-        {
-            AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Create();
-            m_createdThreadPoolAllocator = true;
-        }
-    }
-
-    //=========================================================================
-    // Activate
-    // [5/29/2012]
-    //=========================================================================
-    void MemoryComponent::Activate()
-    {
-    }
-
-    //=========================================================================
-    // Deactivate
-    // [5/29/2012]
-    //=========================================================================
-    void MemoryComponent::Deactivate()
-    {
-    }
-
-    //=========================================================================
-    // GetProvidedServices
-    //=========================================================================
-    void MemoryComponent::GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided)
-    {
-        provided.push_back(AZ_CRC("MemoryService", 0x5c4d473c));
-    }
-
-    //=========================================================================
-    // GetIncompatibleServices
-    //=========================================================================
-    void MemoryComponent::GetIncompatibleServices(ComponentDescriptor::DependencyArrayType& incompatible)
-    {
-        incompatible.push_back(AZ_CRC("MemoryService", 0x5c4d473c));
-    }
-
-    //=========================================================================
-    // Reflect
-    //=========================================================================
-    void MemoryComponent::Reflect(ReflectContext* context)
-    {
-        if (SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context))
-        {
-            serializeContext->Class<MemoryComponent, AZ::Component>()
-                ->Version(1)
-                ->Field("isPoolAllocator", &MemoryComponent::m_isPoolAllocator)
-                ->Field("isThreadPoolAllocator", &MemoryComponent::m_isThreadPoolAllocator)
-                ;
-
-            ;
-            if (EditContext* editContext = serializeContext->GetEditContext())
-            {
-                editContext->Class<MemoryComponent>("Memory System", "Initializes and maintains fundamental memory allocators")
-                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
-                        ->Attribute(AZ::Edit::Attributes::Category, "Engine")
-                        ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
-                    ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MemoryComponent::m_isPoolAllocator, "Pool allocator", "Fast allocation pooling for small allocations < 256 bytes, use from main thread only!")
-                    ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MemoryComponent::m_isThreadPoolAllocator, "Thread pool allocator", "Fast allocation pool that can be used from any thread, if uses more memory! (as it keeps the pools per thread)")
-                    ;
-            }
-        }
-    }
-} // namespace AZ

+ 0 - 58
Code/Framework/AzCore/AzCore/Memory/MemoryComponent.h

@@ -1,58 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#ifndef AZCORE_MEMORY_COMPONENT_H
-#define AZCORE_MEMORY_COMPONENT_H
-
-#include <AzCore/Component/Component.h>
-#include <AzCore/Math/Crc.h>
-
-namespace AZ
-{
-    /**
-     * Memory manager component. It will manager all memory managers.
-     * This is the only component that requires special care as memory managers
-     * must be operational for any system to operate. In addition this component doesn't have a factory
-     * as it's managed by the bootstrap component class.
-     */
-    class MemoryComponent
-        : public Component
-    {
-    public:
-        AZ_COMPONENT(AZ::MemoryComponent, "{6F450DDA-6F4D-40fd-A93B-E5CCCDBC72AB}")
-
-        MemoryComponent();
-        virtual ~MemoryComponent();
-
-        //////////////////////////////////////////////////////////////////////////
-        // Component base
-        void Init() override;
-        void Activate() override;
-        void Deactivate() override;
-        //////////////////////////////////////////////////////////////////////////
-
-    private:
-
-        /// \ref ComponentDescriptor::GetProvidedServices
-        static void GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided);
-        /// \ref ComponentDescriptor::GetIncompatibleServices
-        static void GetIncompatibleServices(ComponentDescriptor::DependencyArrayType& incompatible);
-        /// \ref ComponentDescriptor::Reflect
-        static void Reflect(ReflectContext* reflection);
-
-        // serialized data
-        bool m_isPoolAllocator;
-        bool m_isThreadPoolAllocator;
-
-        // non-serialized data
-        bool m_createdPoolAllocator;
-        bool m_createdThreadPoolAllocator;
-    };
-}
-
-#endif // AZCORE_MEMORY_COMPONENT_H
-#pragma once

+ 5 - 9
Code/Framework/AzCore/AzCore/Serialization/SerializeContext.cpp

@@ -3169,18 +3169,14 @@ namespace AZ
         auto genericClassInfoContainer = AZStd::move(m_moduleLocalGenericClassInfos);
         auto serializeContextSet = AZStd::move(m_serializeContextSet);
         // Un-reflect GenericClassInfo from each serialize context registered with the module
-        // The SerailizeContext uses the SystemAllocator so it is required to be ready in order to remove the data
-        if (AZ::AllocatorInstance<AZ::SystemAllocator>::IsReady())
+        for (AZ::SerializeContext* serializeContext : serializeContextSet)
         {
-            for (AZ::SerializeContext* serializeContext : serializeContextSet)
+            for (const auto& [specializedTypeId, genericClassInfo] : genericClassInfoContainer)
             {
-                for (const auto& [specializedTypeId, genericClassInfo] : genericClassInfoContainer)
-                {
-                    serializeContext->RemoveGenericClassInfo(genericClassInfo);
-                }
-
-                serializeContext->m_perModuleSet.erase(this);
+                serializeContext->RemoveGenericClassInfo(genericClassInfo);
             }
+
+            serializeContext->m_perModuleSet.erase(this);
         }
 
         // Cleanup the memory for the GenericClassInfo objects.

+ 0 - 19
Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h

@@ -166,25 +166,6 @@ namespace UnitTest
     class ScopedAllocatorBenchmarkEnvironment
         : public AZ::Test::BenchmarkEnvironmentBase
     {
-    public:
-        ScopedAllocatorBenchmarkEnvironment()
-        {
-            // Only create the allocator if it doesn't exist
-            if (!AZ::AllocatorInstance<AZ::SystemAllocator>::IsReady())
-            {
-                AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
-                m_ownsAllocator = true;
-            }
-        }
-        ~ScopedAllocatorBenchmarkEnvironment() override
-        {
-            if (m_ownsAllocator)
-            {
-                AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
-            }
-        }
-    private:
-        bool m_ownsAllocator{};
     };
 #endif
 

+ 0 - 6
Code/Framework/AzCore/AzCore/UserSettings/UserSettingsComponent.cpp

@@ -86,12 +86,6 @@ namespace AZ
         provided.push_back(AZ_CRC("UserSettingsService", 0xa0eadff5));
     }
 
-    //-----------------------------------------------------------------------------
-    void UserSettingsComponent::GetDependentServices(ComponentDescriptor::DependencyArrayType& dependent)
-    {
-        dependent.push_back(AZ_CRC("MemoryService", 0x5c4d473c));
-    }
-
     //-----------------------------------------------------------------------------
 
     //-----------------------------------------------------------------------------

+ 0 - 2
Code/Framework/AzCore/AzCore/UserSettings/UserSettingsComponent.h

@@ -57,8 +57,6 @@ namespace AZ
 
         /// \ref ComponentDescriptor::GetProvidedServices
         static void GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided);
-        /// \ref ComponentDescriptor::GetDependentServices
-        static void GetDependentServices(ComponentDescriptor::DependencyArrayType& dependent);
         /// \red ComponentDescriptor::Reflect
         static void Reflect(ReflectContext* reflection);
 

+ 0 - 2
Code/Framework/AzCore/AzCore/azcore_files.cmake

@@ -412,8 +412,6 @@ set(FILES
     Memory/IAllocator.h
     Memory/Memory.cpp
     Memory/Memory.h
-    Memory/MemoryComponent.cpp
-    Memory/MemoryComponent.h
     Memory/nedmalloc.inl
     Memory/NewAndDelete.inl
     Memory/OSAllocator.cpp

+ 0 - 6
Code/Framework/AzCore/Tests/AZStd/VariantSerialization.cpp

@@ -25,9 +25,6 @@ namespace UnitTest
         {
             LeakDetectionFixture::SetUp();
 
-            AZ::AllocatorInstance<AZ::PoolAllocator>::Create();
-            AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Create();
-
             m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
             AZ::Entity::Reflect(m_serializeContext.get());
             
@@ -41,9 +38,6 @@ namespace UnitTest
 
             m_serializeContext.reset();
 
-            AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Destroy();
-            AZ::AllocatorInstance<AZ::PoolAllocator>::Destroy();
-
             LeakDetectionFixture::TearDown();
         }
 

+ 0 - 12
Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp

@@ -72,9 +72,6 @@ namespace JsonSerializationTests
         {
             BaseJsonSerializerFixture::SetUp();
 
-            AZ::AllocatorInstance<AZ::PoolAllocator>::Create();
-            AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Create();
-
             // Set up the Job Manager with 1 thread so that the Asset Manager is able to load assets.
             AZ::JobManagerDesc jobDesc;
             AZ::JobManagerThreadDesc threadDesc;
@@ -104,9 +101,6 @@ namespace JsonSerializationTests
             delete m_jobContext;
             delete m_jobManager;
 
-            AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Destroy();
-            AZ::AllocatorInstance<AZ::PoolAllocator>::Destroy();
-
             BaseJsonSerializerFixture::TearDown();
         }
 
@@ -157,9 +151,6 @@ namespace JsonSerializationTests
 
         void SetUp() override
         {
-            AZ::AllocatorInstance<AZ::PoolAllocator>::Create();
-            AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Create();
-
             // Set up the Job Manager with 1 thread so that the Asset Manager is able to load assets.
             AZ::JobManagerDesc jobDesc;
             AZ::JobManagerThreadDesc threadDesc;
@@ -181,9 +172,6 @@ namespace JsonSerializationTests
             AZ::JobContext::SetGlobalContext(nullptr);
             delete m_jobContext;
             delete m_jobManager;
-
-            AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Destroy();
-            AZ::AllocatorInstance<AZ::PoolAllocator>::Destroy();
         }
 
         using JsonSerializerConformityTestDescriptor<AZ::Data::Asset<TestAssetData>>::Reflect;

+ 3 - 14
Code/Framework/AzCore/Tests/Components.cpp

@@ -18,7 +18,6 @@
 #include <AzCore/IO/Streamer/StreamerComponent.h>
 #include <AzCore/Serialization/ObjectStream.h>
 
-#include <AzCore/Memory/MemoryComponent.h>
 #include <AzCore/UserSettings/UserSettingsComponent.h>
 #include <AzCore/IO/SystemFile.h>
 
@@ -60,7 +59,6 @@ namespace UnitTest
         appDesc.m_recordingMode = AllocationRecords::RECORD_FULL;
         Entity* systemEntity = app.Create(appDesc);
 
-        systemEntity->CreateComponent<MemoryComponent>();
         systemEntity->CreateComponent<StreamerComponent>();
         systemEntity->CreateComponent(AZ::Uuid("{CAE3A025-FAC9-4537-B39E-0A800A2326DF}")); // JobManager component
         systemEntity->CreateComponent(AZ::Uuid("{D5A73BCC-0098-4d1e-8FE4-C86101E374AC}")); // AssetDatabase component
@@ -175,9 +173,7 @@ namespace UnitTest
         ComponentApplication componentApp;
         ComponentApplication::Descriptor desc;
         desc.m_useExistingAllocator = true;
-        ComponentApplication::StartupParameters startupParams;
-        startupParams.m_allocator = &AZ::AllocatorInstance<AZ::SystemAllocator>::Get();
-        Entity* systemEntity = componentApp.Create(desc, startupParams);
+        Entity* systemEntity = componentApp.Create(desc, {});
         AZ_TEST_ASSERT(systemEntity);
         systemEntity->Init();
 
@@ -631,10 +627,7 @@ namespace UnitTest
             ComponentApplication::Descriptor desc;
             desc.m_useExistingAllocator = true;
 
-            ComponentApplication::StartupParameters startupParams;
-            startupParams.m_allocator = &AZ::AllocatorInstance<AZ::SystemAllocator>::Get();
-
-            Entity* systemEntity = m_componentApp->Create(desc, startupParams);
+            Entity* systemEntity = m_componentApp->Create(desc, {});
             systemEntity->Init();
 
             m_entity = aznew Entity();
@@ -1116,7 +1109,6 @@ namespace UnitTest
         app.UserSettingsFileLocatorBus::Handler::BusConnect();
 
         MyUserSettings::Reflect(app.GetSerializeContext());
-        systemEntity->CreateComponent<MemoryComponent>();
 
         UserSettingsComponent* globalUserSettingsComponent = systemEntity->CreateComponent<UserSettingsComponent>();
         AZ_TEST_ASSERT(globalUserSettingsComponent);
@@ -1978,10 +1970,7 @@ namespace Benchmark
         ComponentApplication::Descriptor desc;
         desc.m_useExistingAllocator = true;
 
-        ComponentApplication::StartupParameters startupParams;
-        startupParams.m_allocator = &AZ::AllocatorInstance<AZ::SystemAllocator>::Get();
-
-        Entity* systemEntity = componentApp.Create(desc, startupParams);
+        Entity* systemEntity = componentApp.Create(desc, {});
         systemEntity->Init();
 
         while(state.KeepRunning())

+ 0 - 2
Code/Framework/AzCore/Tests/DOM/DomFixtures.cpp

@@ -16,12 +16,10 @@ namespace AZ::Dom::Tests
     void DomTestHarness::SetUpHarness()
     {
         NameDictionary::Create();
-        AZ::AllocatorInstance<ValueAllocator>::Create();
     }
 
     void DomTestHarness::TearDownHarness()
     {
-        AZ::AllocatorInstance<ValueAllocator>::Destroy();
         NameDictionary::Destroy();
     }
 

+ 27 - 0
Code/Framework/AzCore/Tests/Debug/PerformanceCollectorTests.cpp

@@ -187,4 +187,31 @@ namespace UnitTest
         }
     }
 
+    TEST_F(PerformanceCollectorTest, CreatePerformnaceCollector_WithDefaultFileExtension_ValidateFileExtension)
+    {
+        auto paramList = AZStd::to_array<AZStd::string_view>({ "param1" });
+        auto onCompleteCallback = [](AZ::u32)
+        {
+        };
+
+        AZ::Debug::PerformanceCollector performanceCollector("PerformanceCollectorTest", paramList, onCompleteCallback);
+
+        const AZStd::string& actualExtension = performanceCollector.GetFileExtension();
+        ASSERT_EQ("json", actualExtension);
+    }
+
+    TEST_F(PerformanceCollectorTest, CreatePerformanceCollector_WithCustomFileExtension_ValidateFileExtension)
+    {
+        auto paramList = AZStd::to_array<AZStd::string_view>({ "param1" });
+        auto onCompleteCallback = [](AZ::u32)
+        {
+        };
+        const AZStd::string testFileExtention("test.json");
+
+        AZ::Debug::PerformanceCollector performanceCollector("PerformanceCollectorTest", paramList, onCompleteCallback, testFileExtention);
+
+        const AZStd::string& actualExtension = performanceCollector.GetFileExtension();
+        ASSERT_EQ(testFileExtention, actualExtension);
+    }
+
 }//namespace UnitTest

+ 0 - 4
Code/Framework/AzCore/Tests/EBus.cpp

@@ -1763,8 +1763,6 @@ namespace UnitTest
         using namespace QueueMessageTest;
 
         // Setup
-        AllocatorInstance<PoolAllocator>::Create();
-        AllocatorInstance<ThreadPoolAllocator>::Create();
         JobManagerDesc jobDesc;
         JobManagerThreadDesc threadDesc;
         jobDesc.m_workerThreads.push_back(threadDesc);
@@ -1818,8 +1816,6 @@ namespace UnitTest
         JobContext::SetGlobalContext(nullptr);
         delete m_jobContext;
         delete m_jobManager;
-        AllocatorInstance<ThreadPoolAllocator>::Destroy();
-        AllocatorInstance<PoolAllocator>::Destroy();
     }
 
     class QueueEbusTest

+ 0 - 12
Code/Framework/AzCore/Tests/Jobs.cpp

@@ -78,9 +78,6 @@ namespace UnitTest
         {
             LeakDetectionFixture::SetUp();
 
-            AllocatorInstance<PoolAllocator>::Create();
-            AllocatorInstance<ThreadPoolAllocator>::Create();
-
             JobManagerDesc desc;
             JobManagerThreadDesc threadDesc;
 #if AZ_TRAIT_SET_JOB_PROCESSOR_ID
@@ -113,9 +110,6 @@ namespace UnitTest
             delete m_jobContext;
             delete m_jobManager;
 
-            AllocatorInstance<ThreadPoolAllocator>::Destroy();
-            AllocatorInstance<PoolAllocator>::Destroy();
-
             LeakDetectionFixture::TearDown();
         }
     };
@@ -1608,9 +1602,6 @@ namespace Benchmark
 
         void internalSetUp()
         {
-            AllocatorInstance<PoolAllocator>::Create();
-            AllocatorInstance<ThreadPoolAllocator>::Create();
-
             JobManagerDesc desc;
             JobManagerThreadDesc threadDesc;
 #if AZ_TRAIT_SET_JOB_PROCESSOR_ID
@@ -1669,9 +1660,6 @@ namespace Benchmark
             m_randomDepths = {};
             delete m_jobContext;
             delete m_jobManager;
-
-            AllocatorInstance<ThreadPoolAllocator>::Destroy();
-            AllocatorInstance<PoolAllocator>::Destroy();
         }
         void TearDown(::benchmark::State&) override
         {

+ 0 - 72
Code/Framework/AzCore/Tests/Memory.cpp

@@ -119,8 +119,6 @@ namespace UnitTest
             // On windows we don't require to preallocate memory to function.
             // On most consoles we do!
             {
-                AllocatorInstance<SystemAllocator>::Create();
-
                 IAllocator& sysAllocator = AllocatorInstance<SystemAllocator>::Get();
 
                 for (int i = 0; i < 100; ++i)
@@ -154,14 +152,10 @@ namespace UnitTest
                         m_threads[i].join();
                     }
                 }
-                //////////////////////////////////////////////////////////////////////////
-
-                AllocatorInstance<SystemAllocator>::Destroy();
             }
 #endif
             memset(address, 0, AZ_ARRAY_SIZE(address) * sizeof(void*));
 
-            AllocatorInstance<SystemAllocator>::Create();
             IAllocator& sysAllocator = AllocatorInstance<SystemAllocator>::Get();
 
             for (int i = 0; i < 100; ++i)
@@ -287,8 +281,6 @@ namespace UnitTest
             //AZStd::chrono::microseconds exTime = AZStd::chrono::steady_clock::now() - startTime;
             //AZ_Printf("UnitTest::SystemAllocatorTest::mspaces","Time: %d Ms\n",exTime.count());
             //////////////////////////////////////////////////////////////////////////
-
-            AllocatorInstance<SystemAllocator>::Destroy();
         }
     };
 
@@ -302,21 +294,6 @@ namespace UnitTest
     {
     protected:
     public:
-        void SetUp() override
-        {
-            MemoryTrackingFixture::SetUp();
-
-            AllocatorInstance<SystemAllocator>::Create();
-            AllocatorInstance<PoolAllocator>::Create();
-        }
-
-        void TearDown() override
-        {
-            AllocatorInstance<PoolAllocator>::Destroy();
-            AllocatorInstance<SystemAllocator>::Destroy();
-            MemoryTrackingFixture::TearDown();
-        }
-
         void run()
         {
             IAllocator& poolAllocator = AllocatorInstance<PoolAllocator>::Get();
@@ -456,17 +433,6 @@ namespace UnitTest
             {
                 m_desc[i].m_stackSize = m_threadStackSize;
             }
-
-            AllocatorInstance<SystemAllocator>::Create();
-            AllocatorInstance<ThreadPoolAllocator>::Create();
-        }
-
-        void TearDown() override
-        {
-            AllocatorInstance<ThreadPoolAllocator>::Destroy();
-            AllocatorInstance<SystemAllocator>::Destroy();
-
-            MemoryTrackingFixture::TearDown();
         }
 
         void AllocDeallocFunc()
@@ -683,9 +649,6 @@ namespace UnitTest
             }
             //////////////////////////////////////////////////////////////////////////
 
-            // Our pools will support only 512 byte allocations
-            AZ::AllocatorInstance<MyThreadPoolAllocator>::Create();
-
             void* pooled512 = AZ::AllocatorInstance<MyThreadPoolAllocator>::Get().Allocate(512, 512);
             ASSERT_TRUE(pooled512);
             AZ::AllocatorInstance<MyThreadPoolAllocator>::Get().DeAllocate(pooled512);
@@ -694,8 +657,6 @@ namespace UnitTest
             void* pooled2048 = AZ::AllocatorInstance<MyThreadPoolAllocator>::Get().Allocate(2048, 2048);
             (void)pooled2048;
             AZ_TEST_STOP_TRACE_SUPPRESSION(1);
-
-            AZ::AllocatorInstance<MyThreadPoolAllocator>::Destroy();
         }
     };
 
@@ -711,21 +672,6 @@ namespace UnitTest
         : public MemoryTrackingFixture
     {
     public:
-        void SetUp() override
-        {
-            MemoryTrackingFixture::SetUp();
-
-            AllocatorInstance<SystemAllocator>::Create();
-            AllocatorInstance<PoolAllocator>::Create();
-        }
-
-        void TearDown() override
-        {
-            AllocatorInstance<PoolAllocator>::Destroy();
-            AllocatorInstance<SystemAllocator>::Destroy();
-            MemoryTrackingFixture::TearDown();
-        }
-
         void run()
         {
             IAllocator& sysAllocator = AllocatorInstance<SystemAllocator>::Get();
@@ -813,22 +759,6 @@ namespace UnitTest
             MyDerivedClass() = default;
         };
     public:
-        void SetUp() override
-        {
-            MemoryTrackingFixture::SetUp();
-
-            AllocatorInstance<SystemAllocator>::Create();
-            AllocatorInstance<PoolAllocator>::Create();
-        }
-
-        void TearDown() override
-        {
-            AllocatorInstance<PoolAllocator>::Destroy();
-            AllocatorInstance<SystemAllocator>::Destroy();
-
-            MemoryTrackingFixture::TearDown();
-        }
-
         void run()
         {
             IAllocator& sysAllocator = AllocatorInstance<SystemAllocator>::Get();
@@ -940,7 +870,6 @@ namespace UnitTest
     public:
         void SetUp() override
         {
-            AllocatorInstance<SystemAllocator>::Create();
             tr = (test_record*)AZ_OS_MALLOC(sizeof(test_record)*N, 8);
             MAX_SIZE = 4096;
         }
@@ -948,7 +877,6 @@ namespace UnitTest
         void TearDown() override
         {
             AZ_OS_FREE(tr);
-            AllocatorInstance<SystemAllocator>::Destroy();
         }
 
         //////////////////////////////////////////////////////////////////////////

+ 28 - 166
Code/Framework/AzCore/Tests/Memory/AllocatorBenchmarks.cpp

@@ -30,126 +30,13 @@ namespace Benchmark
         size_t GetMemorySize(void* memory);
     }
 
-    /// <summary>
-    /// Test allocator wrapper that redirects the calls to the passed TAllocator by using AZ::AllocatorInstance.
-    /// It also creates/destroys the TAllocator type (to reflect what happens at runtime)
-    /// </summary>
-    /// <typeparam name="TAllocator">Allocator type to wrap</typeparam>
-    template<typename TAllocator>
-    class TestAllocatorWrapper
+    class RawMallocAllocator
+        : public AZStd::stateless_allocator
     {
     public:
-        static void SetUp()
-        {
-            AZ::AllocatorInstance<TAllocator>::Create();
-        }
-
-        static void TearDown()
-        {
-            AZ::AllocatorInstance<TAllocator>::Destroy();
-        }
-
-        static void* Allocate(size_t byteSize, size_t alignment)
-        {
-            return AZ::AllocatorInstance<TAllocator>::Get().Allocate(byteSize, alignment);
-        }
-
-        static void DeAllocate(void* ptr, size_t byteSize = 0)
-        {
-            AZ::AllocatorInstance<TAllocator>::Get().DeAllocate(ptr, byteSize);
-        }
-
-        static void* ReAllocate(void* ptr, size_t newSize, size_t newAlignment)
-        {
-            return AZ::AllocatorInstance<TAllocator>::Get().ReAllocate(ptr, newSize, newAlignment);
-        }
-
-        static void GarbageCollect()
-        {
-            AZ::AllocatorInstance<TAllocator>::Get().GarbageCollect();
-        }
-
-        static size_t NumAllocatedBytes()
-        {
-            return AZ::AllocatorInstance<TAllocator>::Get().NumAllocatedBytes() +
-                AZ::AllocatorInstance<TAllocator>::Get().GetUnAllocatedMemory();
-        }
-
-        static size_t GetSize(void* ptr)
-        {
-            return AZ::AllocatorInstance<TAllocator>::Get().AllocationSize(ptr);
-        }
+        void GarbageCollect() {}
+        size_t NumAllocatedBytes() { return 0; }
     };
-
-    /// <summary>
-    /// Basic allocator used as a baseline. This allocator is the most basic allocation possible with the OS (AZ_OS_MALLOC).
-    /// </summary>
-    class RawMallocAllocator {};
-
-    template<>
-    class TestAllocatorWrapper<RawMallocAllocator>
-    {
-    public:
-        TestAllocatorWrapper()
-        {
-            s_numAllocatedBytes = 0;
-        }
-
-        static void SetUp()
-        {
-            s_numAllocatedBytes = 0;
-        }
-
-        static void TearDown()
-        {
-        }
-
-        static void* Allocate(size_t byteSize, size_t)
-        {
-            s_numAllocatedBytes += byteSize;
-            // Don't pass an alignment since we wont be able to get the memory size without also passing the alignment
-            return AZ_OS_MALLOC(byteSize, 1);
-        }
-
-        static void DeAllocate(void* ptr, size_t = 0)
-        {
-            s_numAllocatedBytes -= Platform::GetMemorySize(ptr);
-            AZ_OS_FREE(ptr);
-        }
-
-        static void* ReAllocate(void* ptr, size_t newSize, size_t)
-        {
-            s_numAllocatedBytes -= Platform::GetMemorySize(ptr);
-            AZ_OS_FREE(ptr);
-
-            s_numAllocatedBytes += newSize;
-            return AZ_OS_MALLOC(newSize, 1);
-        }
-
-        static size_t Resize(void* ptr, size_t newSize)
-        {
-            AZ_UNUSED(ptr);
-            AZ_UNUSED(newSize);
-
-            return 0;
-        }
-
-        static void GarbageCollect() {}
-
-        static size_t NumAllocatedBytes()
-        {
-            return s_numAllocatedBytes;
-        }
-
-        static size_t GetSize(void* ptr)
-        {
-            return Platform::GetMemorySize(ptr);
-        }
-
-    private:
-         inline static size_t s_numAllocatedBytes = 0;
-    };
-
     // We use both this HphaSchemaAllocator and the SystemAllocator configured with Hpha because the SystemAllocator
     // has extra things
     class HphaSchemaAllocator : public AZ::SimpleSchemaAllocator<AZ::HphaSchema>
@@ -199,14 +86,12 @@ namespace Benchmark
         : public ::benchmark::Fixture
     {
     protected:
-        using TestAllocatorType = TestAllocatorWrapper<TAllocator>;
+        using TestAllocatorType = TAllocator;
 
         virtual void internalSetUp(const ::benchmark::State& state)
         {
             if (state.thread_index() == 0)
             {
-                TestAllocatorType::SetUp();
-
                 m_allocations.resize(state.threads());
                 for (auto& perThreadAllocations : m_allocations)
                 {
@@ -221,8 +106,6 @@ namespace Benchmark
             {
                 m_allocations.clear();
                 m_allocations.shrink_to_fit();
-
-                TestAllocatorType::TearDown();
             }
         }
 
@@ -250,7 +133,11 @@ namespace Benchmark
             internalTearDown(state);
         }
 
+        const TestAllocatorType& GetAllocator() const { return m_allocator; }
+        TestAllocatorType& GetAllocator() { return m_allocator; }
+
     private:
+        TestAllocatorType m_allocator;
         AZStd::vector<AZStd::vector<void*>> m_allocations;
     };
 
@@ -278,21 +165,21 @@ namespace Benchmark
                     totalAllocationSize += allocationSize;
 
                     state.ResumeTiming();
-                    perThreadAllocations[allocationIndex] = TestAllocatorType::Allocate(allocationSize, 0);
+                    perThreadAllocations[allocationIndex] = this->GetAllocator().allocate(allocationSize, 0);
                     state.PauseTiming();
                 }
 
-                state.counters[s_counterAllocatorMemory] = benchmark::Counter(static_cast<double>(TestAllocatorType::NumAllocatedBytes()), benchmark::Counter::kDefaults);
+                state.counters[s_counterAllocatorMemory] = benchmark::Counter(static_cast<double>(this->GetAllocator().NumAllocatedBytes()), benchmark::Counter::kDefaults);
                 state.counters[s_counterBenchmarkMemory] = benchmark::Counter(static_cast<double>(totalAllocationSize), benchmark::Counter::kDefaults);
 
                 for (size_t allocationIndex = 0; allocationIndex < numberOfAllocations; ++allocationIndex)
                 {
                     const AllocationSizeArray& allocationArray = s_allocationSizes[TAllocationSize];
                     const size_t allocationSize = allocationArray[allocationIndex % allocationArray.size()];
-                    TestAllocatorType::DeAllocate(perThreadAllocations[allocationIndex], allocationSize);
+                    this->GetAllocator().deallocate(perThreadAllocations[allocationIndex], allocationSize);
                     perThreadAllocations[allocationIndex] = nullptr;
                 }
-                TestAllocatorType::GarbageCollect();
+                this->GetAllocator().GarbageCollect();
 
                 state.SetItemsProcessed(numberOfAllocations);
 
@@ -323,7 +210,7 @@ namespace Benchmark
                     const AllocationSizeArray& allocationArray = s_allocationSizes[TAllocationSize];
                     const size_t allocationSize = allocationArray[allocationIndex % allocationArray.size()];
                     totalAllocationSize += allocationSize;
-                    perThreadAllocations[allocationIndex] = TestAllocatorType::Allocate(allocationSize, 0);
+                    perThreadAllocations[allocationIndex] = this->GetAllocator().allocate(allocationSize, 0);
                 }
 
                 for (size_t allocationIndex = 0; allocationIndex < numberOfAllocations; ++allocationIndex)
@@ -331,17 +218,17 @@ namespace Benchmark
                     const AllocationSizeArray& allocationArray = s_allocationSizes[TAllocationSize];
                     const size_t allocationSize = allocationArray[allocationIndex % allocationArray.size()];
                     state.ResumeTiming();
-                    TestAllocatorType::DeAllocate(perThreadAllocations[allocationIndex], allocationSize);
+                    this->GetAllocator().deallocate(perThreadAllocations[allocationIndex], allocationSize);
                     state.PauseTiming();
                     perThreadAllocations[allocationIndex] = nullptr;
                 }
 
-                state.counters[s_counterAllocatorMemory] = benchmark::Counter(static_cast<double>(TestAllocatorType::NumAllocatedBytes()), benchmark::Counter::kDefaults);
+                state.counters[s_counterAllocatorMemory] = benchmark::Counter(static_cast<double>(this->GetAllocator().NumAllocatedBytes()), benchmark::Counter::kDefaults);
                 state.counters[s_counterBenchmarkMemory] = benchmark::Counter(static_cast<double>(totalAllocationSize), benchmark::Counter::kDefaults);
 
                 state.SetItemsProcessed(numberOfAllocations);
 
-                TestAllocatorType::GarbageCollect();
+                this->GetAllocator().GarbageCollect();
 
                 state.ResumeTiming();
             }
@@ -351,17 +238,7 @@ namespace Benchmark
     template<typename TAllocator>
     class RecordedAllocationBenchmarkFixture : public ::benchmark::Fixture
     {
-        using TestAllocatorType = TestAllocatorWrapper<TAllocator>;
-
-        virtual void internalSetUp()
-        {
-            TestAllocatorType::SetUp();
-        }
-
-        void internalTearDown()
-        {
-            TestAllocatorType::TearDown();
-        }
+        using TestAllocatorType = TAllocator;
 
         #pragma pack(push, 1)
         struct alignas(1) AllocatorOperation
@@ -380,24 +257,6 @@ namespace Benchmark
         static_assert(sizeof(AllocatorOperation) == 8);
 
     public:
-        void SetUp(const ::benchmark::State&) override
-        {
-            internalSetUp();
-        }
-        void SetUp(::benchmark::State&) override
-        {
-            internalSetUp();
-        }
-
-        void TearDown(const ::benchmark::State&) override
-        {
-            internalTearDown();
-        }
-        void TearDown(::benchmark::State&) override
-        {
-            internalTearDown();
-        }
-
         void Benchmark(benchmark::State& state)
         {
             for ([[maybe_unused]] auto _ : state)
@@ -436,7 +295,7 @@ namespace Benchmark
                                 if (it.second) // otherwise already allocated
                                 {
                                     state.ResumeTiming();
-                                    void* ptr = TestAllocatorType::Allocate(operation.m_size, operation.m_alignment);
+                                    void* ptr = this->GetAllocator().allocate(operation.m_size, operation.m_alignment);
                                     state.PauseTiming();
                                     totalAllocationSize += operation.m_size;
                                     it.first->second = ptr;
@@ -446,7 +305,7 @@ namespace Benchmark
                                     // Doing a resize, dont account for this memory change, this operation is rare and we dont have
                                     // the size of the previous allocation
                                     state.ResumeTiming();
-                                    TestAllocatorType::ReAllocate(it.first->second, operation.m_size, operation.m_alignment);
+                                    this->GetAllocator().reallocate(it.first->second, operation.m_size, operation.m_alignment);
                                     state.PauseTiming();
                                 }
                             }
@@ -459,7 +318,7 @@ namespace Benchmark
                                     {
                                         totalAllocationSize -= operation.m_size;
                                         state.ResumeTiming();
-                                        TestAllocatorType::DeAllocate(
+                                        this->GetAllocator().deallocate(
                                             ptrIt->second,
                                             /*operation.m_size*/ 0); // size is not correct after a resize, a 0 size deals with it
                                         state.PauseTiming();
@@ -470,7 +329,7 @@ namespace Benchmark
                                 {
                                     // Just to account of the call of deallocate(nullptr);
                                     state.ResumeTiming();
-                                    TestAllocatorType::DeAllocate(nullptr, /*operation.m_size*/ 0);
+                                    this->GetAllocator().deallocate(nullptr, /*operation.m_size*/ 0);
                                     state.PauseTiming();
                                 }
                             }
@@ -486,23 +345,26 @@ namespace Benchmark
                     for (const auto& pointerMapping : pointerRemapping)
                     {
                         state.ResumeTiming();
-                        TestAllocatorType::DeAllocate(pointerMapping.second);
+                        this->GetAllocator().deallocate(pointerMapping.second);
                         state.PauseTiming();
                     }
                     itemsProcessed += pointerRemapping.size();
                     pointerRemapping.clear();
                 }
 
-                state.counters[s_counterAllocatorMemory] = benchmark::Counter(static_cast<double>(TestAllocatorType::NumAllocatedBytes()), benchmark::Counter::kDefaults);
+                state.counters[s_counterAllocatorMemory] = benchmark::Counter(static_cast<double>(this->GetAllocator().NumAllocatedBytes()), benchmark::Counter::kDefaults);
                 state.counters[s_counterBenchmarkMemory] = benchmark::Counter(static_cast<double>(totalAllocationSize), benchmark::Counter::kDefaults);
 
                 state.SetItemsProcessed(itemsProcessed);
 
-                TestAllocatorType::GarbageCollect();
+                this->GetAllocator().GarbageCollect();
 
                 state.ResumeTiming();
             }
         }
+    private:
+        TestAllocatorType m_allocator;
+        TestAllocatorType& GetAllocator() { return m_allocator; }
     };
 
     // For non-threaded ranges, run 100, 400, 1600 amounts

+ 0 - 10
Code/Framework/AzCore/Tests/Memory/HphaAllocator.cpp

@@ -56,16 +56,6 @@ namespace UnitTest
         : public LeakDetectionFixture
         , public ::testing::WithParamInterface<HphaSchemaTestParameters>
     {
-    public:
-        void SetUp() override
-        {
-            AZ::AllocatorInstance<HphaSchema_TestAllocator>::Create();
-        }
-
-        void TearDown() override
-        {
-            AZ::AllocatorInstance<HphaSchema_TestAllocator>::Destroy();
-        }
     };
 
     TEST_P(HphaSchemaTestFixture, Allocate)

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