Browse Source

fixed new merge issues

Signed-off-by: T.J. McGrath-Daly <[email protected]>
T.J. McGrath-Daly 3 năm trước cách đây
mục cha
commit
a4f3e6e657
100 tập tin đã thay đổi với 3598 bổ sung1982 xóa
  1. 14 0
      .github/CODEOWNERS
  2. 73 6
      AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Benchmark_GPU.py
  3. 44 1
      AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py
  4. 294 22
      AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponentsLevel_DisplayMapperAdded.py
  5. 313 40
      AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DisplayMapperAdded.py
  6. 0 6
      AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py
  7. 1 1
      AutomatedTesting/Gem/PythonTests/EditorPythonBindings/LevelComponentCommands_test_case.py
  8. 27 2
      AutomatedTesting/Gem/PythonTests/Multiplayer/TestSuite_Main.py
  9. 8 8
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests.py
  10. 0 174
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/assets_with_direct_preload_dependency/TestC.slice
  11. 0 174
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/assets_with_direct_preload_dependency/TestD.slice
  12. 0 222
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/assets_with_nested_preload_dependency/TestA.slice
  13. 0 174
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/assets_with_nested_preload_dependency/TestB.slice
  14. 0 174
      AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/assets_with_nested_preload_dependency/TestD.slice
  15. 0 181
      AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks.py
  16. 0 3
      AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/TestSuite_Main.py
  17. 0 21
      AutomatedTesting/Gem/PythonTests/largeworlds/large_worlds_utils/editor_dynveg_test_helper.py
  18. 4 5
      AutomatedTesting/Levels/Physics/ScriptCanvas_PreUpdateEvent/ScriptCanvas_PreUpdateEvent.prefab
  19. 1 115
      Code/Editor/CryEdit.cpp
  20. 0 28
      Code/Editor/CryEdit.h
  21. 143 24
      Code/Editor/MainWindow.cpp
  22. 3 2
      Code/Framework/AzCore/AzCore/DOM/DomValue.h
  23. 3 0
      Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl
  24. 11 3
      Code/Framework/AzCore/AzCore/base.h
  25. 7 4
      Code/Framework/AzCore/AzCore/std/containers/vector.h
  26. 1 1
      Code/Framework/AzCore/AzCore/std/parallel/thread.h
  27. 10 1
      Code/Framework/AzCore/Platform/Linux/AzCore/std/parallel/internal/thread_Linux.cpp
  28. 17 0
      Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/AdapterBuilder.cpp
  29. 19 1
      Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/AdapterBuilder.h
  30. 1 1
      Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/BasicAdapter.h
  31. 198 0
      Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/CvarAdapter.cpp
  32. 31 0
      Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/CvarAdapter.h
  33. 0 4
      Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/DocumentAdapter.h
  34. 101 6
      Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/DocumentSchema.h
  35. 98 1
      Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/PropertyEditorNodes.h
  36. 2 2
      Code/Framework/AzFramework/AzFramework/Network/AssetProcessorConnection.cpp
  37. 3 23
      Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSceneQueries.h
  38. 2 9
      Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h
  39. 19 1
      Code/Framework/AzFramework/AzFramework/Physics/HeightfieldProviderBus.h
  40. 1 1
      Code/Framework/AzFramework/AzFramework/Physics/Mocks/MockHeightfieldProviderBus.h
  41. 15 0
      Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp
  42. 1 0
      Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h
  43. 2 0
      Code/Framework/AzFramework/AzFramework/azframework_files.cmake
  44. 3 3
      Code/Framework/AzFramework/Tests/DocumentPropertyEditor/AdapterBuilderTests.cpp
  45. 167 0
      Code/Framework/AzFramework/Tests/DocumentPropertyEditor/CvarAdapterTests.cpp
  46. 57 0
      Code/Framework/AzFramework/Tests/DocumentPropertyEditor/SchemaTests.cpp
  47. 2 0
      Code/Framework/AzFramework/Tests/frameworktests_files.cmake
  48. 36 0
      Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h
  49. 3 0
      Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h
  50. 2 0
      Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp
  51. 5 0
      Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp
  52. 5 0
      Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h
  53. 14 0
      Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp
  54. 1 0
      Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h
  55. 7 1
      Code/Framework/AzToolsFramework/AzToolsFramework/SourceControl/PerforceComponent.cpp
  56. 14 0
      Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp
  57. 2 0
      Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h
  58. 31 0
      Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp
  59. 12 1
      Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx
  60. 9 0
      Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp
  61. 4 0
      Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.hxx
  62. 6 0
      Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp
  63. 1 0
      Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/Mocks/MockFocusModeInterface.h
  64. 51 0
      Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/LocalViewBookmarkComponent.cpp
  65. 31 0
      Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/LocalViewBookmarkComponent.h
  66. 514 0
      Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/LocalViewBookmarkLoader.cpp
  67. 58 0
      Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/LocalViewBookmarkLoader.h
  68. 111 0
      Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/SharedViewBookmarkComponent.cpp
  69. 55 0
      Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/SharedViewBookmarkComponent.h
  70. 88 0
      Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewBookmarkLoaderInterface.h
  71. 36 0
      Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewBookmarkSystemComponent.cpp
  72. 38 0
      Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewBookmarkSystemComponent.h
  73. 23 7
      Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp
  74. 9 0
      Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake
  75. 109 29
      Code/Framework/AzToolsFramework/Tests/ManipulatorCoreTests.cpp
  76. 4 1
      Code/Legacy/CryCommon/ISystem.h
  77. 4 1
      Code/Legacy/CrySystem/DllMain.cpp
  78. 1 1
      Code/Tools/AssetProcessor/native/tests/AssetProcessorMessagesTests.cpp
  79. 4 0
      Code/Tools/ProjectManager/Source/Application.cpp
  80. 1 0
      Code/Tools/SerializeContextTools/Converter.cpp
  81. 0 24
      Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderCapabilitiesConfigFile.cpp
  82. 0 40
      Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderCapabilitiesConfigFile.h
  83. 0 136
      Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp
  84. 0 32
      Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.h
  85. 3 2
      Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp
  86. 2 1
      Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.h
  87. 3 5
      Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp
  88. 0 81
      Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/GlobalBuildOptions.cpp
  89. 0 37
      Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/GlobalBuildOptions.h
  90. 130 57
      Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp
  91. 10 20
      Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.h
  92. 28 42
      Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp
  93. 237 0
      Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuildArgumentsManager.cpp
  94. 146 0
      Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuildArgumentsManager.h
  95. 15 3
      Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp
  96. 2 1
      Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h
  97. 26 15
      Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp
  98. 1 1
      Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.h
  99. 2 0
      Gems/Atom/Asset/Shader/Code/Tests/Common/ShaderBuilderTestFixture.cpp
  100. 8 0
      Gems/Atom/Asset/Shader/Code/Tests/Common/ShaderBuilderTestFixture.h

+ 14 - 0
.github/CODEOWNERS

@@ -0,0 +1,14 @@
+
+/cmake/LYTestWrappers.cmake @o3de/sig-testing-reviewers
+
+/Code/Framework/AzTest @o3de/sig-testing-reviewers
+/Code/Tools/AzTestRunner/ @o3de/sig-testing-reviewers
+
+/o3de/pytest.ini @o3de/sig-testing-reviewers
+/o3de/AutomatedTesting/Gem/PythonTests/editor_test_testing/ @o3de/sig-testing-reviewers
+/o3de/scripts/ctest/ @o3de/sig-testing-reviewers
+
+/Tools/LyTestTools/ @o3de/sig-testing-reviewers
+# This is being deprecated.
+/Tools/RemoteConsole/ @o3de/sig-testing-reviewers
+

+ 73 - 6
AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Benchmark_GPU.py

@@ -6,6 +6,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
 """
 import logging
 import os
+import psutil
 
 import pytest
 
@@ -15,16 +16,76 @@ from ly_test_tools.benchmark.data_aggregator import BenchmarkDataAggregator
 logger = logging.getLogger(__name__)
 
 
[email protected]('rhi', ['dx12', 'vulkan'])
+def filebeat_service_running():
+    """
+    Checks if the filebeat service is currently running on the OS.
+    :return: True if filebeat service detected and running, False otherwise.
+    """
+    result = False
+    try:
+        filebeat_service = psutil.win_service_get('filebeat')
+        filebeat_service_info = filebeat_service.as_dict()
+        if filebeat_service_info['status'] == 'running':
+            result = True
+    except psutil.NoSuchProcess:
+        return result
+
+    return result
+
+
 @pytest.mark.parametrize("project", ["AutomatedTesting"])
 @pytest.mark.parametrize("launcher_platform", ["windows_editor"])
 @pytest.mark.parametrize("level", ["AtomFeatureIntegrationBenchmark"])
 class TestPerformanceBenchmarkSuite(object):
-    def test_AtomFeatureIntegrationBenchmarkTest_UploadMetrics(
+
+    @pytest.mark.parametrize('rhi', ['-rhi=dx12'])
+    def test_AtomFeatureIntegrationBenchmarkTest_GatherBenchmarkMetrics_DX12(
+            self, request, editor, workspace, rhi, project, launcher_platform, level):
+        """
+        Please review the hydra script run by this test for more specific test info.
+        """
+        expected_lines = [
+            "Benchmark metadata captured.",
+            "Pass timestamps captured.",
+            "CPU frame time captured.",
+            "Captured data successfully.",
+            "Exited game mode"
+        ]
+
+        unexpected_lines = [
+            "Failed to capture data.",
+            "Failed to capture pass timestamps.",
+            "Failed to capture CPU frame time.",
+            "Failed to capture benchmark metadata."
+        ]
+
+        hydra.launch_and_validate_results(
+            request,
+            os.path.join(os.path.dirname(__file__), "tests"),
+            editor,
+            "hydra_GPUTest_AtomFeatureIntegrationBenchmark.py",
+            timeout=600,
+            expected_lines=expected_lines,
+            unexpected_lines=unexpected_lines,
+            halt_on_unexpected=True,
+            cfg_args=[level, rhi],
+            null_renderer=False,
+        )
+
+    @pytest.mark.skipif(not filebeat_service_running(), reason="filebeat service not running")
+    def test_AtomFeatureIntegrationBenchmarkTest_SendBenchmarkMetrics_DX12(
+            self, request, editor, workspace, project, launcher_platform, level):
+        """
+        Gathers the DX12 benchmark metrics and uses filebeat to send the metrics data.
+        """
+        aggregator = BenchmarkDataAggregator(workspace, logger, 'main_gpu')
+        aggregator.upload_metrics('dx12')
+
+    @pytest.mark.parametrize('rhi', ['-rhi=Vulkan'])
+    def test_AtomFeatureIntegrationBenchmarkTest_GatherBenchmarkMetrics_Vulkan(
             self, request, editor, workspace, rhi, project, launcher_platform, level):
         """
         Please review the hydra script run by this test for more specific test info.
-        Tests the performance of the Simple level.
         """
         expected_lines = [
             "Benchmark metadata captured.",
@@ -50,9 +111,15 @@ class TestPerformanceBenchmarkSuite(object):
             expected_lines=expected_lines,
             unexpected_lines=unexpected_lines,
             halt_on_unexpected=True,
-            cfg_args=[level],
+            cfg_args=[level, rhi],
             null_renderer=False,
         )
 
-        aggregator = BenchmarkDataAggregator(workspace, logger, 'periodic')
-        aggregator.upload_metrics(rhi)
+    @pytest.mark.skipif(not filebeat_service_running(), reason="filebeat service not running")
+    def test_AtomFeatureIntegrationBenchmarkTest_SendBenchmarkMetrics_Vulkan(
+            self, request, editor, workspace, project, launcher_platform, level):
+        """
+        Gathers the Vulkan benchmark metrics and uses filebeat to send the metrics data.
+        """
+        aggregator = BenchmarkDataAggregator(workspace, logger, 'main_gpu')
+        aggregator.upload_metrics('Vulkan')

+ 44 - 1
AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py

@@ -63,6 +63,23 @@ MESH_LOD_TYPE = {
     'specific lod': 2,
 }
 
+# Display Mapper type
+DISPLAY_MAPPER_OPERATION_TYPE = {
+    'Aces': 0,
+    'AcesLut': 1,
+    'Passthrough': 2,
+    'GammaSRGB': 3,
+    'Reinhard': 4,
+}
+
+# Display Mapper presets
+DISPLAY_MAPPER_PRESET = {
+    '48Nits': 0,
+    '1000Nits': 1,
+    '2000Nits': 2,
+    '4000Nits': 3,
+}
+
 # Level list used in Editor Level Load Test
 # WARNING: "Sponza" level is sandboxed due to an intermittent failure.
 LEVEL_LIST = ["hermanubis", "hermanubis_high", "macbeth_shaderballs", "PbrMaterialChart", "ShadowTest"]
@@ -312,16 +329,42 @@ class AtomComponentProperties:
     def display_mapper(property: str = 'name') -> str:
         """
         Display Mapper level component properties.
+          - 'Type' specifies the Display Mapper type from atom_constants.py DISPLAY_MAPPER_OPERATION_TYPE
           - 'Enable LDR color grading LUT' toggles the use of LDR color grading LUT
           - 'LDR color Grading LUT' is the Low Definition Range (LDR) color grading for Look-up Textures (LUT) which is
-            an Asset.id value corresponding to a lighting asset file.
+            an Asset.id value corresponding to a LUT asset file.
+          - 'Override Defaults' toggle enables parameter overrides for ACES settings (bool)
+          - 'Alter Surround' toggle applies gamma adjustments for dim surround (bool)
+          - 'Alter Desaturation' toggle applies desaturation adjustment for luminance differences (bool)
+          - 'Alter CAT D60 to D65' toggles conversion referencing black luminance level constant (bool)
+          - 'Preset Selection' select from a list of presets from atom_constants.py DISPLAY_MAPPER_PRESET
+          - 'Cinema Limit (black)' reference black
+          - 'Cinema Limit (white)' reference white
+          - 'Min Point (luminance)' linear extension below this value
+          - 'Mid Point (luminance)' middle gray value
+          - 'Max Point (luminance)' linear extension above this value
+          - 'Surround Gamma' applied to compensate for the condition of the viewing environment
+          - 'Gamma' value applied as the basic Gamma curve Opto-Electrical Transfer Function (OETF)
         :param property: From the last element of the property tree path. Default 'name' for component name string.
         :return: Full property path OR component name if no property specified.
         """
         properties = {
             'name': 'Display Mapper',
+            'Type': 'Controller|Configuration|Type',
             'Enable LDR color grading LUT': 'Controller|Configuration|Enable LDR color grading LUT',
             'LDR color Grading LUT': 'Controller|Configuration|LDR color Grading LUT',
+            'Override Defaults': 'Controller|Configuration|ACES Parameters|Override Defaults',
+            'Alter Surround': 'Controller|Configuration|ACES Parameters|Alter Surround',
+            'Alter Desaturation': 'Controller|Configuration|ACES Parameters|Alter Desaturation',
+            'Alter CAT D60 to D65': 'Controller|Configuration|ACES Parameters|Alter CAT D60 to D65',
+            'Preset Selection': 'Controller|Configuration|ACES Parameters|Load Preset|Preset Selection',
+            'Cinema Limit (black)': 'Controller|Configuration|ACES Parameters|Cinema Limit (black)',
+            'Cinema Limit (white)': 'Controller|Configuration|ACES Parameters|Cinema Limit (white)',
+            'Min Point (luminance)': 'Controller|Configuration|ACES Parameters|Min Point (luminance)',
+            'Mid Point (luminance)': 'Controller|Configuration|ACES Parameters|Mid Point (luminance)',
+            'Max Point (luminance)': 'Controller|Configuration|ACES Parameters|Max Point (luminance)',
+            'Surround Gamma': 'Controller|Configuration|ACES Parameters|Surround Gamma',
+            'Gamma': 'Controller|Configuration|ACES Parameters|Gamma',
         }
         return properties[property]
 

+ 294 - 22
AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponentsLevel_DisplayMapperAdded.py

@@ -9,25 +9,71 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
 class Tests:
     creation_undo = (
         "UNDO level component addition success",
-        "UNDO level component addition failed")
+        "P0: UNDO level component addition failed")
     creation_redo = (
         "REDO Level component addition success",
-        "REDO Level component addition failed")
+        "P0: REDO Level component addition failed")
     display_mapper_component = (
         "Level has a Display Mapper component",
-        "Level failed to find Display Mapper component")
+        "P0: Level failed to find Display Mapper component")
     ldr_color_grading_lut = (
         "LDR color Grading LUT asset set",
-        "LDR color Grading LUT asset could not be set")
+        "P0: LDR color Grading LUT asset could not be set")
     enable_ldr_color_grading_lut = (
         "Enable LDR color grading LUT set",
-        "Enable LDR color grading LUT could not be set")
+        "P0: Enable LDR color grading LUT could not be set")
     enter_game_mode = (
         "Entered game mode",
-        "Failed to enter game mode")
+        "P0: Failed to enter game mode")
     exit_game_mode = (
         "Exited game mode",
-        "Couldn't exit game mode")
+        "P0: Couldn't exit game mode")
+    override_defaults = (
+        "Override Defaults property set",
+        "P1: Override Defaults property failed to be set correctly")
+    alter_surround = (
+        "Alter Surround property set",
+        "P1: Alter Surround property failed to be set correctly")
+    alter_desaturation = (
+        "Alter Desaturation property set",
+        "P1: Alter Desaturation property failed to be set correctly")
+    alter_cat = (
+        "Alter CAT D60 to D65 property set",
+        "P1: Alter CAT D60 to D65 property failed to be set correctly")
+    black_level_min = (
+        "Cinema Limit (black) property set to minimum value",
+        "P1: Cinema Limit (black) property failed to take minimum value")
+    black_level_max = (
+        "Cinema Limit (black) property set to maximum value",
+        "P1: Cinema Limit (black) property failed to take maximum value")
+    white_level_min = (
+        "Cinema Limit (white) property set to minimum value",
+        "P1: Cinema Limit (white) property failed to take minimum value")
+    white_level_max = (
+        "Cinema Limit (white) property set to maximum value",
+        "P1: Cinema Limit (white) property failed to take maximum value")
+    luminance_level_min = (
+        "Min Point (luminance) property set",
+        "P1: Min Point (luminance) property failed to set expected value")
+    luminance_level_mid = (
+        "Mid Point (luminance) property set",
+        "P1: Mid Point (luminance) property failed to set expected value")
+    luminance_level_max = (
+        "Max Point (luminance) property set",
+        "P1: Max Point (luminance) property failed to set expected value")
+    surround_gamma = (
+        "Surround Gamma property set",
+        "P1: Surround Gamma property failed to set expected value")
+    gamma = (
+        "Gamma property set",
+        "P1: Gamma property failed to set expected value")
+    display_mapper_type = (
+        "Display Mapper Operation Type is correctly set",
+        "P1: Display Mapper Operation type is not as expected")
+
+
+# IsClose tolerance defaults to , 1e-9, but float values in some tests need a looser tolerance
+TOLERANCE = 1e-6
 
 
 def AtomEditorComponentsLevel_DisplayMapper_AddedToEntity():
@@ -48,20 +94,36 @@ def AtomEditorComponentsLevel_DisplayMapper_AddedToEntity():
     2) UNDO the level component addition.
     3) REDO the level component addition.
     4) Set LDR color Grading LUT asset.
-    5) Set Enable LDR color grading LUT property True
-    6) Enter/Exit game mode.
-    7) Look for errors and asserts.
+    5) Set the Display Mapper Operation Type enumerated in DISPLAY_MAPPER_OPERATION_TYPE for each type
+    6) Set Enable LDR color grading LUT property True
+    7) Toggle Override Defaults
+    8) Toggle Alter Surround
+    9) Toggle Alter Desaturation
+    10) Toggle 'Alter CAT D60 to D65'
+    11) Set 'Cinema Limit (black)' max value which is dynamic based on Cinema Limit (white) then min value
+    12) Set 'Cinema Limit (white)' max value then min, and finally back to default
+    13) Set 'Min Point (luminance)' to high and low value
+    14) Set 'Mid Point (luminance)' to high and low value then set default
+    15) Set 'Max Point (luminance)' to high and low value then set default
+    16) Set 'Surround Gamma' to high and low value
+    17) Set 'Gamma' to high and low value
+    18) Enter/Exit game mode.
+    19) Select and load each preset
+    20) Look for errors and asserts.
 
     :return: None
     """
     import os
 
+    import azlmbr.bus as bus
     import azlmbr.legacy.general as general
+    import azlmbr.render as render
 
+    from azlmbr.math import Math_IsClose
     from editor_python_test_tools.asset_utils import Asset
     from editor_python_test_tools.editor_entity_utils import EditorLevelEntity
     from editor_python_test_tools.utils import Report, Tracer, TestHelper
-    from Atom.atom_utils.atom_constants import AtomComponentProperties
+    from Atom.atom_utils.atom_constants import AtomComponentProperties, DISPLAY_MAPPER_PRESET, DISPLAY_MAPPER_OPERATION_TYPE
 
     with Tracer() as error_tracer:
         # Test setup begins.
@@ -89,7 +151,7 @@ def AtomEditorComponentsLevel_DisplayMapper_AddedToEntity():
         Report.result(Tests.creation_redo, EditorLevelEntity.has_component(AtomComponentProperties.display_mapper()))
 
         # 4. Set LDR color Grading LUT asset.
-        display_mapper_asset_path = os.path.join("TestData", "test.lightingpreset.azasset")
+        display_mapper_asset_path = os.path.join("LookupTables", "LUT_Sepia.azasset")
         display_mapper_asset = Asset.find_asset_by_path(display_mapper_asset_path, False)
         display_mapper_component.set_component_property_value(
             AtomComponentProperties.display_mapper('LDR color Grading LUT'), display_mapper_asset.id)
@@ -98,20 +160,230 @@ def AtomEditorComponentsLevel_DisplayMapper_AddedToEntity():
             display_mapper_component.get_component_property_value(
                 AtomComponentProperties.display_mapper('LDR color Grading LUT')) == display_mapper_asset.id)
 
-        # 5. Set Enable LDR color grading LUT property True
+        for operation_type in DISPLAY_MAPPER_OPERATION_TYPE.keys():
+            # 5. Set the Display Mapper Operation Type enumerated in DISPLAY_MAPPER_OPERATION_TYPE for each type
+            # Type property cannot be set currently. as a workaround we are calling an ebus to set the operation type
+            # display_mapper_component.set_component_property_value(
+            #     AtomComponentProperties.display_mapper('Type'), DISPLAY_MAPPER_OPERATION_TYPE[operation_type])
+            render.DisplayMapperComponentRequestBus(
+                bus.Broadcast, "SetDisplayMapperOperationType", DISPLAY_MAPPER_OPERATION_TYPE[operation_type])
+            general.idle_wait_frames(3)
+            set_type = render.DisplayMapperComponentRequestBus(bus.Broadcast, "GetDisplayMapperOperationType")
+            Report.info(f"DiplayMapperOperationType: {set_type}")
+            Report.result(Tests.display_mapper_type, set_type == DISPLAY_MAPPER_OPERATION_TYPE[operation_type])
+
+            # 6. Set Enable LDR color grading LUT property True
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Enable LDR color grading LUT'), True)
+            Report.result(
+                Tests.enable_ldr_color_grading_lut,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Enable LDR color grading LUT')) is True)
+
+            # 7. Toggle Override Defaults
+            # Set Override Defaults to False
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Override Defaults'), False)
+            Report.result(
+                Tests.override_defaults,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Override Defaults')) is False)
+
+            # Set Override Defaults to True
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Override Defaults'), True)
+            Report.result(
+                Tests.override_defaults,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Override Defaults')) is True)
+
+            # 8. Toggle Alter Surround
+            # Set Alter Surround to True
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Alter Surround'), True)
+            Report.result(
+                Tests.alter_surround,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Alter Surround')) is True)
+
+            # Set Alter Surround to False
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Alter Surround'), False)
+            Report.result(
+                Tests.alter_surround,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Alter Surround')) is False)
+
+            # 9. Toggle Alter Desaturation
+            # Set Alter Desaturation to True
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Alter Desaturation'), True)
+            Report.result(
+                Tests.alter_desaturation,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Alter Desaturation')) is True)
+
+            # Set Alter Desaturation to False
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Alter Desaturation'), False)
+            Report.result(
+                Tests.alter_desaturation,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Alter Desaturation')) is False)
+
+            # 10. Toggle 'Alter CAT D60 to D65'
+            # Set 'Alter CAT D60 to D65' to True
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Alter CAT D60 to D65'), True)
+            Report.result(
+                Tests.alter_cat,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Alter CAT D60 to D65')) is True)
+
+            # Set 'Alter CAT D60 to D65' to False
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Alter CAT D60 to D65'), False)
+            Report.result(
+                Tests.alter_cat,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Alter CAT D60 to D65')) is False)
+
+            general.idle_wait_frames(1)
+
+            # 11. Set 'Cinema Limit (black)' max value which is dynamic based on Cinema Limit (white) then min value
+            # set max value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (black)'), value=48.0)
+            Report.result(Tests.black_level_max, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (black)')), 48.0, TOLERANCE))
+
+            # set min value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (black)'), value=0.02)
+            Report.result(Tests.black_level_min, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (black)')), 0.02, TOLERANCE))
+
+            # 12. Set 'Cinema Limit (white)' maximum value then min, and finally back to default
+            # set max value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (white)'), value=4000.0)
+            Report.result(Tests.white_level_max, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (white)')), 4000.0, TOLERANCE))
+
+            # Set min value which is dynamic based on Cinema Limit (black)
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (white)'), value=0.02)
+            Report.result(Tests.white_level_min, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (white)')), 0.02, TOLERANCE))
+
+            # Reset this to the default 48 so following cycles don't impact Cinema Limit (Black)
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (white)'), value=48.0)
+
+            # 13. Set 'Min Point (luminance)' to high and low value
+            # set high value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Min Point (luminance)'), value=4.8)
+            Report.info(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Min Point (luminance)')))
+            Report.result(Tests.luminance_level_min, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Min Point (luminance)')), 4.8, TOLERANCE))
+
+            # set low value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Min Point (luminance)'), value=0.002)
+            Report.result(Tests.luminance_level_min, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Min Point (luminance)')), 0.002, TOLERANCE))
+
+            # 14. Set 'Mid Point (luminance)' to high and low value then set default
+            # set high value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Mid Point (luminance)'), value=1005.0)
+            Report.result(Tests.luminance_level_mid, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Mid Point (luminance)')), 1005.0, TOLERANCE))
+
+            # set low value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Mid Point (luminance)'), value=0.002)
+            Report.result(Tests.luminance_level_mid, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Mid Point (luminance)')), 0.002, TOLERANCE))
+
+            # restore the default since as this impacts the range of 'Min Point (luminance)'
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Mid Point (luminance)'), value=4.8)
+
+            # 15. Set 'Max Point (luminance)' to high and low value then set default
+            # set a high value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Max Point (luminance)'), value=4000.0)
+            Report.result(Tests.luminance_level_max, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Max Point (luminance)')), 4000.0, TOLERANCE))
+
+            # set a low value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Max Point (luminance)'), value=0.002)
+            Report.result(Tests.luminance_level_max, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Max Point (luminance)')), 0.002, TOLERANCE))
+
+            # restore the default since this impacts the range of 'Mid Point (luminance)'
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Max Point (luminance)'), value=1005.7191162)
+
+            # 16. Set 'Surround Gamma' to high and low value
+            # set a high value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Surround Gamma'), value=1.2)
+            Report.result(Tests.surround_gamma, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Surround Gamma')), 1.2, TOLERANCE))
+
+            # set a low value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Surround Gamma'), value=0.6)
+            Report.result(Tests.surround_gamma, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Surround Gamma')), 0.6, TOLERANCE))
+
+            # 17. Set 'Gamma' to high and low value
+            # set a high value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Gamma'), value=4.0)
+            Report.result(Tests.gamma, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Gamma')), 4.0, TOLERANCE))
+
+            # set a low value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Gamma'), value=0.2)
+            Report.result(Tests.gamma, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Gamma')), 0.2, TOLERANCE))
+
+            # 18. Enter/Exit game mode.
+            TestHelper.enter_game_mode(Tests.enter_game_mode)
+            general.idle_wait_frames(1)
+            TestHelper.exit_game_mode(Tests.exit_game_mode)
+
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Enable LDR color grading LUT'), False)
+
         display_mapper_component.set_component_property_value(
             AtomComponentProperties.display_mapper('Enable LDR color grading LUT'), True)
-        Report.result(
-            Tests.enable_ldr_color_grading_lut,
-            display_mapper_component.get_component_property_value(
-                AtomComponentProperties.display_mapper('Enable LDR color grading LUT')) is True)
 
-        # 6. Enter/Exit game mode.
-        TestHelper.enter_game_mode(Tests.enter_game_mode)
-        general.idle_wait_frames(1)
-        TestHelper.exit_game_mode(Tests.exit_game_mode)
+        cinema_limit_white_presets = [48.0, 184.3200073, 368.6400146, 737.2800293]
+        for preset in DISPLAY_MAPPER_PRESET.keys():
+            # 19. Select and load each preset
+            # Preset Selection cannot be set or loaded currently; as a workaround we are calling an ebus to load preset
+            # A fix is in progress
+            # display_mapper_component.set_component_property_value(
+            #     AtomComponentProperties.display_mapper('Preset Selection'), DISPLAY_MAPPER_PRESET[preset])
+            render.DisplayMapperComponentRequestBus(bus.Broadcast, "LoadPreset", DISPLAY_MAPPER_PRESET[preset])
+            general.idle_wait_frames(1)
+            # check some value to confirm preset loaded
+            test_preset = (f"Preset {preset} loaded expected value",
+                      f"P1: Preset {preset} failed to load values as expected")
+            Report.result(test_preset, Math_IsClose(
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Cinema Limit (white)')),
+                cinema_limit_white_presets[DISPLAY_MAPPER_PRESET[preset]], TOLERANCE))
 
-        # 7. Look for errors and asserts.
+        # 20. Look for errors and asserts.
         TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
         for error_info in error_tracer.errors:
             Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")

+ 313 - 40
AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DisplayMapperAdded.py

@@ -9,43 +9,89 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
 class Tests:
     creation_undo = (
         "UNDO Entity creation success",
-        "UNDO Entity creation failed")
+        "P0: UNDO Entity creation failed")
     creation_redo = (
         "REDO Entity creation success",
-        "REDO Entity creation failed")
+        "P0: REDO Entity creation failed")
     display_mapper_creation = (
         "Display Mapper Entity successfully created",
-        "Display Mapper Entity failed to be created")
+        "P0: Display Mapper Entity failed to be created")
     display_mapper_component = (
         "Entity has a Display Mapper component",
-        "Entity failed to find Display Mapper component")
+        "P0: Entity failed to find Display Mapper component")
     enter_game_mode = (
         "Entered game mode",
-        "Failed to enter game mode")
+        "P0: Failed to enter game mode")
     exit_game_mode = (
         "Exited game mode",
-        "Couldn't exit game mode")
+        "P0: Couldn't exit game mode")
     is_visible = (
         "Entity is visible",
-        "Entity was not visible")
+        "P0: Entity was not visible")
     is_hidden = (
         "Entity is hidden",
-        "Entity was not hidden")
+        "P0: Entity was not hidden")
     ldr_color_grading_lut = (
         "LDR color Grading LUT asset set",
-        "LDR color Grading LUT asset could not be set")
+        "P0: LDR color Grading LUT asset could not be set")
     enable_ldr_color_grading_lut = (
         "Enable LDR color grading LUT set",
-        "Enable LDR color grading LUT could not be set")
+        "P0: Enable LDR color grading LUT could not be set")
     entity_deleted = (
         "Entity deleted",
-        "Entity was not deleted")
+        "P0: Entity was not deleted")
     deletion_undo = (
         "UNDO deletion success",
-        "UNDO deletion failed")
+        "P0: UNDO deletion failed")
     deletion_redo = (
         "REDO deletion success",
-        "REDO deletion failed")
+        "P0: REDO deletion failed")
+    override_defaults = (
+        "Override Defaults property set",
+        "P1: Override Defaults property failed to be set correctly")
+    alter_surround = (
+        "Alter Surround property set",
+        "P1: Alter Surround property failed to be set correctly")
+    alter_desaturation = (
+        "Alter Desaturation property set",
+        "P1: Alter Desaturation property failed to be set correctly")
+    alter_cat = (
+        "Alter CAT D60 to D65 property set",
+        "P1: Alter CAT D60 to D65 property failed to be set correctly")
+    black_level_min = (
+        "Cinema Limit (black) property set to minimum value",
+        "P1: Cinema Limit (black) property failed to take minimum value")
+    black_level_max = (
+        "Cinema Limit (black) property set to maximum value",
+        "P1: Cinema Limit (black) property failed to take maximum value")
+    white_level_min = (
+        "Cinema Limit (white) property set to minimum value",
+        "P1: Cinema Limit (white) property failed to take minimum value")
+    white_level_max = (
+        "Cinema Limit (white) property set to maximum value",
+        "P1: Cinema Limit (white) property failed to take maximum value")
+    luminance_level_min = (
+        "Min Point (luminance) property set",
+        "P1: Min Point (luminance) property failed to set expected value")
+    luminance_level_mid = (
+        "Mid Point (luminance) property set",
+        "P1: Mid Point (luminance) property failed to set expected value")
+    luminance_level_max = (
+        "Max Point (luminance) property set",
+        "P1: Max Point (luminance) property failed to set expected value")
+    surround_gamma = (
+        "Surround Gamma property set",
+        "P1: Surround Gamma property failed to set expected value")
+    gamma = (
+        "Gamma property set",
+        "P1: Gamma property failed to set expected value")
+    display_mapper_type = (
+        "Display Mapper Operation Type is correctly set",
+        "P1: Display Mapper Operation type is not as expected")
+
+
+# IsClose tolerance defaults to , 1e-9, but float values in some tests need a looser tolerance
+TOLERANCE = 1e-6
 
 
 def AtomEditorComponents_DisplayMapper_AddedToEntity():
@@ -67,25 +113,41 @@ def AtomEditorComponents_DisplayMapper_AddedToEntity():
     3) UNDO the entity creation and component addition.
     4) REDO the entity creation and component addition.
     5) Set LDR color Grading LUT asset.
-    6) Set Enable LDR color grading LUT property True
-    7) Enter/Exit game mode.
-    8) Test IsHidden.
-    9) Test IsVisible.
-    10) Delete Display Mapper entity.
-    11) UNDO deletion.
-    12) REDO deletion.
-    13) Look for errors and asserts.
+    6) Set the Display Mapper Operation Type enumerated in DISPLAY_MAPPER_OPERATION_TYPE for each type
+    7) Set Enable LDR color grading LUT property True
+    8) Toggle Override Defaults
+    9) Toggle Alter Surround
+    10) Toggle Alter Desaturation
+    11) Toggle 'Alter CAT D60 to D65'
+    12) Set 'Cinema Limit (black)' max value which is dynamic based on Cinema Limit (white) then min value
+    13) Set 'Cinema Limit (white)' max value then min, and finally back to default
+    14) Set 'Min Point (luminance)' to high and low value
+    15) Set 'Mid Point (luminance)' to high and low value then set default
+    16) Set 'Max Point (luminance)' to high and low value then set default
+    17) Set 'Surround Gamma' to high and low value
+    18) Set 'Gamma' to high and low value
+    19) Enter/Exit game mode.
+    20) Select and load each preset
+    21) Test IsHidden.
+    22) Test IsVisible.
+    23) Delete Display Mapper entity.
+    24) UNDO deletion.
+    25) REDO deletion.
+    26) Look for errors and asserts.
 
     :return: None
     """
     import os
 
+    import azlmbr.bus as bus
     import azlmbr.legacy.general as general
+    import azlmbr.render as render
 
+    from azlmbr.math import Math_IsClose
     from editor_python_test_tools.asset_utils import Asset
     from editor_python_test_tools.editor_entity_utils import EditorEntity
     from editor_python_test_tools.utils import Report, Tracer, TestHelper
-    from Atom.atom_utils.atom_constants import AtomComponentProperties
+    from Atom.atom_utils.atom_constants import AtomComponentProperties, DISPLAY_MAPPER_PRESET, DISPLAY_MAPPER_OPERATION_TYPE
 
     with Tracer() as error_tracer:
         # Test setup begins.
@@ -129,52 +191,263 @@ def AtomEditorComponents_DisplayMapper_AddedToEntity():
         Report.result(Tests.creation_redo, display_mapper_entity.exists())
 
         # 5. Set LDR color Grading LUT asset.
-        display_mapper_asset_path = os.path.join("TestData", "test.lightingpreset.azasset")
+        display_mapper_asset_path = os.path.join("LookupTables", "LUT_Sepia.azasset")
         display_mapper_asset = Asset.find_asset_by_path(display_mapper_asset_path, False)
         display_mapper_component.set_component_property_value(
-            AtomComponentProperties.display_mapper("LDR color Grading LUT"), display_mapper_asset.id)
+            AtomComponentProperties.display_mapper('LDR color Grading LUT'), display_mapper_asset.id)
         Report.result(
             Tests.ldr_color_grading_lut,
             display_mapper_component.get_component_property_value(
-                AtomComponentProperties.display_mapper("LDR color Grading LUT")) == display_mapper_asset.id)
+                AtomComponentProperties.display_mapper('LDR color Grading LUT')) == display_mapper_asset.id)
+
+        for operation_type in DISPLAY_MAPPER_OPERATION_TYPE.keys():
+            # 6. Set the Display Mapper Operation Type enumerated in DISPLAY_MAPPER_OPERATION_TYPE for each type
+            # Type property cannot be set currently. as a workaround we are calling an ebus to set the operation type
+            # A fix is in progress
+            # display_mapper_component.set_component_property_value(
+            #     AtomComponentProperties.display_mapper('Type'), DISPLAY_MAPPER_OPERATION_TYPE[operation_type])
+            render.DisplayMapperComponentRequestBus(
+                bus.Broadcast, "SetDisplayMapperOperationType", DISPLAY_MAPPER_OPERATION_TYPE[operation_type])
+            general.idle_wait_frames(3)
+            set_type = render.DisplayMapperComponentRequestBus(bus.Broadcast, "GetDisplayMapperOperationType")
+            Report.info(f"DiplayMapperOperationType: {set_type}")
+            Report.result(Tests.display_mapper_type, set_type == DISPLAY_MAPPER_OPERATION_TYPE[operation_type])
+
+            # 7. Set Enable LDR color grading LUT property True
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Enable LDR color grading LUT'), True)
+            Report.result(
+                Tests.enable_ldr_color_grading_lut,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Enable LDR color grading LUT')) is True)
+
+            # 8. Toggle Override Defaults
+            # Set Override Defaults to False
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Override Defaults'), False)
+            Report.result(
+                Tests.override_defaults,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Override Defaults')) is False)
+
+            # Set Override Defaults to True
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Override Defaults'), True)
+            Report.result(
+                Tests.override_defaults,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Override Defaults')) is True)
+
+            # 9. Toggle Alter Surround
+            # Set Alter Surround to True
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Alter Surround'), True)
+            Report.result(
+                Tests.alter_surround,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Alter Surround')) is True)
+
+            # Set Alter Surround to False
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Alter Surround'), False)
+            Report.result(
+                Tests.alter_surround,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Alter Surround')) is False)
+
+            # 10. Toggle Alter Desaturation
+            # Set Alter Desaturation to True
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Alter Desaturation'), True)
+            Report.result(
+                Tests.alter_desaturation,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Alter Desaturation')) is True)
+
+            # Set Alter Desaturation to False
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Alter Desaturation'), False)
+            Report.result(
+                Tests.alter_desaturation,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Alter Desaturation')) is False)
+
+            # 11. Toggle 'Alter CAT D60 to D65'
+            # Set 'Alter CAT D60 to D65' to True
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Alter CAT D60 to D65'), True)
+            Report.result(
+                Tests.alter_cat,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Alter CAT D60 to D65')) is True)
+
+            # Set 'Alter CAT D60 to D65' to False
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Alter CAT D60 to D65'), False)
+            Report.result(
+                Tests.alter_cat,
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Alter CAT D60 to D65')) is False)
+
+            general.idle_wait_frames(1)
+
+            # 12. Set 'Cinema Limit (black)' max value which is dynamic based on Cinema Limit (white) then min value
+            # set max value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (black)'), value=48.0)
+            Report.result(Tests.black_level_max, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (black)')), 48.0, TOLERANCE))
+
+            # set min value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (black)'), value=0.02)
+            Report.result(Tests.black_level_min, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (black)')), 0.02, TOLERANCE))
+
+            # 13. Set 'Cinema Limit (white)' maximum value then min, and finally back to default
+            # set max value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (white)'), value=4000.0)
+            Report.result(Tests.white_level_max, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (white)')), 4000.0, TOLERANCE))
+
+            # Set min value which is dynamic based on Cinema Limit (black)
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (white)'), value=0.02)
+            Report.result(Tests.white_level_min, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (white)')), 0.02, TOLERANCE))
+
+            # Reset this to the default 48 so following cycles don't impact Cinema Limit (Black)
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Cinema Limit (white)'), value=48.0)
+
+            # 14. Set 'Min Point (luminance)' to high and low value
+            # set high value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Min Point (luminance)'), value=4.8)
+            Report.info(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Min Point (luminance)')))
+            Report.result(Tests.luminance_level_min, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Min Point (luminance)')), 4.8, TOLERANCE))
+
+            # set low value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Min Point (luminance)'), value=0.002)
+            Report.result(Tests.luminance_level_min, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Min Point (luminance)')), 0.002, TOLERANCE))
+
+            # 15. Set 'Mid Point (luminance)' to high and low value then set default
+            # set high value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Mid Point (luminance)'), value=1005.0)
+            Report.result(Tests.luminance_level_mid, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Mid Point (luminance)')), 1005.0, TOLERANCE))
+
+            # set low value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Mid Point (luminance)'), value=0.002)
+            Report.result(Tests.luminance_level_mid, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Mid Point (luminance)')), 0.002, TOLERANCE))
+
+            # restore the default since as this impacts the range of 'Min Point (luminance)'
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Mid Point (luminance)'), value=4.8)
+
+            # 16. Set 'Max Point (luminance)' to high and low value then set default
+            # set a high value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Max Point (luminance)'), value=4000.0)
+            Report.result(Tests.luminance_level_max, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Max Point (luminance)')), 4000.0, TOLERANCE))
+
+            # set a low value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Max Point (luminance)'), value=0.002)
+            Report.result(Tests.luminance_level_max, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Max Point (luminance)')), 0.002, TOLERANCE))
+
+            # restore the default since this impacts the range of 'Mid Point (luminance)'
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Max Point (luminance)'), value=1005.7191162)
+
+            # 17. Set 'Surround Gamma' to high and low value
+            # set a high value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Surround Gamma'), value=1.2)
+            Report.result(Tests.surround_gamma, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Surround Gamma')), 1.2, TOLERANCE))
+
+            # set a low value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Surround Gamma'), value=0.6)
+            Report.result(Tests.surround_gamma, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Surround Gamma')), 0.6, TOLERANCE))
+
+            # 18. Set 'Gamma' to high and low value
+            # set a high value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Gamma'), value=4.0)
+            Report.result(Tests.gamma, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Gamma')), 4.0, TOLERANCE))
+
+            # set a low value
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Gamma'), value=0.2)
+            Report.result(Tests.gamma, Math_IsClose(display_mapper_component.get_component_property_value(
+                AtomComponentProperties.display_mapper('Gamma')), 0.2, TOLERANCE))
+
+            # 19. Enter/Exit game mode.
+            TestHelper.enter_game_mode(Tests.enter_game_mode)
+            general.idle_wait_frames(1)
+            TestHelper.exit_game_mode(Tests.exit_game_mode)
+
+            display_mapper_component.set_component_property_value(
+                AtomComponentProperties.display_mapper('Enable LDR color grading LUT'), False)
 
-        # 6. Set Enable LDR color grading LUT property True
         display_mapper_component.set_component_property_value(
             AtomComponentProperties.display_mapper('Enable LDR color grading LUT'), True)
-        Report.result(
-            Tests.enable_ldr_color_grading_lut,
-            display_mapper_component.get_component_property_value(
-                AtomComponentProperties.display_mapper('Enable LDR color grading LUT')) is True)
 
-        # 7. Enter/Exit game mode.
-        TestHelper.enter_game_mode(Tests.enter_game_mode)
-        general.idle_wait_frames(1)
-        TestHelper.exit_game_mode(Tests.exit_game_mode)
+        cinema_limit_white_presets = [48.0, 184.3200073, 368.6400146, 737.2800293]
+        for preset in DISPLAY_MAPPER_PRESET.keys():
+            # 20. Select and load each preset
+            # Preset Selection cannot be set or loaded currently; as a workaround we are calling an ebus to load preset
+            # A fix is in progress
+            # display_mapper_component.set_component_property_value(
+            #     AtomComponentProperties.display_mapper('Preset Selection'), DISPLAY_MAPPER_PRESET[preset])
+            render.DisplayMapperComponentRequestBus(bus.Broadcast, "LoadPreset", DISPLAY_MAPPER_PRESET[preset])
+            general.idle_wait_frames(1)
+            # check some value to confirm preset loaded
+            test_preset = (f"Preset {preset} loaded expected value",
+                           f"P1: Preset {preset} failed to load values as expected")
+            Report.result(test_preset, Math_IsClose(
+                display_mapper_component.get_component_property_value(
+                    AtomComponentProperties.display_mapper('Cinema Limit (white)')),
+                cinema_limit_white_presets[DISPLAY_MAPPER_PRESET[preset]], TOLERANCE))
 
-        # 8. Test IsHidden.
+        # 21. Test IsHidden.
         display_mapper_entity.set_visibility_state(False)
         Report.result(Tests.is_hidden, display_mapper_entity.is_hidden() is True)
 
-        # 9. Test IsVisible.
+        # 22. Test IsVisible.
         display_mapper_entity.set_visibility_state(True)
         general.idle_wait_frames(1)
         Report.result(Tests.is_visible, display_mapper_entity.is_visible() is True)
 
-        # 10. Delete Display Mapper entity.
+        # 23. Delete Display Mapper entity.
         display_mapper_entity.delete()
         Report.result(Tests.entity_deleted, not display_mapper_entity.exists())
 
-        # 11. UNDO deletion.
+        # 24. UNDO deletion.
         general.undo()
         general.idle_wait_frames(1)
         Report.result(Tests.deletion_undo, display_mapper_entity.exists())
 
-        # 12. REDO deletion.
+        # 25. REDO deletion.
         general.redo()
         general.idle_wait_frames(1)
         Report.result(Tests.deletion_redo, not display_mapper_entity.exists())
 
-        # 13. Look for errors and asserts.
+        # 26. Look for errors and asserts.
         TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
         for error_info in error_tracer.errors:
             Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")

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

@@ -5,14 +5,8 @@ For complete copyright and license terms please see the LICENSE at the root of t
 SPDX-License-Identifier: Apache-2.0 OR MIT
 """
 
-import os
-import sys
-
 import azlmbr.legacy.general as general
 
-sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
-
-import editor_python_test_tools.hydra_editor_utils as hydra
 from editor_python_test_tools.editor_test_helper import EditorTestHelper
 from Atom.atom_utils.benchmark_utils import BenchmarkHelper
 

+ 1 - 1
AutomatedTesting/Gem/PythonTests/EditorPythonBindings/LevelComponentCommands_test_case.py

@@ -128,7 +128,7 @@ if len(sys.argv) > 1:
 
 # Open a level (any level should work)
 general.create_level_no_prompt('LevelComponentTest', 128, 1, 512, True)
-# Make sure the default slices get a chance to initialize.
+# Make sure the default prefabs get a chance to initialize.
 general.idle_wait(1.0)
 
 # Generate List of Component Types

+ 27 - 2
AutomatedTesting/Gem/PythonTests/Multiplayer/TestSuite_Main.py

@@ -8,10 +8,19 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
 
 import pytest
 import os
-import sys
 from ly_test_tools.o3de.editor_test import EditorTestSuite, EditorSingleTest
 
-sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared')
+
+# Saves the level cache folder.
+# These artifacts will be saved in the test results so developers can access the level assets
+# to debug should the test ever fail.
+def save_multiplayer_level_cache_folder_artifact(workspace, multiplayer_level):
+    level_cache_folder_path = os.path.join(workspace.paths.platform_cache(), "levels", "multiplayer", multiplayer_level)
+
+    if os.path.exists(level_cache_folder_path):
+        workspace.artifact_manager.save_artifact(level_cache_folder_path)
+    else:
+        pytest.fail(f"Failed to find level asset cache for '{multiplayer_level}', located here: '{level_cache_folder_path}'! Make sure AssetProcessor successfully built the level.")
 
 @pytest.mark.SUITE_main
 @pytest.mark.parametrize("project", ["AutomatedTesting"])
@@ -20,12 +29,28 @@ class TestAutomation(EditorTestSuite):
     class test_Multiplayer_AutoComponent_NetworkInput(EditorSingleTest):
         from .tests import Multiplayer_AutoComponent_NetworkInput as test_module
 
+        @classmethod
+        def setup(cls, instance, request, workspace, editor, editor_test_results, launcher_platform):
+            save_multiplayer_level_cache_folder_artifact(workspace, "autocomponent_networkinput")
+
     class test_Multiplayer_AutoComponent_RPC(EditorSingleTest):
         from .tests import Multiplayer_AutoComponent_RPC as test_module
 
+        @classmethod
+        def setup(cls, instance, request, workspace, editor, editor_test_results, launcher_platform):
+            save_multiplayer_level_cache_folder_artifact(workspace, "autocomponent_rpc")
+
     class test_Multiplayer_BasicConnectivity_Connects(EditorSingleTest):
         from .tests import Multiplayer_BasicConnectivity_Connects as test_module
 
+        @classmethod
+        def setup(cls, instance, request, workspace, editor, editor_test_results, launcher_platform):
+            save_multiplayer_level_cache_folder_artifact(workspace, "basicconnectivity_connects")
+
     class test_Multiplayer_SimpleNetworkLevelEntity(EditorSingleTest):
         from .tests import Multiplayer_SimpleNetworkLevelEntity as test_module
 
+        @classmethod
+        def setup(cls, instance, request, workspace, editor, editor_test_results, launcher_platform):
+            save_multiplayer_level_cache_folder_artifact(workspace, "simplenetworklevelentity")
+

+ 8 - 8
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests.py

@@ -674,14 +674,14 @@ class TestsAssetProcessorBatch_AllPlatforms(object):
 
     @pytest.mark.BAT
     @pytest.mark.assetpipeline
-    @pytest.mark.skip(reason="update assets from .slice to a different type to test preload cyclical dependencies")
+    @pytest.mark.skip(reason="GHI: 8,365 Update assets from .prefab to a different type to test preload cyclical dependencies")
     def test_validateDirectPreloadDependency_Found(self, asset_processor, ap_setup_fixture, workspace):
         """
         Tests processing an asset with a circular dependency and verifies that Asset Processor will return an error
         notifying the user about a circular dependency.
 
         Test Steps:
-        1. Create test environment with an asset that has a circular dependency
+        1. Create test environment with an asset that has a preload circular dependency
         2. Launch asset processor
         3. Verify that error is returned informing the user that the asset has a circular dependency
         """
@@ -692,23 +692,23 @@ class TestsAssetProcessorBatch_AllPlatforms(object):
 
         success, output = asset_processor.batch_process(capture_output=True, expect_failure=False)
         log = APOutputParser(output)
-        for _ in log.get_lines(-1, ["Preload circular dependency detected", "testc.dynamicslice"]):
+        for _ in log.get_lines(-1, ["Preload circular dependency detected", "testc.prefab"]):
             error_line_found = True
 
         assert error_line_found, "The error could not be found in the newest run of the AP Batch log."
 
     @pytest.mark.BAT
     @pytest.mark.assetpipeline
-    @pytest.mark.skip(reason="need to change assets from .slice files to an asset type that can have nested dependencies")
+    @pytest.mark.skip(reason="GHI: 8,365 Update assets from .prefab to an asset type that can have nested preload dependencies")
     def test_validateNestedPreloadDependency_Found(self, asset_processor, ap_setup_fixture, workspace):
         """
-        Tests processing of a nested circular dependency and verifies that Asset Processor will return an error
+        Tests processing of a nested preload circular dependency and verifies that Asset Processor will return an error
         notifying the user about a circular dependency.
 
         Test Steps:
-        1. Create test environment with an asset that has a nested circular dependency
+        1. Create test environment with an asset that has a nested preload circular dependency
         2. Launch asset processor
-        3. Verify that error is returned informing the user that the asset has a circular dependency
+        3. Verify that error is returned informing the user that the asset has a preload circular dependency
         """
 
         env = ap_setup_fixture
@@ -718,7 +718,7 @@ class TestsAssetProcessorBatch_AllPlatforms(object):
 
         success, output = asset_processor.batch_process(capture_output=True, expect_failure=False)
         log = APOutputParser(output)
-        for _ in log.get_lines(-1, ["Preload circular dependency detected", "testa.dynamicslice"]):
+        for _ in log.get_lines(-1, ["Preload circular dependency detected", "testa.prefab"]):
             error_line_found = True
 
         assert error_line_found, "The error could not be found in the newest run of the AP Batch log."

+ 0 - 174
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/assets_with_direct_preload_dependency/TestC.slice

@@ -1,174 +0,0 @@
-<ObjectStream version="3">
-	<Class name="AZ::Entity" 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="1295506446949" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		</Class>
-		<Class name="AZStd::string" field="Name" value="Slice" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		<Class name="AZStd::vector" 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="15843242153155423542" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-				<Class name="AZStd::vector" 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="1304096381541" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-						</Class>
-						<Class name="AZStd::string" field="Name" value="TestC" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-						<Class name="AZStd::vector" 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="7006315855742782669" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="bool" field="IsEditorOnly" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="TransformComponent" field="element" version="9" type="{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0}">
-								<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="3584527199662731007" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="EntityId" field="Parent Entity" 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="EditorTransform" field="Transform Data" version="2" type="{B02B7063-D238-4F40-A724-405F7A6D68CB}">
-									<Class name="Vector3" field="Translate" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
-									<Class name="Vector3" field="Rotate" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
-									<Class name="Vector3" field="Scale" value="1.0000000 1.0000000 1.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
-									<Class name="bool" field="Locked" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								</Class>
-								<Class name="Transform" field="Cached World Transform" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000" type="{5D9958E9-9F1E-4985-B532-FFFDE75FEDFD}"/>
-								<Class name="EntityId" field="Cached World Transform Parent" 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="unsigned int" field="Parent Activation Transform Mode" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-								<Class name="bool" field="IsStatic" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								<Class name="bool" field="Sync Enabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								<Class name="unsigned int" field="InterpolatePosition" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-								<Class name="unsigned int" field="InterpolateRotation" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-							</Class>
-							<Class name="EditorInspectorComponent" field="element" version="2" type="{47DE3DDA-50C5-4F50-B1DB-BA4AE66AB056}">
-								<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="7706925336429309894" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="ComponentOrderEntryArray" type="{B6EFED5B-19B4-5084-9D92-42DECCE83872}">
-									<Class name="ComponentOrderEntry" field="element" version="1" type="{335C5861-5197-4DD5-A766-EF2B551B0D9D}">
-										<Class name="AZ::u64" field="ComponentId" value="3584527199662731007" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-										<Class name="AZ::u64" field="SortIndex" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-									<Class name="ComponentOrderEntry" field="element" version="1" type="{335C5861-5197-4DD5-A766-EF2B551B0D9D}">
-										<Class name="AZ::u64" field="ComponentId" value="251416810686704101" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-										<Class name="AZ::u64" field="SortIndex" value="1" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-							</Class>
-							<Class name="EditorEntitySortComponent" field="element" version="2" type="{6EA1E03D-68B2-466D-97F7-83998C8C27F0}">
-								<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="2232445749633468678" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="ChildEntityOrderEntryArray" type="{BE163120-C1ED-5F69-A650-DC2528A8FF94}"/>
-							</Class>
-							<Class name="SelectionComponent" field="element" type="{73B724FC-43D1-4C75-ACF5-79AA8A3BF89D}">
-								<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-									<Class name="AZ::u64" field="Id" value="5414135994254332294" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-								</Class>
-							</Class>
-							<Class name="EditorSpawnerComponent" field="element" version="1" type="{77CDE991-EC1A-B7C1-B112-7456ABAC81A1}">
-								<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-									<Class name="AZ::u64" field="Id" value="251416810686704101" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-								</Class>
-								<Class name="Asset" field="Slice" value="id={56FC3E9D-3FE4-592F-B6FF-8DF2EBD44B16}:2,type={78802ABF-9595-463A-8D2B-D022F906F9B1},hint={assets_with_direct_preload_dependency/testd.dynamicslice}" version="1" type="{77A19D40-8731-4D3C-9041-1B43047366A4}"/>
-								<Class name="bool" field="SpawnOnActivate" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								<Class name="bool" field="DestroyOnDeactivate" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="EditorVisibilityComponent" field="element" type="{88E08E78-5C2F-4943-9F73-C115E6FFAB43}">
-								<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="18139478027057937842" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="bool" field="VisibilityFlag" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="EditorLockComponent" field="element" type="{C3A169C9-7EFB-4D6C-8710-3591680D0936}">
-								<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="11193408165200254248" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="bool" field="Locked" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="EditorPendingCompositionComponent" field="element" type="{D40FCB35-153D-45B3-AF6D-7BA576D8AFBB}">
-								<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="7509785945442840634" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="PendingComponents" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"/>
-							</Class>
-							<Class name="EditorEntityIconComponent" field="element" type="{E15D42C2-912D-466F-9547-E7E948CE2D7D}">
-								<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="10935675379356727788" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AssetId" field="EntityIconAssetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-									<Class name="AZ::Uuid" field="guid" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-									<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-								</Class>
-							</Class>
-							<Class name="EditorDisabledCompositionComponent" field="element" type="{E77AE6AC-897D-4035-8353-637449B6DCFB}">
-								<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="17579734367307202992" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="DisabledComponents" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"/>
-							</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" 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="1299801414245" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-					</Class>
-					<Class name="AZStd::string" field="Name" value="No Asset Association" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-					<Class name="AZStd::vector" 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="11042881146501432583" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-							</Class>
-							<Class name="AZStd::set" field="AssociatedIds" type="{78E024C3-0143-53FC-B393-0675227839AF}">
-								<Class name="EntityId" field="element" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-									<Class name="AZ::u64" field="id" value="1304096381541" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-								</Class>
-							</Class>
-							<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" field="ChildrenIds" type="{6C8F8E52-AB4A-5C1F-8E56-9AC390290B94}"/>
-							<Class name="bool" field="PersistenceFlag" value="false" 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" 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>
-</ObjectStream>
-

+ 0 - 174
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/assets_with_direct_preload_dependency/TestD.slice

@@ -1,174 +0,0 @@
-<ObjectStream version="3">
-	<Class name="AZ::Entity" 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="382257329386" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		</Class>
-		<Class name="AZStd::string" field="Name" value="Slice" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		<Class name="AZStd::vector" 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="10124611306244674550" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-				<Class name="AZStd::vector" 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="390847263978" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-						</Class>
-						<Class name="AZStd::string" field="Name" value="TestB" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-						<Class name="AZStd::vector" 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="9595291727352692926" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="bool" field="IsEditorOnly" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="TransformComponent" field="element" version="9" type="{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0}">
-								<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="6918190889556026264" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="EntityId" field="Parent Entity" 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="EditorTransform" field="Transform Data" version="2" type="{B02B7063-D238-4F40-A724-405F7A6D68CB}">
-									<Class name="Vector3" field="Translate" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
-									<Class name="Vector3" field="Rotate" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
-									<Class name="Vector3" field="Scale" value="1.0000000 1.0000000 1.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
-									<Class name="bool" field="Locked" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								</Class>
-								<Class name="Transform" field="Cached World Transform" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000" type="{5D9958E9-9F1E-4985-B532-FFFDE75FEDFD}"/>
-								<Class name="EntityId" field="Cached World Transform Parent" 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="unsigned int" field="Parent Activation Transform Mode" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-								<Class name="bool" field="IsStatic" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								<Class name="bool" field="Sync Enabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								<Class name="unsigned int" field="InterpolatePosition" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-								<Class name="unsigned int" field="InterpolateRotation" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-							</Class>
-							<Class name="EditorInspectorComponent" field="element" version="2" type="{47DE3DDA-50C5-4F50-B1DB-BA4AE66AB056}">
-								<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="16488522651299490860" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="ComponentOrderEntryArray" type="{B6EFED5B-19B4-5084-9D92-42DECCE83872}">
-									<Class name="ComponentOrderEntry" field="element" version="1" type="{335C5861-5197-4DD5-A766-EF2B551B0D9D}">
-										<Class name="AZ::u64" field="ComponentId" value="6918190889556026264" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-										<Class name="AZ::u64" field="SortIndex" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-									<Class name="ComponentOrderEntry" field="element" version="1" type="{335C5861-5197-4DD5-A766-EF2B551B0D9D}">
-										<Class name="AZ::u64" field="ComponentId" value="1133009518516046488" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-										<Class name="AZ::u64" field="SortIndex" value="1" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-							</Class>
-							<Class name="EditorEntitySortComponent" field="element" version="2" type="{6EA1E03D-68B2-466D-97F7-83998C8C27F0}">
-								<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="6551321942498556777" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="ChildEntityOrderEntryArray" type="{BE163120-C1ED-5F69-A650-DC2528A8FF94}"/>
-							</Class>
-							<Class name="SelectionComponent" field="element" type="{73B724FC-43D1-4C75-ACF5-79AA8A3BF89D}">
-								<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-									<Class name="AZ::u64" field="Id" value="5168720242367005303" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-								</Class>
-							</Class>
-							<Class name="EditorSpawnerComponent" field="element" version="1" type="{77CDE991-EC1A-B7C1-B112-7456ABAC81A1}">
-								<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-									<Class name="AZ::u64" field="Id" value="1133009518516046488" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-								</Class>
-								<Class name="Asset" field="Slice" value="id={A4A3A611-18D0-536C-99D9-134A644AAA70}:2,type={78802ABF-9595-463A-8D2B-D022F906F9B1},hint={assets_with_direct_preload_dependency/testc.dynamicslice}" version="1" type="{77A19D40-8731-4D3C-9041-1B43047366A4}"/>
-								<Class name="bool" field="SpawnOnActivate" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								<Class name="bool" field="DestroyOnDeactivate" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="EditorVisibilityComponent" field="element" type="{88E08E78-5C2F-4943-9F73-C115E6FFAB43}">
-								<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="17020070072341888679" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="bool" field="VisibilityFlag" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="EditorLockComponent" field="element" type="{C3A169C9-7EFB-4D6C-8710-3591680D0936}">
-								<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="16300364923199181818" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="bool" field="Locked" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="EditorPendingCompositionComponent" field="element" type="{D40FCB35-153D-45B3-AF6D-7BA576D8AFBB}">
-								<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="3997039705476816210" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="PendingComponents" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"/>
-							</Class>
-							<Class name="EditorEntityIconComponent" field="element" type="{E15D42C2-912D-466F-9547-E7E948CE2D7D}">
-								<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="10323419800905366237" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AssetId" field="EntityIconAssetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-									<Class name="AZ::Uuid" field="guid" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-									<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-								</Class>
-							</Class>
-							<Class name="EditorDisabledCompositionComponent" field="element" type="{E77AE6AC-897D-4035-8353-637449B6DCFB}">
-								<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="2409852450700585411" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="DisabledComponents" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"/>
-							</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" 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="386552296682" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-					</Class>
-					<Class name="AZStd::string" field="Name" value="No Asset Association" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-					<Class name="AZStd::vector" 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="6483308780985076120" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-							</Class>
-							<Class name="AZStd::set" field="AssociatedIds" type="{78E024C3-0143-53FC-B393-0675227839AF}">
-								<Class name="EntityId" field="element" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-									<Class name="AZ::u64" field="id" value="390847263978" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-								</Class>
-							</Class>
-							<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" field="ChildrenIds" type="{6C8F8E52-AB4A-5C1F-8E56-9AC390290B94}"/>
-							<Class name="bool" field="PersistenceFlag" value="false" 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" 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>
-</ObjectStream>
-

+ 0 - 222
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/assets_with_nested_preload_dependency/TestA.slice

@@ -1,222 +0,0 @@
-<ObjectStream version="3">
-	<Class name="AZ::Entity" type="{75651658-8663-478D-9090-2432DFCAFA44}" version="2">
-		<Class field="Id" name="EntityId" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}" version="1">
-			<Class field="id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="269594828358" />
-		</Class>
-		<Class field="Name" name="AZStd::string" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}" value="Slice" />
-		<Class field="Components" name="AZStd::vector" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
-			<Class field="element" name="SliceComponent" type="{AFD304E4-1773-47C8-855A-8B622398934F}" version="3">
-				<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-					<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="13642727600084297375" />
-				</Class>
-				<Class field="Entities" name="AZStd::vector" type="{21786AF0-2606-5B9A-86EB-0892E2820E6C}">
-					<Class field="element" name="AZ::Entity" type="{75651658-8663-478D-9090-2432DFCAFA44}" version="2">
-						<Class field="Id" name="EntityId" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}" version="1">
-							<Class field="id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="278184762950" />
-						</Class>
-						<Class field="Name" name="AZStd::string" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}" value="TestE" />
-						<Class field="Components" name="AZStd::vector" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
-							<Class field="element" name="EditorOnlyEntityComponent" type="{22A16F1D-6D49-422D-AAE9-91AE45B5D3E7}">
-								<Class field="BaseClass1" name="EditorComponentBase" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}" version="1">
-									<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-										<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="16738199190794244171" />
-									</Class>
-								</Class>
-								<Class field="IsEditorOnly" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-							</Class>
-							<Class field="element" name="TransformComponent" type="{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0}" version="9">
-								<Class field="BaseClass1" name="EditorComponentBase" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}" version="1">
-									<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-										<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="16210900323787785224" />
-									</Class>
-								</Class>
-								<Class field="Parent Entity" name="EntityId" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}" version="1">
-									<Class field="id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="4294967295" />
-								</Class>
-								<Class field="Transform Data" name="EditorTransform" type="{B02B7063-D238-4F40-A724-405F7A6D68CB}" version="2">
-									<Class field="Translate" name="Vector3" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}" value="0.0000000 0.0000000 0.0000000" />
-									<Class field="Rotate" name="Vector3" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}" value="0.0000000 0.0000000 0.0000000" />
-									<Class field="Scale" name="Vector3" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}" value="1.0000000 1.0000000 1.0000000" />
-									<Class field="Locked" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-								</Class>
-								<Class field="Cached World Transform" name="Transform" type="{5D9958E9-9F1E-4985-B532-FFFDE75FEDFD}" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000" />
-								<Class field="Cached World Transform Parent" name="EntityId" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}" version="1">
-									<Class field="id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="4294967295" />
-								</Class>
-								<Class field="Parent Activation Transform Mode" name="unsigned int" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}" value="0" />
-								<Class field="IsStatic" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-								<Class field="Sync Enabled" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-								<Class field="InterpolatePosition" name="unsigned int" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}" value="0" />
-								<Class field="InterpolateRotation" name="unsigned int" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}" value="0" />
-							</Class>
-							<Class field="element" name="EditorInspectorComponent" type="{47DE3DDA-50C5-4F50-B1DB-BA4AE66AB056}" version="2">
-								<Class field="BaseClass1" name="EditorComponentBase" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}" version="1">
-									<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-										<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="7735546012552452863" />
-									</Class>
-								</Class>
-								<Class field="ComponentOrderEntryArray" name="AZStd::vector" type="{B6EFED5B-19B4-5084-9D92-42DECCE83872}">
-									<Class field="element" name="ComponentOrderEntry" type="{335C5861-5197-4DD5-A766-EF2B551B0D9D}" version="1">
-										<Class field="ComponentId" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="16210900323787785224" />
-										<Class field="SortIndex" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="0" />
-									</Class>
-									<Class field="element" name="ComponentOrderEntry" type="{335C5861-5197-4DD5-A766-EF2B551B0D9D}" version="1">
-										<Class field="ComponentId" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="4070968465717414181" />
-										<Class field="SortIndex" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="1" />
-									</Class>
-									<Class field="element" name="ComponentOrderEntry" type="{335C5861-5197-4DD5-A766-EF2B551B0D9D}" version="1">
-										<Class field="ComponentId" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="8906495340202656540" />
-										<Class field="SortIndex" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="2" />
-									</Class>
-								</Class>
-							</Class>
-							<Class field="element" name="EditorEntitySortComponent" type="{6EA1E03D-68B2-466D-97F7-83998C8C27F0}" version="2">
-								<Class field="BaseClass1" name="EditorComponentBase" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}" version="1">
-									<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-										<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="9760814841523354339" />
-									</Class>
-								</Class>
-								<Class field="ChildEntityOrderEntryArray" name="AZStd::vector" type="{BE163120-C1ED-5F69-A650-DC2528A8FF94}" />
-							</Class>
-							<Class field="element" name="SelectionComponent" type="{73B724FC-43D1-4C75-ACF5-79AA8A3BF89D}">
-								<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-									<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="8339376805608654145" />
-								</Class>
-							</Class>
-							<Class field="element" name="EditorSpawnerComponent" type="{77CDE991-EC1A-B7C1-B112-7456ABAC81A1}" version="1">
-								<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-									<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="4070968465717414181" />
-								</Class>
-								<Class field="Slice" name="Asset" type="{77A19D40-8731-4D3C-9041-1B43047366A4}" value="id={F6621671-E624-53B1-BEB8-EB028B777B4C}:2,type={78802ABF-9595-463A-8D2B-D022F906F9B1},hint={assets_with_nested_preload_dependency/testd.dynamicslice}" version="1" />
-								<Class field="SpawnOnActivate" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-								<Class field="DestroyOnDeactivate" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-							</Class>
-							<Class field="element" name="EditorVisibilityComponent" type="{88E08E78-5C2F-4943-9F73-C115E6FFAB43}">
-								<Class field="BaseClass1" name="EditorComponentBase" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}" version="1">
-									<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-										<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="10678724437556014335" />
-									</Class>
-								</Class>
-								<Class field="VisibilityFlag" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="true" />
-							</Class>
-							<Class field="element" name="EditorActorComponent" type="{A863EE1B-8CFD-4EDD-BA0D-1CEC2879AD44}" version="4">
-								<Class field="BaseClass1" name="EditorComponentBase" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}" version="1">
-									<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-										<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="8906495340202656540" />
-									</Class>
-								</Class>
-								<Class field="ActorAsset" name="Asset" type="{77A19D40-8731-4D3C-9041-1B43047366A4}" value="id={58BE9DA5-1F17-53B9-8CEE-EEB10E63454D}:914f19b7,type={F67CC648-EA51-464C-9F5D-4A9CE41A7F86},hint={objects/characters/jack/jack.actor}" version="1" />
-								<Class field="MaterialPerLOD" name="AZStd::vector" type="{BB800BD1-3E2D-5089-8423-F400597960FF}">
-									<Class field="element" name="AzFramework::SimpleAssetReference&lt;LmbrCentral::MaterialAsset&gt;" type="{B7B8ECC7-FF89-4A76-A50E-4C6CA2B6E6B4}" version="1">
-										<Class field="BaseClass1" name="SimpleAssetReferenceBase" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}" version="1">
-											<Class field="AssetPath" name="AZStd::string" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}" value="objects/characters/jack/jack.mtl" />
-										</Class>
-									</Class>
-									<Class field="element" name="AzFramework::SimpleAssetReference&lt;LmbrCentral::MaterialAsset&gt;" type="{B7B8ECC7-FF89-4A76-A50E-4C6CA2B6E6B4}" version="1">
-										<Class field="BaseClass1" name="SimpleAssetReferenceBase" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}" version="1">
-											<Class field="AssetPath" name="AZStd::string" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}" value="objects/characters/jack/jack.mtl" />
-										</Class>
-									</Class>
-									<Class field="element" name="AzFramework::SimpleAssetReference&lt;LmbrCentral::MaterialAsset&gt;" type="{B7B8ECC7-FF89-4A76-A50E-4C6CA2B6E6B4}" version="1">
-										<Class field="BaseClass1" name="SimpleAssetReferenceBase" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}" version="1">
-											<Class field="AssetPath" name="AZStd::string" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}" value="objects/characters/jack/jack.mtl" />
-										</Class>
-									</Class>
-									<Class field="element" name="AzFramework::SimpleAssetReference&lt;LmbrCentral::MaterialAsset&gt;" type="{B7B8ECC7-FF89-4A76-A50E-4C6CA2B6E6B4}" version="1">
-										<Class field="BaseClass1" name="SimpleAssetReferenceBase" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}" version="1">
-											<Class field="AssetPath" name="AZStd::string" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}" value="objects/characters/jack/jack.mtl" />
-										</Class>
-									</Class>
-								</Class>
-								<Class field="MaterialPerActor" name="AzFramework::SimpleAssetReference&lt;LmbrCentral::MaterialAsset&gt;" type="{B7B8ECC7-FF89-4A76-A50E-4C6CA2B6E6B4}" version="1">
-									<Class field="BaseClass1" name="SimpleAssetReferenceBase" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}" version="1">
-										<Class field="AssetPath" name="AZStd::string" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}" value="objects/characters/jack/jack.mtl" />
-									</Class>
-								</Class>
-								<Class field="AttachmentType" name="unsigned int" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}" value="0" />
-								<Class field="AttachmentTarget" name="EntityId" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}" version="1">
-									<Class field="id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="4294967295" />
-								</Class>
-								<Class field="RenderSkeleton" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-								<Class field="RenderCharacter" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="true" />
-								<Class field="RenderBounds" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-								<Class field="SkinningMethod" name="unsigned int" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}" value="0" />
-								<Class field="UpdateJointTransformsWhenOutOfView" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-								<Class field="LodLevel" name="unsigned int" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}" value="0" />
-							</Class>
-							<Class field="element" name="EditorLockComponent" type="{C3A169C9-7EFB-4D6C-8710-3591680D0936}">
-								<Class field="BaseClass1" name="EditorComponentBase" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}" version="1">
-									<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-										<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="2755228366872136502" />
-									</Class>
-								</Class>
-								<Class field="Locked" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-							</Class>
-							<Class field="element" name="EditorPendingCompositionComponent" type="{D40FCB35-153D-45B3-AF6D-7BA576D8AFBB}">
-								<Class field="BaseClass1" name="EditorComponentBase" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}" version="1">
-									<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-										<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="2364131805451940550" />
-									</Class>
-								</Class>
-								<Class field="PendingComponents" name="AZStd::vector" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}" />
-							</Class>
-							<Class field="element" name="EditorEntityIconComponent" type="{E15D42C2-912D-466F-9547-E7E948CE2D7D}">
-								<Class field="BaseClass1" name="EditorComponentBase" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}" version="1">
-									<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-										<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="15019118415351685531" />
-									</Class>
-								</Class>
-								<Class field="EntityIconAssetId" name="AssetId" type="{652ED536-3402-439B-AEBE-4A5DBC554085}" version="1">
-									<Class field="guid" name="AZ::Uuid" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}" value="{00000000-0000-0000-0000-000000000000}" />
-									<Class field="subId" name="unsigned int" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}" value="0" />
-								</Class>
-							</Class>
-							<Class field="element" name="EditorDisabledCompositionComponent" type="{E77AE6AC-897D-4035-8353-637449B6DCFB}">
-								<Class field="BaseClass1" name="EditorComponentBase" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}" version="1">
-									<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-										<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="12728572968760191789" />
-									</Class>
-								</Class>
-								<Class field="DisabledComponents" name="AZStd::vector" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}" />
-							</Class>
-						</Class>
-						<Class field="IsDependencyReady" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="true" />
-						<Class field="IsRuntimeActive" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="true" />
-					</Class>
-				</Class>
-				<Class field="Prefabs" name="AZStd::list" type="{DAD45EB6-5853-5645-B762-3A37F8775E12}" />
-				<Class field="IsDynamic" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="true" />
-				<Class field="MetadataEntity" name="AZ::Entity" type="{75651658-8663-478D-9090-2432DFCAFA44}" version="2">
-					<Class field="Id" name="EntityId" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}" version="1">
-						<Class field="id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="273889795654" />
-					</Class>
-					<Class field="Name" name="AZStd::string" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}" value="No Asset Association" />
-					<Class field="Components" name="AZStd::vector" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
-						<Class field="element" name="SliceMetadataInfoComponent" type="{25EE4D75-8A17-4449-81F4-E561005BAABD}" version="2">
-							<Class field="BaseClass1" name="AZ::Component" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-								<Class field="Id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="1605466577178627956" />
-							</Class>
-							<Class field="AssociatedIds" name="AZStd::set" type="{78E024C3-0143-53FC-B393-0675227839AF}">
-								<Class field="element" name="EntityId" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}" version="1">
-									<Class field="id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="278184762950" />
-								</Class>
-							</Class>
-							<Class field="ParentId" name="EntityId" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}" version="1">
-								<Class field="id" name="AZ::u64" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}" value="4294967295" />
-							</Class>
-							<Class field="ChildrenIds" name="AZStd::unordered_set" type="{6C8F8E52-AB4A-5C1F-8E56-9AC390290B94}" />
-							<Class field="PersistenceFlag" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-						</Class>
-					</Class>
-					<Class field="IsDependencyReady" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-					<Class field="IsRuntimeActive" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="true" />
-				</Class>
-				<Class field="DataFlagsForNewEntities" name="DataFlagsPerEntity" type="{57FE7B9E-B2AF-4F6F-9F8D-87F671E91C99}" version="1">
-					<Class field="EntityToDataFlags" name="AZStd::unordered_map" type="{CAB9E1F5-761E-54B8-916E-E7FB597E5EDE}" />
-				</Class>
-			</Class>
-		</Class>
-		<Class field="IsDependencyReady" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="false" />
-		<Class field="IsRuntimeActive" name="bool" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}" value="true" />
-	</Class>
-</ObjectStream>

+ 0 - 174
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/assets_with_nested_preload_dependency/TestB.slice

@@ -1,174 +0,0 @@
-<ObjectStream version="3">
-	<Class name="AZ::Entity" 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="268989189527" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		</Class>
-		<Class name="AZStd::string" field="Name" value="Slice" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		<Class name="AZStd::vector" 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="13244161893904461810" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-				<Class name="AZStd::vector" 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="277579124119" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-						</Class>
-						<Class name="AZStd::string" field="Name" value="TestB" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-						<Class name="AZStd::vector" 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="1413149470528250202" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="bool" field="IsEditorOnly" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="TransformComponent" field="element" version="9" type="{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0}">
-								<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="10451347479842120634" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="EntityId" field="Parent Entity" 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="EditorTransform" field="Transform Data" version="2" type="{B02B7063-D238-4F40-A724-405F7A6D68CB}">
-									<Class name="Vector3" field="Translate" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
-									<Class name="Vector3" field="Rotate" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
-									<Class name="Vector3" field="Scale" value="1.0000000 1.0000000 1.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
-									<Class name="bool" field="Locked" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								</Class>
-								<Class name="Transform" field="Cached World Transform" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000" type="{5D9958E9-9F1E-4985-B532-FFFDE75FEDFD}"/>
-								<Class name="EntityId" field="Cached World Transform Parent" 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="unsigned int" field="Parent Activation Transform Mode" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-								<Class name="bool" field="IsStatic" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								<Class name="bool" field="Sync Enabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								<Class name="unsigned int" field="InterpolatePosition" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-								<Class name="unsigned int" field="InterpolateRotation" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-							</Class>
-							<Class name="EditorInspectorComponent" field="element" version="2" type="{47DE3DDA-50C5-4F50-B1DB-BA4AE66AB056}">
-								<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="16572464487825802784" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="ComponentOrderEntryArray" type="{B6EFED5B-19B4-5084-9D92-42DECCE83872}">
-									<Class name="ComponentOrderEntry" field="element" version="1" type="{335C5861-5197-4DD5-A766-EF2B551B0D9D}">
-										<Class name="AZ::u64" field="ComponentId" value="10451347479842120634" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-										<Class name="AZ::u64" field="SortIndex" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-									<Class name="ComponentOrderEntry" field="element" version="1" type="{335C5861-5197-4DD5-A766-EF2B551B0D9D}">
-										<Class name="AZ::u64" field="ComponentId" value="17743482064793827553" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-										<Class name="AZ::u64" field="SortIndex" value="1" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-							</Class>
-							<Class name="EditorEntitySortComponent" field="element" version="2" type="{6EA1E03D-68B2-466D-97F7-83998C8C27F0}">
-								<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="6677854451525670577" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="ChildEntityOrderEntryArray" type="{BE163120-C1ED-5F69-A650-DC2528A8FF94}"/>
-							</Class>
-							<Class name="SelectionComponent" field="element" type="{73B724FC-43D1-4C75-ACF5-79AA8A3BF89D}">
-								<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-									<Class name="AZ::u64" field="Id" value="10965799152348437728" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-								</Class>
-							</Class>
-							<Class name="EditorSpawnerComponent" field="element" version="1" type="{77CDE991-EC1A-B7C1-B112-7456ABAC81A1}">
-								<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-									<Class name="AZ::u64" field="Id" value="17743482064793827553" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-								</Class>
-								<Class name="Asset" field="Slice" value="id={0216D84C-4061-5F7E-B6DA-0ABF747BCF1B}:2,type={78802ABF-9595-463A-8D2B-D022F906F9B1},hint={assets_with_nested_preload_dependency/testa.dynamicslice}" version="1" type="{77A19D40-8731-4D3C-9041-1B43047366A4}"/>
-								<Class name="bool" field="SpawnOnActivate" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								<Class name="bool" field="DestroyOnDeactivate" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="EditorVisibilityComponent" field="element" type="{88E08E78-5C2F-4943-9F73-C115E6FFAB43}">
-								<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="3307404167904755547" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="bool" field="VisibilityFlag" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="EditorLockComponent" field="element" type="{C3A169C9-7EFB-4D6C-8710-3591680D0936}">
-								<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="603163492571995613" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="bool" field="Locked" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="EditorPendingCompositionComponent" field="element" type="{D40FCB35-153D-45B3-AF6D-7BA576D8AFBB}">
-								<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="2776840331440727096" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="PendingComponents" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"/>
-							</Class>
-							<Class name="EditorEntityIconComponent" field="element" type="{E15D42C2-912D-466F-9547-E7E948CE2D7D}">
-								<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="12291544534723865655" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AssetId" field="EntityIconAssetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-									<Class name="AZ::Uuid" field="guid" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-									<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-								</Class>
-							</Class>
-							<Class name="EditorDisabledCompositionComponent" field="element" type="{E77AE6AC-897D-4035-8353-637449B6DCFB}">
-								<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="12816958447570956345" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="DisabledComponents" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"/>
-							</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" 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="273284156823" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-					</Class>
-					<Class name="AZStd::string" field="Name" value="No Asset Association" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-					<Class name="AZStd::vector" 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="7886784016988102927" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-							</Class>
-							<Class name="AZStd::set" field="AssociatedIds" type="{78E024C3-0143-53FC-B393-0675227839AF}">
-								<Class name="EntityId" field="element" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-									<Class name="AZ::u64" field="id" value="277579124119" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-								</Class>
-							</Class>
-							<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" field="ChildrenIds" type="{6C8F8E52-AB4A-5C1F-8E56-9AC390290B94}"/>
-							<Class name="bool" field="PersistenceFlag" value="false" 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" 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>
-</ObjectStream>
-

+ 0 - 174
AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/assets_with_nested_preload_dependency/TestD.slice

@@ -1,174 +0,0 @@
-<ObjectStream version="3">
-	<Class name="AZ::Entity" 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="382257329386" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-		</Class>
-		<Class name="AZStd::string" field="Name" value="Slice" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-		<Class name="AZStd::vector" 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="10124611306244674550" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-				</Class>
-				<Class name="AZStd::vector" 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="390847263978" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-						</Class>
-						<Class name="AZStd::string" field="Name" value="TestB" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-						<Class name="AZStd::vector" 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="9595291727352692926" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="bool" field="IsEditorOnly" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="TransformComponent" field="element" version="9" type="{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0}">
-								<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="6918190889556026264" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="EntityId" field="Parent Entity" 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="EditorTransform" field="Transform Data" version="2" type="{B02B7063-D238-4F40-A724-405F7A6D68CB}">
-									<Class name="Vector3" field="Translate" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
-									<Class name="Vector3" field="Rotate" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
-									<Class name="Vector3" field="Scale" value="1.0000000 1.0000000 1.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
-									<Class name="bool" field="Locked" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								</Class>
-								<Class name="Transform" field="Cached World Transform" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000" type="{5D9958E9-9F1E-4985-B532-FFFDE75FEDFD}"/>
-								<Class name="EntityId" field="Cached World Transform Parent" 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="unsigned int" field="Parent Activation Transform Mode" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-								<Class name="bool" field="IsStatic" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								<Class name="bool" field="Sync Enabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								<Class name="unsigned int" field="InterpolatePosition" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-								<Class name="unsigned int" field="InterpolateRotation" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-							</Class>
-							<Class name="EditorInspectorComponent" field="element" version="2" type="{47DE3DDA-50C5-4F50-B1DB-BA4AE66AB056}">
-								<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="16488522651299490860" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="ComponentOrderEntryArray" type="{B6EFED5B-19B4-5084-9D92-42DECCE83872}">
-									<Class name="ComponentOrderEntry" field="element" version="1" type="{335C5861-5197-4DD5-A766-EF2B551B0D9D}">
-										<Class name="AZ::u64" field="ComponentId" value="6918190889556026264" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-										<Class name="AZ::u64" field="SortIndex" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-									<Class name="ComponentOrderEntry" field="element" version="1" type="{335C5861-5197-4DD5-A766-EF2B551B0D9D}">
-										<Class name="AZ::u64" field="ComponentId" value="1133009518516046488" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-										<Class name="AZ::u64" field="SortIndex" value="1" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-							</Class>
-							<Class name="EditorEntitySortComponent" field="element" version="2" type="{6EA1E03D-68B2-466D-97F7-83998C8C27F0}">
-								<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="6551321942498556777" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="ChildEntityOrderEntryArray" type="{BE163120-C1ED-5F69-A650-DC2528A8FF94}"/>
-							</Class>
-							<Class name="SelectionComponent" field="element" type="{73B724FC-43D1-4C75-ACF5-79AA8A3BF89D}">
-								<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-									<Class name="AZ::u64" field="Id" value="5168720242367005303" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-								</Class>
-							</Class>
-							<Class name="EditorSpawnerComponent" field="element" version="1" type="{77CDE991-EC1A-B7C1-B112-7456ABAC81A1}">
-								<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
-									<Class name="AZ::u64" field="Id" value="1133009518516046488" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-								</Class>
-								<Class name="Asset" field="Slice" value="id={F47140D7-4A19-5BAA-B0A5-117E6575647A}:2,type={78802ABF-9595-463A-8D2B-D022F906F9B1},hint={assets_with_nested_preload_dependency/testb.dynamicslice}" version="1" type="{77A19D40-8731-4D3C-9041-1B43047366A4}"/>
-								<Class name="bool" field="SpawnOnActivate" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-								<Class name="bool" field="DestroyOnDeactivate" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="EditorVisibilityComponent" field="element" type="{88E08E78-5C2F-4943-9F73-C115E6FFAB43}">
-								<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="17020070072341888679" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="bool" field="VisibilityFlag" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="EditorLockComponent" field="element" type="{C3A169C9-7EFB-4D6C-8710-3591680D0936}">
-								<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="16300364923199181818" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="bool" field="Locked" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
-							</Class>
-							<Class name="EditorPendingCompositionComponent" field="element" type="{D40FCB35-153D-45B3-AF6D-7BA576D8AFBB}">
-								<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="3997039705476816210" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="PendingComponents" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"/>
-							</Class>
-							<Class name="EditorEntityIconComponent" field="element" type="{E15D42C2-912D-466F-9547-E7E948CE2D7D}">
-								<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="10323419800905366237" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AssetId" field="EntityIconAssetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
-									<Class name="AZ::Uuid" field="guid" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
-									<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-								</Class>
-							</Class>
-							<Class name="EditorDisabledCompositionComponent" field="element" type="{E77AE6AC-897D-4035-8353-637449B6DCFB}">
-								<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="2409852450700585411" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-									</Class>
-								</Class>
-								<Class name="AZStd::vector" field="DisabledComponents" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"/>
-							</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" 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="386552296682" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-					</Class>
-					<Class name="AZStd::string" field="Name" value="No Asset Association" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
-					<Class name="AZStd::vector" 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="6483308780985076120" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-							</Class>
-							<Class name="AZStd::set" field="AssociatedIds" type="{78E024C3-0143-53FC-B393-0675227839AF}">
-								<Class name="EntityId" field="element" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
-									<Class name="AZ::u64" field="id" value="390847263978" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
-								</Class>
-							</Class>
-							<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" field="ChildrenIds" type="{6C8F8E52-AB4A-5C1F-8E56-9AC390290B94}"/>
-							<Class name="bool" field="PersistenceFlag" value="false" 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" 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>
-</ObjectStream>
-

+ 0 - 181
AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks.py

@@ -1,181 +0,0 @@
-"""
-Copyright (c) Contributors to the Open 3D Engine Project.
-For complete copyright and license terms please see the LICENSE at the root of this distribution.
-
-SPDX-License-Identifier: Apache-2.0 OR MIT
-"""
-
-
-class BehaviorContextTests:
-    spawner_initialized = (
-        "Successfully initialized a Dynamic Slice Instance Spawner",
-        "Failed to initialize a Dynamic Slice Instance Spawner"
-    )
-    spawner_slice_asset_path_set = (
-        "Successfully set a Dynamic Slice asset path",
-        "Failed to set a Dynamic Slice asset path"
-    )
-    spawner_empty_slice_asset_path_set = (
-        "Successfully set an empty Dynamic Slice asset path",
-        "Failed to set an empty Dynamic Slice asset path"
-    )
-    desc_spawnertype_sets_spawner = (
-        "Setting spawnerType sets spawner too",
-        "Setting spawnerType failed to set spawner to expected value"
-    )
-    desc_spawner_sets_spawnertype = (
-        "Setting spawner sets spawnerType too",
-        "Setting spawner failed to set spawnerType to expected value"
-    )
-
-
-class PropertyTreeTests:
-    entity_created = (
-        "Spawner entity created successfully",
-        "Failed to create spawner entity"
-    )
-    spawner_type_set = (
-        "Successfully set spawner type",
-        "Failed to set spawner type"
-    )
-    empty_instance_count_validation = (
-        "Expected number of empty instances planted",
-        "Unexpected number of empty instances planted"
-    )
-    no_instances_when_empty_disallowed = (
-        "No empty instances found when Empty Assets are not allowed",
-        "Unexpectedly found empty instances when Empty Assets are not allowed"
-    )
-    nonempty_asset_instance_count_validation = (
-        "Expected number of instances planted",
-        "Unexpected number of instances planted"
-    )
-
-
-def DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks():
-    """
-    Summary:
-    Test aspects of the DynamicSliceInstanceSpawner through the BehaviorContext and the Property Tree.
-
-    :return: None
-    """
-
-    import os
-
-    import azlmbr.legacy.general as general
-    import azlmbr.math as math
-
-    import editor_python_test_tools.hydra_editor_utils as hydra
-    from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
-    from editor_python_test_tools.utils import Report
-    from editor_python_test_tools.utils import TestHelper as helper
-
-    # 1) Open an existing simple level
-    hydra.open_base_level()
-    general.set_current_view_position(512.0, 480.0, 38.0)
-
-    # Grab the UUID that we need for creating an Dynamic Slice Instance Spawner
-    dynamic_slice_spawner_uuid = azlmbr.math.Uuid_CreateString('{BBA5CC1E-B4CA-4792-89F7-93711E98FBD1}', 0)
-
-    # Grab a path to a test dynamic slice asset
-    test_slice_asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
-
-    # 2) Test DynamicSliceInstanceSpawner BehaviorContext
-    behavior_context_test_success = True
-    dynamic_slice_spawner = azlmbr.vegetation.DynamicSliceInstanceSpawner()
-    behavior_context_test_success = behavior_context_test_success and (dynamic_slice_spawner is not None)
-    behavior_context_test_success = behavior_context_test_success and (dynamic_slice_spawner.typename == 'DynamicSliceInstanceSpawner')
-    Report.critical_result(BehaviorContextTests.spawner_initialized, behavior_context_test_success)
-    # Try to get/set the slice asset path with a valid asset
-    dynamic_slice_spawner.SetSliceAssetPath(test_slice_asset_path)
-    validate_path = dynamic_slice_spawner.GetSliceAssetPath()
-    # We expect the path to get lowercased and normalized with a forward slash, so we compare our result
-    # vs that instead of directly against test_slice_asset_path.
-    behavior_context_test_success = behavior_context_test_success and hydra.compare_values('slices/pinkflower.dynamicslice', validate_path, 'GetSliceAssetPath - valid')
-    Report.result(BehaviorContextTests.spawner_slice_asset_path_set, behavior_context_test_success)
-    # Try to get/set the slice asset path with an empty path
-    dynamic_slice_spawner.SetSliceAssetPath('')
-    validate_path = dynamic_slice_spawner.GetSliceAssetPath()
-    behavior_context_test_success = behavior_context_test_success and hydra.compare_values('', validate_path, 'GetSliceAssetPath - empty')
-    Report.result(BehaviorContextTests.spawner_empty_slice_asset_path_set, behavior_context_test_success)
-    Report.info(f'DynamicSliceInstanceSpawner() BehaviorContext test: {behavior_context_test_success}')
-
-    # 3) Test Descriptor BehaviorContext - setting spawnerType sets spawner too
-    spawner_type_test_success = True
-    descriptor = azlmbr.vegetation.Descriptor()
-    spawner_type_test_success = spawner_type_test_success and hydra.get_set_property_test(descriptor, 'spawnerType', dynamic_slice_spawner_uuid)
-    spawner_type_test_success = spawner_type_test_success and (descriptor.spawner.typename == 'DynamicSliceInstanceSpawner')
-    Report.result(BehaviorContextTests.desc_spawnertype_sets_spawner, spawner_type_test_success)
-    Report.info(f'Descriptor() BehaviorContext spawnerType test: {spawner_type_test_success}')
-
-    # 4) Test Descriptor BehaviorContext - setting spawner sets spawnerType too
-    spawner_test_success = True
-    descriptor = azlmbr.vegetation.Descriptor()
-    descriptor.spawner = dynamic_slice_spawner
-    spawner_test_success = spawner_test_success and (descriptor.spawnerType.Equal(dynamic_slice_spawner_uuid))
-    spawner_test_success = spawner_test_success and (descriptor.spawner.typename == 'DynamicSliceInstanceSpawner')
-    Report.result(BehaviorContextTests.desc_spawner_sets_spawnertype, spawner_test_success)
-    Report.info(f'Descriptor() BehaviorContext spawner test: {spawner_test_success}')
-
-    ### Setup for Property Tree set of tests
-
-    # Create a new entity with required vegetation area components
-    spawner_entity = hydra.Entity("Veg Area")
-    spawner_entity.create_entity(
-        math.Vector3(512.0, 512.0, 32.0),
-        ["Vegetation Layer Spawner", "Box Shape", "Vegetation Asset List"]
-        )
-    Report.critical_result(PropertyTreeTests.entity_created, spawner_entity.id.IsValid())
-
-    # Resize the Box Shape component
-    new_box_dimensions = math.Vector3(16.0, 16.0, 16.0)
-    box_dimensions_path = "Box Shape|Box Configuration|Dimensions"
-    spawner_entity.get_set_test(1, box_dimensions_path, new_box_dimensions)
-
-    # Create a surface to plant on
-    dynveg.create_surface_entity("Surface Entity", math.Vector3(512.0, 512.0, 32.0), 1024.0, 1024.0, 1.0)
-
-    # 5) Descriptor Property Tree test: spawner type can be set
-
-    # - Validate the dynamic slice spawner type can be set correctly.
-    property_tree_success = True
-    property_tree_success = property_tree_success and spawner_entity.get_set_test(2, 'Configuration|Embedded Assets|[0]|Instance Spawner', dynamic_slice_spawner_uuid)
-    Report.result(PropertyTreeTests.spawner_type_set, property_tree_success)
-
-    # This should result in 400 instances, since our box is 16 m x 16 m and by default the veg system plants
-    # 20 instances per 16 meters
-    spawner_entity.get_set_test(0, 'Configuration|Allow Empty Assets', True)
-    num_expected_instances = 20 * 20
-    property_tree_success = property_tree_success and helper.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected_instances), 5.0)
-    Report.result(PropertyTreeTests.empty_instance_count_validation, property_tree_success)
-    Report.info(f'Property Tree spawner type test: {property_tree_success}')
-
-    # 6) Validate that the "Allow Empty Assets" setting affects the DynamicSliceInstanceSpawner
-    allow_empty_assets_success = True
-    # Since we have an empty slice path, we should have 0 instances once we disable 'Allow Empty Assets'
-    num_expected_instances = 0
-    allow_empty_assets_success = allow_empty_assets_success and spawner_entity.get_set_test(0, 'Configuration|Allow Empty Assets', False)
-    Report.info('Allow Empty Assets test:')
-    allow_empty_assets_success = allow_empty_assets_success and helper.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected_instances), 5.0)
-    Report.result(PropertyTreeTests.no_instances_when_empty_disallowed, allow_empty_assets_success)
-    Report.info(f'Allow Empty Assets test: {allow_empty_assets_success}')
-
-    # 7) Validate that with 'Allow Empty Assets' set to False, a non-empty slice asset gives us the number
-    # of instances we expect.
-    spawns_slices_success = True
-    num_expected_instances = 20 * 20
-    dynamic_slice_spawner.SetSliceAssetPath(test_slice_asset_path)
-    spawns_slices_success = spawns_slices_success and spawner_entity.get_set_test(0, 'Configuration|Allow Empty Assets', False)
-    descriptor = hydra.get_component_property_value(spawner_entity.components[2], 'Configuration|Embedded Assets|[0]')
-    descriptor.spawner = dynamic_slice_spawner
-    spawns_slices_success = spawns_slices_success and spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]", descriptor)
-    Report.info('Spawn dynamic slices test:')
-    spawns_slices_success = spawns_slices_success and helper.wait_for_condition(lambda: dynveg.validate_instance_count_in_entity_shape(spawner_entity.id, num_expected_instances), 5.0)
-    Report.result(PropertyTreeTests.nonempty_asset_instance_count_validation, spawns_slices_success)
-    Report.info(f'Spawn dynamic slices test: {spawns_slices_success}')
-
-
-if __name__ == "__main__":
-
-    from editor_python_test_tools.utils import Report
-    Report.start_test(DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks)

+ 0 - 3
AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/TestSuite_Main.py

@@ -45,9 +45,6 @@ class TestAutomation(EditorTestSuite):
     class test_DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius(EditorSharedTest):
         from .EditorScripts import DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius as test_module
 
-    class test_DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks(EditorSharedTest):
-        from .EditorScripts import DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks as test_module
-
     class test_EmptyInstanceSpawner_EmptySpawnerWorks(EditorSharedTest):
         from .EditorScripts import EmptyInstanceSpawner_EmptySpawnerWorks as test_module
 

+ 0 - 21
AutomatedTesting/Gem/PythonTests/largeworlds/large_worlds_utils/editor_dynveg_test_helper.py

@@ -93,27 +93,6 @@ def create_mesh_surface_entity_with_slopes(name, center_point, uniform_scale):
     return surface_entity
 
 
-def create_dynamic_slice_vegetation_area(name, center_point, box_size_x, box_size_y, box_size_z, dynamic_slice_asset_path):
-    # Create a vegetation area entity to use as our test vegetation spawner
-    spawner_entity = hydra.Entity(name)
-    spawner_entity.create_entity(
-        center_point,
-        ["Vegetation Layer Spawner", "Box Shape", "Vegetation Asset List"]
-        )
-    if spawner_entity.id.IsValid():
-        print(f"'{spawner_entity.name}' created")
-    spawner_entity.get_set_test(1, "Box Shape|Box Configuration|Dimensions", math.Vector3(box_size_x, box_size_y,
-                                                                                          box_size_z))
-
-    # Set the vegetation area to a Dynamic Slice spawner with a specific slice asset selected
-    descriptor = hydra.get_component_property_value(spawner_entity.components[2], 'Configuration|Embedded Assets|[0]')
-    dynamic_slice_spawner = vegetation.DynamicSliceInstanceSpawner()
-    dynamic_slice_spawner.SetSliceAssetPath(dynamic_slice_asset_path)
-    descriptor.spawner = dynamic_slice_spawner
-    spawner_entity.get_set_test(2, "Configuration|Embedded Assets|[0]", descriptor)
-    return spawner_entity
-
-
 def create_temp_prefab_vegetation_area(name, center_point, box_size_x, box_size_y, box_size_z, target_prefab):
     """Creates a vegetation area using in-memory prefabs. Use when test is solely contained to Editor"""
     # Create a vegetation area entity to use as our test vegetation spawner

+ 4 - 5
AutomatedTesting/Levels/Physics/ScriptCanvas_PreUpdateEvent/ScriptCanvas_PreUpdateEvent.prefab

@@ -20,7 +20,6 @@
                 "Id": 14126657869720434043,
                 "Child Entity Order": [
                     "Entity_[3471072164802]",
-                    "Entity_[3475367132098]",
                     "Entity_[3475367132098]"
                 ]
             },
@@ -88,7 +87,7 @@
                     "Parent Entity": "Entity_[1146574390643]",
                     "Transform Data": {
                         "Translate": [
-                            506.0,
+                            510.0,
                             530.0,
                             39.0
                         ]
@@ -139,9 +138,9 @@
                     "Parent Entity": "Entity_[1146574390643]",
                     "Transform Data": {
                         "Translate": [
-                            0.0,
-                            0.09999752044677734,
-                            4.010498523712158
+                            509.0,
+                            530.0,
+                            39.0
                         ]
                     }
                 },

+ 1 - 115
Code/Editor/CryEdit.cpp

@@ -384,32 +384,7 @@ void CCryEditApp::RegisterActionHandlers()
     ON_COMMAND(ID_VIEW_CONFIGURELAYOUT, OnViewConfigureLayout)
 
     ON_COMMAND(IDC_SELECTION, OnDummyCommand)
-    //////////////////////////////////////////////////////////////////////////
-    ON_COMMAND(ID_TAG_LOC1, OnTagLocation1)
-    ON_COMMAND(ID_TAG_LOC2, OnTagLocation2)
-    ON_COMMAND(ID_TAG_LOC3, OnTagLocation3)
-    ON_COMMAND(ID_TAG_LOC4, OnTagLocation4)
-    ON_COMMAND(ID_TAG_LOC5, OnTagLocation5)
-    ON_COMMAND(ID_TAG_LOC6, OnTagLocation6)
-    ON_COMMAND(ID_TAG_LOC7, OnTagLocation7)
-    ON_COMMAND(ID_TAG_LOC8, OnTagLocation8)
-    ON_COMMAND(ID_TAG_LOC9, OnTagLocation9)
-    ON_COMMAND(ID_TAG_LOC10, OnTagLocation10)
-    ON_COMMAND(ID_TAG_LOC11, OnTagLocation11)
-    ON_COMMAND(ID_TAG_LOC12, OnTagLocation12)
-    //////////////////////////////////////////////////////////////////////////
-    ON_COMMAND(ID_GOTO_LOC1, OnGotoLocation1)
-    ON_COMMAND(ID_GOTO_LOC2, OnGotoLocation2)
-    ON_COMMAND(ID_GOTO_LOC3, OnGotoLocation3)
-    ON_COMMAND(ID_GOTO_LOC4, OnGotoLocation4)
-    ON_COMMAND(ID_GOTO_LOC5, OnGotoLocation5)
-    ON_COMMAND(ID_GOTO_LOC6, OnGotoLocation6)
-    ON_COMMAND(ID_GOTO_LOC7, OnGotoLocation7)
-    ON_COMMAND(ID_GOTO_LOC8, OnGotoLocation8)
-    ON_COMMAND(ID_GOTO_LOC9, OnGotoLocation9)
-    ON_COMMAND(ID_GOTO_LOC10, OnGotoLocation10)
-    ON_COMMAND(ID_GOTO_LOC11, OnGotoLocation11)
-    ON_COMMAND(ID_GOTO_LOC12, OnGotoLocation12)
+
     //////////////////////////////////////////////////////////////////////////
 
     ON_COMMAND(ID_TOOLS_LOGMEMORYUSAGE, OnToolsLogMemoryUsage)
@@ -3420,31 +3395,6 @@ void CCryEditApp::OnViewConfigureLayout()
     }
 }
 
-//////////////////////////////////////////////////////////////////////////
-void CCryEditApp::TagLocation(int index)
-{
-    CViewport* pRenderViewport = GetIEditor()->GetViewManager()->GetGameViewport();
-    if (!pRenderViewport)
-    {
-        return;
-    }
-
-    Vec3 vPosVec = pRenderViewport->GetViewTM().GetTranslation();
-
-    m_tagLocations[index - 1] = vPosVec;
-    m_tagAngles[index - 1] = Ang3::GetAnglesXYZ(Matrix33(pRenderViewport->GetViewTM()));
-
-    QString sTagConsoleText("");
-    sTagConsoleText = tr("Camera Tag Point %1 set to the position: x=%2, y=%3, z=%4 ").arg(index).arg(vPosVec.x, 0, 'f', 2).arg(vPosVec.y, 0, 'f', 2).arg(vPosVec.z, 0, 'f', 2);
-
-    GetIEditor()->WriteToConsole(sTagConsoleText.toUtf8().data());
-
-    if (gSettings.bAutoSaveTagPoints)
-    {
-        SaveTagLocations();
-    }
-}
-
 void CCryEditApp::SaveTagLocations()
 {
     // Save to file.
@@ -3462,41 +3412,6 @@ void CCryEditApp::SaveTagLocations()
     }
 }
 
-
-//////////////////////////////////////////////////////////////////////////
-void CCryEditApp::GotoTagLocation(int index)
-{
-    QString sTagConsoleText("");
-    Vec3 pos = m_tagLocations[index - 1];
-
-    if (!IsVectorsEqual(m_tagLocations[index - 1], Vec3(0, 0, 0)))
-    {
-        // Change render viewport view TM to the stored one.
-        CViewport* pRenderViewport = GetIEditor()->GetViewManager()->GetGameViewport();
-        if (pRenderViewport)
-        {
-            Matrix34 tm = Matrix34::CreateRotationXYZ(m_tagAngles[index - 1]);
-            tm.SetTranslation(pos);
-            pRenderViewport->SetViewTM(tm);
-            Vec3 vPosVec(tm.GetTranslation());
-
-            GetISystem()->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_BEAM_PLAYER_TO_CAMERA_POS, (UINT_PTR)&tm, 0);
-
-            sTagConsoleText = tr("Moved Camera To Tag Point %1 (x=%2, y=%3, z=%4)").arg(index).arg(vPosVec.x, 0, 'f', 2).arg(vPosVec.y, 0, 'f', 2).arg(vPosVec.z, 0, 'f', 2);
-        }
-    }
-    else
-    {
-        sTagConsoleText = tr("Camera Tag Point %1 not set").arg(index);
-    }
-
-    if (!sTagConsoleText.isEmpty())
-    {
-        GetIEditor()->WriteToConsole(sTagConsoleText.toUtf8().data());
-    }
-}
-
-
 //////////////////////////////////////////////////////////////////////////
 void CCryEditApp::LoadTagLocations()
 {
@@ -3535,35 +3450,6 @@ void CCryEditApp::OnToolsLogMemoryUsage()
     gEnv->pConsole->ExecuteString("SaveLevelStats");
 }
 
-//////////////////////////////////////////////////////////////////////////
-void CCryEditApp::OnTagLocation1() { TagLocation(1); }
-void CCryEditApp::OnTagLocation2() { TagLocation(2); }
-void CCryEditApp::OnTagLocation3() { TagLocation(3); }
-void CCryEditApp::OnTagLocation4() { TagLocation(4); }
-void CCryEditApp::OnTagLocation5() { TagLocation(5); }
-void CCryEditApp::OnTagLocation6() { TagLocation(6); }
-void CCryEditApp::OnTagLocation7() { TagLocation(7); }
-void CCryEditApp::OnTagLocation8() { TagLocation(8); }
-void CCryEditApp::OnTagLocation9() { TagLocation(9); }
-void CCryEditApp::OnTagLocation10() { TagLocation(10); }
-void CCryEditApp::OnTagLocation11() { TagLocation(11); }
-void CCryEditApp::OnTagLocation12() { TagLocation(12); }
-
-
-//////////////////////////////////////////////////////////////////////////
-void CCryEditApp::OnGotoLocation1() { GotoTagLocation(1); }
-void CCryEditApp::OnGotoLocation2() { GotoTagLocation(2); }
-void CCryEditApp::OnGotoLocation3() { GotoTagLocation(3); }
-void CCryEditApp::OnGotoLocation4() { GotoTagLocation(4); }
-void CCryEditApp::OnGotoLocation5() { GotoTagLocation(5); }
-void CCryEditApp::OnGotoLocation6() { GotoTagLocation(6); }
-void CCryEditApp::OnGotoLocation7() { GotoTagLocation(7); }
-void CCryEditApp::OnGotoLocation8() { GotoTagLocation(8); }
-void CCryEditApp::OnGotoLocation9() { GotoTagLocation(9); }
-void CCryEditApp::OnGotoLocation10() { GotoTagLocation(10); }
-void CCryEditApp::OnGotoLocation11() { GotoTagLocation(11); }
-void CCryEditApp::OnGotoLocation12() { GotoTagLocation(12); }
-
 //////////////////////////////////////////////////////////////////////////
 void CCryEditApp::OnCustomizeKeyboard()
 {

+ 0 - 28
Code/Editor/CryEdit.h

@@ -247,8 +247,6 @@ private:
 
     CMainFrame* GetMainFrame() const;
     void WriteConfig();
-    void TagLocation(int index);
-    void GotoTagLocation(int index);
     void LoadTagLocations();
     bool UserExportToGame(bool bNoMsgBox = true);
     static void ShowSplashScreen(CCryEditApp* app);
@@ -359,32 +357,6 @@ private:
     void OnUpdateWireframe(QAction* action);
     void OnViewConfigureLayout();
 
-    // Tag Locations.
-    void OnTagLocation1();
-    void OnTagLocation2();
-    void OnTagLocation3();
-    void OnTagLocation4();
-    void OnTagLocation5();
-    void OnTagLocation6();
-    void OnTagLocation7();
-    void OnTagLocation8();
-    void OnTagLocation9();
-    void OnTagLocation10();
-    void OnTagLocation11();
-    void OnTagLocation12();
-
-    void OnGotoLocation1();
-    void OnGotoLocation2();
-    void OnGotoLocation3();
-    void OnGotoLocation4();
-    void OnGotoLocation5();
-    void OnGotoLocation6();
-    void OnGotoLocation7();
-    void OnGotoLocation8();
-    void OnGotoLocation9();
-    void OnGotoLocation10();
-    void OnGotoLocation11();
-    void OnGotoLocation12();
     void OnToolsLogMemoryUsage();
     void OnCustomizeKeyboard();
     void OnToolsConfiguretools();

+ 143 - 24
Code/Editor/MainWindow.cpp

@@ -21,6 +21,10 @@
 #include <QAbstractEventDispatcher>
 #endif
 
+// Atom
+#include <Atom/RPI.Public/ViewportContext.h>
+#include <Atom/RPI.Public/ViewportContextBus.h>
+
 // AzCore
 #include <AzCore/Component/ComponentApplication.h>
 #include <AzCore/Interface/Interface.h>
@@ -35,6 +39,7 @@
 #include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
 #include <AzFramework/Network/SocketConnection.h>
 #include <AzFramework/Asset/AssetSystemComponent.h>
+#include <AzFramework/Viewport/CameraInput.h>
 
 // AzToolsFramework
 #include <AzToolsFramework/Application/Ticker.h>
@@ -44,6 +49,8 @@
 #include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
 #include <AzToolsFramework/Viewport/ViewportSettings.h>
 #include <AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h>
+#include <AzToolsFramework/API/EditorCameraBus.h>
+#include <AzToolsFramework/Viewport/ViewBookmarkLoaderInterface.h>
 
 // AzQtComponents
 #include <AzQtComponents/Buses/ShortcutDispatch.h>
@@ -95,6 +102,7 @@
 #include <ImGuiBus.h>
 #include <AzToolsFramework/Viewport/ViewportMessages.h>
 #include <LmbrCentral/Audio/AudioSystemComponentBus.h>
+#include <Editor/EditorViewportCamera.h>
 
 using namespace AZ;
 using namespace AzQtComponents;
@@ -845,78 +853,189 @@ void MainWindow::InitActions()
         .SetShortcut(tr("Z"))
         .SetToolTip(tr("Center on Selection (Z)"))
         .Connect(&QAction::triggered, this, &MainWindow::OnGotoSelected);
+
+    const auto goToViewBookmarkFn = [](int index)
+    {
+        AzToolsFramework::ViewBookmarkLoaderInterface* bookmarkLoader = AZ::Interface<ViewBookmarkLoaderInterface>::Get();
+        if (!bookmarkLoader)
+        {
+            AZ_Warning("Main Window", false, "Couldn't find View Bookmark Loader");
+            return false;
+        }
+
+        const AZStd::optional<AzToolsFramework::ViewBookmark> bookmark =
+            bookmarkLoader->LoadBookmarkAtIndex(index);
+
+        if (!bookmark.has_value())
+        {
+            return false;
+        }
+
+        // Check the bookmark we want to load is not exactly 0 
+        if (bookmark.value().IsZero())
+        {
+            QString tagConsoleText = tr("View Bookmark %1 has not been set yet").arg(index + 1);
+            AZ_Warning("Main Window", false, tagConsoleText.toUtf8().data());
+            return false;
+        }
+
+        auto viewportContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
+        if (!viewportContextManager)
+        {
+            return false;
+        }
+
+        auto viewportContext = viewportContextManager->GetDefaultViewportContext();
+        if (!viewportContext)
+        {
+            return false;
+        }
+
+        SandboxEditor::InterpolateDefaultViewportCameraToTransform(
+            bookmark->m_position, bookmark->m_rotation.GetX(), bookmark->m_rotation.GetZ());
+
+        QString tagConsoleText = tr("View Bookmark %1 loaded position: x=%2, y=%3, z=%4")
+                                     .arg(index + 1)
+                                     .arg(bookmark->m_position.GetX(), 0, 'f', 2)
+                                     .arg(bookmark->m_position.GetY(), 0, 'f', 2)
+                                     .arg(bookmark->m_position.GetZ(), 0, 'f', 2);
+        AZ_Printf("MainWindow", tagConsoleText.toUtf8().data());
+        return true;
+    };
+
     am->AddAction(ID_GOTO_LOC1, tr("Location 1"))
         .SetShortcut(tr("Shift+F1"))
-        .SetToolTip(tr("Location 1 (Shift+F1)"));
+        .SetToolTip(tr("Go to Location 1 (Shift+F1)"))
+        .Connect(&QAction::triggered, [goToViewBookmarkFn](){ goToViewBookmarkFn(0);});
     am->AddAction(ID_GOTO_LOC2, tr("Location 2"))
         .SetShortcut(tr("Shift+F2"))
-        .SetToolTip(tr("Location 2 (Shift+F2)"));
+        .SetToolTip(tr("Go to Location 2 (Shift+F2)"))
+        .Connect(&QAction::triggered, [goToViewBookmarkFn](){ goToViewBookmarkFn(1);});
     am->AddAction(ID_GOTO_LOC3, tr("Location 3"))
         .SetShortcut(tr("Shift+F3"))
-        .SetToolTip(tr("Location 3 (Shift+F3)"));
+        .SetToolTip(tr("Go to Location 3 (Shift+F3)"))
+        .Connect(&QAction::triggered, [goToViewBookmarkFn](){ goToViewBookmarkFn(2);});
     am->AddAction(ID_GOTO_LOC4, tr("Location 4"))
         .SetShortcut(tr("Shift+F4"))
-        .SetToolTip(tr("Location 4 (Shift+F4)"));
+        .SetToolTip(tr("Go to Location 4 (Shift+F4)"))
+        .Connect(&QAction::triggered, [goToViewBookmarkFn](){ goToViewBookmarkFn(3);});
     am->AddAction(ID_GOTO_LOC5, tr("Location 5"))
         .SetShortcut(tr("Shift+F5"))
-        .SetToolTip(tr("Location 5 (Shift+F5)"));
+        .SetToolTip(tr("Go to Location 5 (Shift+F5)"))
+        .Connect(&QAction::triggered, [goToViewBookmarkFn](){ goToViewBookmarkFn(4);});
     am->AddAction(ID_GOTO_LOC6, tr("Location 6"))
         .SetShortcut(tr("Shift+F6"))
-        .SetToolTip(tr("Location 6 (Shift+F6)"));
+        .SetToolTip(tr("Go to Location 6 (Shift+F6)"))
+        .Connect(&QAction::triggered, [goToViewBookmarkFn](){ goToViewBookmarkFn(5);});
     am->AddAction(ID_GOTO_LOC7, tr("Location 7"))
         .SetShortcut(tr("Shift+F7"))
-        .SetToolTip(tr("Location 7 (Shift+F7)"));
+        .SetToolTip(tr("Go to Location 7 (Shift+F7)"))
+        .Connect(&QAction::triggered, [goToViewBookmarkFn](){ goToViewBookmarkFn(6);});
     am->AddAction(ID_GOTO_LOC8, tr("Location 8"))
         .SetShortcut(tr("Shift+F8"))
-        .SetToolTip(tr("Location 8 (Shift+F8)"));
+        .SetToolTip(tr("Go to Location 8 (Shift+F8)"))
+        .Connect(&QAction::triggered, [goToViewBookmarkFn](){ goToViewBookmarkFn(7);});
     am->AddAction(ID_GOTO_LOC9, tr("Location 9"))
         .SetShortcut(tr("Shift+F9"))
-        .SetToolTip(tr("Location 9 (Shift+F9)"));
+        .SetToolTip(tr("Go to Location 9 (Shift+F9)"))
+        .Connect(&QAction::triggered, [goToViewBookmarkFn](){ goToViewBookmarkFn(8);});
     am->AddAction(ID_GOTO_LOC10, tr("Location 10"))
         .SetShortcut(tr("Shift+F10"))
-        .SetToolTip(tr("Location 10 (Shift+F10)"));
+        .SetToolTip(tr("Go to Location 10 (Shift+F10)"))
+        .Connect(&QAction::triggered, [goToViewBookmarkFn](){ goToViewBookmarkFn(9);});
     am->AddAction(ID_GOTO_LOC11, tr("Location 11"))
         .SetShortcut(tr("Shift+F11"))
-        .SetToolTip(tr("Location 11 (Shift+F11)"));
+        .SetToolTip(tr("Go to Location 11 (Shift+F11)"))
+        .Connect(&QAction::triggered, [goToViewBookmarkFn](){ goToViewBookmarkFn(10);});
     am->AddAction(ID_GOTO_LOC12, tr("Location 12"))
         .SetShortcut(tr("Shift+F12"))
-        .SetToolTip(tr("Location 12 (Shift+F12)"));
+        .SetToolTip(tr("Go to Location 12 (Shift+F12)"))
+        .Connect(&QAction::triggered, [goToViewBookmarkFn](){ goToViewBookmarkFn(11);});
+
+    const auto tagViewBookmarkFn = [](int index)
+    {
+        AzToolsFramework::ViewBookmarkLoaderInterface* bookmarkLoader = AZ::Interface<ViewBookmarkLoaderInterface>::Get();
+        if (!bookmarkLoader)
+        {
+            QString tagConsoleText = tr("Failed to tag View Bookmark %1").arg(index + 1);
+            AZ_Warning("Main Window", false, tagConsoleText.toUtf8().data());
+            return false;
+        }
+
+        bool found = false;
+        AzFramework::CameraState cameraState;
+        Camera::EditorCameraRequestBus::BroadcastResult(
+            found, &Camera::EditorCameraRequestBus::Events::GetActiveCameraState, cameraState);
+
+        if (!found)
+        {
+            AZ_Warning("Main Window", false, "tagLocation: Couldn't find Active Camera State.");
+            return false;
+        }
+
+        ViewBookmark bookmark;
+        bookmark.m_position = cameraState.m_position;
+        bookmark.m_rotation =
+            AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromColumns(cameraState.m_side, cameraState.m_forward, cameraState.m_up));
+
+        bookmarkLoader->ModifyBookmarkAtIndex(bookmark, index);
+        QString tagConsoleText = tr("View Bookmark %1 set to the position: x=%2, y=%3, z=%4")
+                                     .arg(index + 1)
+                                     .arg(bookmark.m_position.GetX(), 0, 'f', 2)
+                                     .arg(bookmark.m_position.GetY(), 0, 'f', 2)
+                                     .arg(bookmark.m_position.GetZ(), 0, 'f', 2);
+        AZ_Printf("MainWindow", tagConsoleText.toUtf8().data());
+        return true;
+    };
+
     am->AddAction(ID_TAG_LOC1, tr("Location 1"))
         .SetShortcut(tr("Ctrl+F1"))
-        .SetToolTip(tr("Location 1 (Ctrl+F1)"));
+        .SetToolTip(tr("Save Location 1 (Ctrl+F1)"))
+        .Connect(&QAction::triggered, [tagViewBookmarkFn](){ tagViewBookmarkFn(0); });
     am->AddAction(ID_TAG_LOC2, tr("Location 2"))
         .SetShortcut(tr("Ctrl+F2"))
-        .SetToolTip(tr("Location 2 (Ctrl+F2)"));
+        .SetToolTip(tr("Save Location 2 (Ctrl+F2)"))
+        .Connect(&QAction::triggered, [tagViewBookmarkFn](){ tagViewBookmarkFn(1); });
     am->AddAction(ID_TAG_LOC3, tr("Location 3"))
         .SetShortcut(tr("Ctrl+F3"))
-        .SetToolTip(tr("Location 3 (Ctrl+F3)"));
+        .SetToolTip(tr("Save Location 3 (Ctrl+F3)"))
+        .Connect(&QAction::triggered, [tagViewBookmarkFn](){ tagViewBookmarkFn(2); });
     am->AddAction(ID_TAG_LOC4, tr("Location 4"))
         .SetShortcut(tr("Ctrl+F4"))
-        .SetToolTip(tr("Location 4 (Ctrl+F4)"));
+        .SetToolTip(tr("Save Location 4 (Ctrl+F4)"))
+        .Connect(&QAction::triggered, [tagViewBookmarkFn](){ tagViewBookmarkFn(3); });
     am->AddAction(ID_TAG_LOC5, tr("Location 5"))
         .SetShortcut(tr("Ctrl+F5"))
-        .SetToolTip(tr("Location 5 (Ctrl+F5)"));
+        .SetToolTip(tr("Save Location 5 (Ctrl+F5)"))
+        .Connect(&QAction::triggered, [tagViewBookmarkFn](){ tagViewBookmarkFn(4); });
     am->AddAction(ID_TAG_LOC6, tr("Location 6"))
         .SetShortcut(tr("Ctrl+F6"))
-        .SetToolTip(tr("Location 6 (Ctrl+F6)"));
+        .SetToolTip(tr("Save Location 6 (Ctrl+F6)"))
+        .Connect(&QAction::triggered, [tagViewBookmarkFn](){ tagViewBookmarkFn(5); });
     am->AddAction(ID_TAG_LOC7, tr("Location 7"))
         .SetShortcut(tr("Ctrl+F7"))
-        .SetToolTip(tr("Location 7 (Ctrl+F7)"));
+        .SetToolTip(tr("Save Location 7 (Ctrl+F7)"))
+        .Connect(&QAction::triggered, [tagViewBookmarkFn](){ tagViewBookmarkFn(6); });
     am->AddAction(ID_TAG_LOC8, tr("Location 8"))
         .SetShortcut(tr("Ctrl+F8"))
-        .SetToolTip(tr("Location 8 (Ctrl+F8)"));
+        .SetToolTip(tr("Save Location 8 (Ctrl+F8)"))
+        .Connect(&QAction::triggered, [tagViewBookmarkFn](){ tagViewBookmarkFn(7); });
     am->AddAction(ID_TAG_LOC9, tr("Location 9"))
         .SetShortcut(tr("Ctrl+F9"))
-        .SetToolTip(tr("Location 9 (Ctrl+F9)"));
+        .SetToolTip(tr("Save Location 9 (Ctrl+F9)"))
+        .Connect(&QAction::triggered, [tagViewBookmarkFn](){ tagViewBookmarkFn(8); });
     am->AddAction(ID_TAG_LOC10, tr("Location 10"))
         .SetShortcut(tr("Ctrl+F10"))
-        .SetToolTip(tr("Location 10 (Ctrl+F10)"));
+        .SetToolTip(tr("Save Location 10 (Ctrl+F10)"))
+        .Connect(&QAction::triggered, [tagViewBookmarkFn](){ tagViewBookmarkFn(9); });
     am->AddAction(ID_TAG_LOC11, tr("Location 11"))
         .SetShortcut(tr("Ctrl+F11"))
-        .SetToolTip(tr("Location 11 (Ctrl+F11)"));
+        .SetToolTip(tr("Save Location 11 (Ctrl+F11)"))
+        .Connect(&QAction::triggered, [tagViewBookmarkFn](){ tagViewBookmarkFn(10); });
     am->AddAction(ID_TAG_LOC12, tr("Location 12"))
         .SetShortcut(tr("Ctrl+F12"))
-        .SetToolTip(tr("Location 12 (Ctrl+F12)"));
+        .SetToolTip(tr("Save Location 12 (Ctrl+F12)"))
+        .Connect(&QAction::triggered, [tagViewBookmarkFn](){ tagViewBookmarkFn(11); });
 
     if (CViewManager::IsMultiViewportEnabled())
     {

+ 3 - 2
Code/Framework/AzCore/AzCore/DOM/DomValue.h

@@ -159,6 +159,9 @@ namespace AZ::Dom
     class Value final
     {
     public:
+        AZ_TYPE_INFO(Value, "{3E20677F-3B8E-4F89-B665-ED41D74F4799}");
+        AZ_CLASS_ALLOCATOR(Value, ValueAllocator, 0);
+
         // Determine the short string buffer size based on the size of our largest internal type (string_view)
         // minus the size of the short string size field.
         static constexpr const size_t ShortStringSize = sizeof(AZStd::string_view) - 2;
@@ -199,8 +202,6 @@ namespace AZ::Dom
         Value(const Value&);
         Value(Value&&) noexcept;
         Value(AZStd::string_view stringView, bool copy);
-        explicit Value(const ValueType&);
-        explicit Value(ValueType&&);
         explicit Value(SharedStringType sharedString);
 
         explicit Value(int8_t value);

+ 3 - 0
Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl

@@ -194,6 +194,9 @@ namespace AZ
             //! For use with slice creation tools. See SliceCreationFlags below for details.
             const static AZ::Crc32 SliceFlags = AZ_CRC("SliceFlags", 0xa447e1fb);
 
+            //! Does the clear button in the LineEdit need to have a test for visibility.
+            const static AZ::Crc32 ShowClearButtonHandler = AZ_CRC_CE("ShowClearButtonHandler");
+
             //! For optional use on Getter Events used for Virtual Properties
             const static AZ::Crc32 PropertyPosition = AZ_CRC("Position", 0x462ce4f5);
             const static AZ::Crc32 PropertyRotation = AZ_CRC("Rotation", 0x297c98f1);

+ 11 - 3
Code/Framework/AzCore/AzCore/base.h

@@ -13,10 +13,18 @@
 
 #include <AzCore/AzCore_Traits_Platform.h>
 
-#ifndef AZ_ARRAY_SIZE
 /// Return an array size for static arrays.
-#   define  AZ_ARRAY_SIZE(__a)  (sizeof(__a)/sizeof(__a[0]))
-#endif
+namespace AZ::Internal
+{
+    template<class T>
+    struct StaticArraySize
+    {
+        static_assert(std::is_array_v<T>, "AZ_ARRAY_SIZE can only be used with a C-style array");
+        static constexpr size_t value = sizeof(T) / sizeof(std::remove_extent_t<T>);
+    };
+}
+#define AZ_ARRAY_SIZE(__a)  AZ::Internal::StaticArraySize<std::remove_reference_t<decltype(__a)>>::value
+
 
 #ifndef AZ_SIZE_ALIGN_UP
 /// Aign to the next bigger/up size

+ 7 - 4
Code/Framework/AzCore/AzCore/std/containers/vector.h

@@ -849,10 +849,13 @@ namespace AZStd
 #endif
 
             size_type offset = firstPtr - m_start;
-            // unless we have 1 elements we have memory overlapping, so we need to use move.
-            pointer newLast = AZStd::move(lastPtr, m_last, firstPtr);
-            Internal::destroy<pointer>::range(newLast, m_last);
-            m_last = newLast;
+            if (firstPtr != lastPtr)
+            {
+                // unless we have 1 elements we have memory overlapping, so we need to use move.
+                pointer newLast = AZStd::move(lastPtr, m_last, firstPtr);
+                Internal::destroy<pointer>::range(newLast, m_last);
+                m_last = newLast;
+            }
             return iterator(AZSTD_POINTER_ITERATOR_PARAMS(m_start)) + offset;
         }
 

+ 1 - 1
Code/Framework/AzCore/AzCore/std/parallel/thread.h

@@ -50,7 +50,7 @@ namespace AZStd
 
     struct thread_desc
     {
-        //! Debug thread name.
+        //! Debug thread name. Limited to 16 characters on Linux.
         const char*     m_name{ "AZStd::thread" };
 
         //! Thread stack size. Default is -1, which means we will use the default stack size for each platform.

+ 10 - 1
Code/Framework/AzCore/Platform/Linux/AzCore/std/parallel/internal/thread_Linux.cpp

@@ -6,6 +6,7 @@
  *
  */
 
+#include <AzCore/std/string/fixed_string.h>
 #include <AzCore/std/parallel/thread.h>
 
 #include <sched.h>
@@ -53,7 +54,15 @@ namespace AZStd
 
         void PostCreateThread(pthread_t tId, const char* name, int)
         {
-            pthread_setname_np(tId, name);
+            if (const int result = pthread_setname_np(tId, name); result == ERANGE)
+            {
+                // The name was too long. pthread limits the name to 16
+                // characters (including the null terminator). Let's elide the
+                // middle.
+                const auto len = strlen(name);
+                const auto elidedName = AZStd::fixed_string<15>{name, 7} + "." + AZStd::fixed_string<15>{name + len - 7, 7};
+                pthread_setname_np(tId, elidedName.c_str());
+            }
         }
 
         uint8_t GetDefaultThreadPriority()

+ 17 - 0
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/AdapterBuilder.cpp

@@ -21,6 +21,23 @@ namespace AZ::DocumentPropertyEditor
         CurrentNode()[attribute] = AZStd::move(value);
     }
 
+    void AdapterBuilder::OnEditorChanged(AZStd::function<void(const Dom::Path&, const Dom::Value&)> onChangedCallback)
+    {
+        // The value path is the first child of the PropertyEditor node
+        Dom::Path changedPath = GetCurrentPath() / 0;
+        CallbackAttribute(
+            Nodes::PropertyEditor::OnChanged,
+            [changedPath, onChangedCallback](const Dom::Value& value)
+            {
+                onChangedCallback(changedPath, value);
+            });
+    }
+
+    Dom::Path AdapterBuilder::GetCurrentPath() const
+    {
+        return m_currentPath;
+    }
+
     bool AdapterBuilder::IsError() const
     {
         return !m_error.empty();

+ 19 - 1
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/AdapterBuilder.h

@@ -59,6 +59,13 @@ namespace AZ::DocumentPropertyEditor
         //! Sets an attribute of the last node. Rows, labels, and property editors all support different attributes.
         //! \see DocumentPropertyEditor::Nodes
         void Attribute(Name attribute, Dom::Value value);
+        //! Adds a Nodes::PropertyEditor::OnChanged attribute that will get called with
+        //! the path of the property value and its new value. This path can be used to generate a
+        //! correct Replace patch for submitting NotifyContentsChanged.
+        void OnEditorChanged(AZStd::function<void(const Dom::Path&, const Dom::Value&)> onChangedCallback);
+
+        //! Gets the path to the DOM node currently being built within this builder's DOM.
+        Dom::Path GetCurrentPath() const;
 
         //! Returns true if an error has been encountered during the build process, 
         bool IsError() const;
@@ -68,6 +75,12 @@ namespace AZ::DocumentPropertyEditor
         //! Operations are no longer valid on this builder once this is called.
         Dom::Value&& FinishAndTakeResult();
 
+        template <class PropertyEditorDefinition>
+        void BeginPropertyEditor(Dom::Value value = {})
+        {
+            BeginPropertyEditor(PropertyEditorDefinition::Name, value);
+        }
+
         template <class NodeDefinition>
         void BeginNode()
         {
@@ -92,12 +105,17 @@ namespace AZ::DocumentPropertyEditor
             Attribute(definition.GetName(), definition.ValueToDom(AZStd::move(value)));
         }
 
+        template <class CallbackType, class Functor>
+        void CallbackAttribute(const CallbackAttributeDefinition<CallbackType>& definition, Functor value)
+        {
+            Attribute(definition.GetName(), definition.ValueToDom(AZStd::function<CallbackType>(value)));
+        }
+
         void Attribute(const AttributeDefinition<AZStd::string_view>& definition, AZStd::string_view value)
         {
             Attribute(definition.GetName(), Dom::Value(value, true));
         }
 
-
     private:
         void Error(AZStd::string_view message);
         Dom::Value& CurrentNode();

+ 1 - 1
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/BasicAdapter.h

@@ -21,7 +21,7 @@ namespace AZ::DocumentPropertyEditor
         //! Resets the contents of this adapter with a new DOM.
         void SetContents(Dom::Value contents);
         Dom::Value GetContents() const override;
-        Dom::PatchOutcome RequestContentChange(const Dom::Patch& patch) override;
+        Dom::PatchOutcome RequestContentChange(const Dom::Patch& patch);
 
     private:
         Dom::Value m_value;

+ 198 - 0
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/CvarAdapter.cpp

@@ -0,0 +1,198 @@
+/*
+ * 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/Console/ConsoleFunctor.h>
+#include <AzCore/Console/IConsole.h>
+#include <AzCore/Interface/Interface.h>
+#include <AzFramework/DocumentPropertyEditor/AdapterBuilder.h>
+#include <AzFramework/DocumentPropertyEditor/CvarAdapter.h>
+
+namespace AZ::DocumentPropertyEditor
+{
+    struct CvarAdapter::Impl
+    {
+        Impl(CvarAdapter* adapter)
+            : m_adapter(adapter)
+        {
+        }
+
+        template<typename T>
+        bool TryBuildNumericEditor(AdapterBuilder& builder, ConsoleFunctorBase* functor)
+        {
+            if (functor->GetTypeId() == azrtti_typeid<T>())
+            {
+                T buffer;
+                functor->GetValue(buffer);
+                builder.BeginPropertyEditor<Nodes::SpinBox<T>>(Dom::Value(buffer));
+                builder.OnEditorChanged(
+                    [this, functor](const Dom::Path& path, const Dom::Value& value)
+                    {
+                        T buffer;
+                        if constexpr (AZStd::is_integral_v<T> && AZStd::is_signed_v<T>)
+                        {
+                            buffer = aznumeric_cast<T>(value.GetInt64());
+                        }
+                        else if constexpr (AZStd::is_integral_v<T> && AZStd::is_unsigned_v<T>)
+                        {
+                            buffer = aznumeric_cast<T>(value.GetUint64());
+                        }
+                        else
+                        {
+                            buffer = aznumeric_cast<T>(value.GetDouble());
+                        }
+                        (*functor)({ ConsoleTypeHelpers::ValueToString(buffer) });
+                        m_adapter->OnContentsChanged(path, value);
+                    });
+                builder.Attribute(Nodes::SpinBox<T>::Min, AZStd::numeric_limits<T>::min());
+                builder.Attribute(Nodes::SpinBox<T>::Max, AZStd::numeric_limits<T>::max());
+                builder.EndPropertyEditor();
+                return true;
+            }
+            return false;
+        }
+
+        template<typename First, typename Second, typename... Rest>
+        bool TryBuildNumericEditor(AdapterBuilder& builder, ConsoleFunctorBase* functor)
+        {
+            if (TryBuildNumericEditor<First>(builder, functor))
+            {
+                return true;
+            }
+            return TryBuildNumericEditor<Second, Rest...>(builder, functor);
+        }
+
+        bool TryBuildStringEditor(AdapterBuilder& builder, ConsoleFunctorBase* functor)
+        {
+            if (functor->GetTypeId() == azrtti_typeid<CVarFixedString>())
+            {
+                CVarFixedString buffer;
+                functor->GetValue(buffer);
+                builder.BeginPropertyEditor<Nodes::LineEdit>(Dom::Value(buffer, true));
+                builder.OnEditorChanged(
+                    [this, functor](const Dom::Path& path, const Dom::Value& value)
+                    {
+                        (*functor)({ value.GetString() });
+                        m_adapter->OnContentsChanged(path, value);
+                    });
+                builder.EndPropertyEditor();
+                return true;
+            }
+            return false;
+        }
+
+        template<typename VectorType, size_t ElementCount, typename NodeType>
+        bool TryBuildMathVectorEditor(AdapterBuilder& builder, ConsoleFunctorBase* functor)
+        {
+            if (functor->GetTypeId() == azrtti_typeid<VectorType>())
+            {
+                VectorType container;
+                functor->GetValue(container);
+                Dom::Value contents(Dom::Type::Array);
+                for (int i = 0; i < ElementCount; ++i)
+                {
+                    contents.ArrayPushBack(Dom::Value(container.GetElement(i)));
+                }
+                builder.BeginPropertyEditor<NodeType>(AZStd::move(contents));
+                builder.OnEditorChanged(
+                    [this, functor](const Dom::Path& path, const Dom::Value& value)
+                    {
+                        // ConsoleCommandContainer holds string_views, so ensure we allocate our parameters here
+                        AZStd::fixed_vector<CVarFixedString, ElementCount> newValue;
+                        for (int i = 0; i < ElementCount; ++i)
+                        {
+                            newValue.push_back(ConsoleTypeHelpers::ValueToString(value[i].GetDouble()));
+                        }
+                        (*functor)(ConsoleCommandContainer(newValue));
+                        m_adapter->OnContentsChanged(path, value);
+                    });
+                builder.EndPropertyEditor();
+                return true;
+            }
+            return false;
+        }
+
+        bool TryBuildCheckBoxEditor(AdapterBuilder& builder, ConsoleFunctorBase* functor)
+        {
+            if (functor->GetTypeId() == azrtti_typeid<bool>())
+            {
+                bool value;
+                functor->GetValue(value);
+                builder.BeginPropertyEditor<Nodes::CheckBox>(Dom::Value(value));
+                builder.OnEditorChanged(
+                    [this, functor](const Dom::Path& path, const Dom::Value& value)
+                    {
+                        (*functor)({ ConsoleTypeHelpers::ValueToString(value.GetBool()) });
+                        m_adapter->OnContentsChanged(path, value);
+                    });
+                builder.EndPropertyEditor();
+                return true;
+            }
+            return false;
+        }
+
+        bool BuildEditorForCvar(AdapterBuilder& builder, ConsoleFunctorBase* functor)
+        {
+            // Check all possible type IDs for our supported types and try to create a property editor
+            return TryBuildNumericEditor<int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t, uint64_t, float, double>(
+                       builder, functor) ||
+                TryBuildStringEditor(builder, functor) || TryBuildMathVectorEditor<AZ::Vector2, 2, Nodes::Vector2>(builder, functor) ||
+                TryBuildMathVectorEditor<AZ::Vector3, 3, Nodes::Vector3>(builder, functor) ||
+                TryBuildMathVectorEditor<AZ::Vector4, 4, Nodes::Vector4>(builder, functor) ||
+                TryBuildMathVectorEditor<AZ::Quaternion, 4, Nodes::Quaternion>(builder, functor) ||
+                TryBuildMathVectorEditor<AZ::Color, 4, Nodes::Color>(builder, functor) || TryBuildCheckBoxEditor(builder, functor);
+        }
+
+        CvarAdapter* m_adapter;
+    };
+
+    CvarAdapter::CvarAdapter()
+        : m_impl(AZStd::make_unique<Impl>(this))
+    {
+    }
+
+    CvarAdapter::~CvarAdapter()
+    {
+    }
+
+    Dom::Value CvarAdapter::GetContents() const
+    {
+        AdapterBuilder builder;
+        builder.BeginAdapter();
+
+        auto consoleInterface = AZ::Interface<AZ::IConsole>::Get();
+        if (consoleInterface != nullptr)
+        {
+            // Enumerate all functors, try to wire up a proper editor for each CVar
+            consoleInterface->VisitRegisteredFunctors(
+                [&](ConsoleFunctorBase* functor)
+                {
+                    // Skip console functors with no registered type ID - CVars all have a type ID set
+                    if (functor->GetTypeId().IsNull())
+                    {
+                        return;
+                    }
+                    builder.BeginRow();
+                    builder.Label(functor->GetName());
+                    if (!m_impl->BuildEditorForCvar(builder, functor))
+                    {
+                        builder.Label("Unknown CVAR type");
+                    }
+                    builder.EndRow();
+                });
+        }
+
+        builder.EndAdapter();
+        return builder.FinishAndTakeResult();
+    }
+
+    void CvarAdapter::OnContentsChanged(const Dom::Path& path, const Dom::Value& value)
+    {
+        // If one of our values has changed, forward a replace patch to the view
+        NotifyContentsChanged({ Dom::PatchOperation::ReplaceOperation(path, value) });
+    }
+} // namespace AZ::DocumentPropertyEditor

+ 31 - 0
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/CvarAdapter.h

@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzFramework/DocumentPropertyEditor/DocumentAdapter.h>
+
+namespace AZ::DocumentPropertyEditor
+{
+    //! An adapter for displaying an editable list of CVars registered to the console instance.
+    //! Supports editing CVars with primitive types, string types, and numeric vector types
+    //! (VectorX, Quaternion, and Color).
+    class CvarAdapter : public DocumentAdapter
+    {
+    public:
+        CvarAdapter();
+        ~CvarAdapter();
+
+        Dom::Value GetContents() const override;
+        void OnContentsChanged(const Dom::Path& path, const Dom::Value& value);
+
+    private:
+        struct Impl;
+        AZStd::unique_ptr<Impl> m_impl;
+    };
+}

+ 0 - 4
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/DocumentAdapter.h

@@ -47,10 +47,6 @@ namespace AZ::DocumentPropertyEditor
         //! Retrieves the contents of this adapter. This must be an Adapter DOM node.
         //! \see AdapterBuilder for building out this DOM structure.
         virtual Dom::Value GetContents() const = 0;
-        //! Called when the view would like to change the current contents - for example, by changing the value of
-        //! a property within a Property Editor. If this patch is accepted and triggers a mutation to the contents of this
-        //! adapter, NotifyContentsChanged should be called to trigger a change event with the accepted patches.
-        virtual Dom::PatchOutcome RequestContentChange(const Dom::Patch& patch) = 0;
 
         //! Connects a listener for the reset event, fired when the contents of this adapter have completely changed.
         //! Any views listening to this adapter will need to call GetContents to retrieve the new contents of the adapter.

+ 101 - 6
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/DocumentSchema.h

@@ -9,8 +9,9 @@
 #pragma once
 
 #include <AzCore/DOM/DomValue.h>
-#include <AzCore/std/string/fixed_string.h>
 #include <AzCore/Name/Name.h>
+#include <AzCore/Outcome/Outcome.h>
+#include <AzCore/std/string/fixed_string.h>
 
 namespace AZ::DocumentPropertyEditor
 {
@@ -45,12 +46,18 @@ namespace AZ::DocumentPropertyEditor
 
     //! Retrieves a node's name from a node definition.
     //! \see NodeDefinition
-    template <typename NodeDefinition>
+    template<typename NodeDefinition>
     Name GetNodeName()
     {
         return AZ::Name(NodeDefinition::Name);
     }
 
+    //! Defines a definition for a PropertyEditor, specified as the type of a PropertyEditor node
+    struct PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "<undefined editor name>";
+    };
+
     //! Defines an attribute applicable to a Node.
     //! Attributes may be defined inline inside of a NodeDefinition.
     //! AttributeDefinitions may be used to marshal types to and from a DOM representation.
@@ -74,17 +81,105 @@ namespace AZ::DocumentPropertyEditor
         //! Converts a value of this attribute's type to a DOM value.
         Dom::Value ValueToDom(const AttributeType& attribute) const
         {
-            return Dom::Value(attribute);
+            if constexpr (AZStd::is_same_v<AZStd::string_view, AttributeType>)
+            {
+                return Dom::Value(attribute, true);
+            }
+            else if constexpr (AZStd::is_constructible_v<Dom::Value, const AttributeType&>)
+            {
+                return Dom::Value(attribute);
+            }
+            else
+            {
+                return Dom::Value::FromOpaqueValue(AZStd::any(attribute));
+            }
         }
 
         //! Converts a DOM value to an instance of AttributeType.
-        AttributeType&& DomToValue(const Dom::Value& value)
+        AttributeType&& DomToValue(const Dom::Value& value) const
         {
             AZ_Assert(false, "DomToValue is not yet implemented");
             return {};
         }
 
-    private:
+    protected:
         AZStd::fixed_string<128> m_name;
     };
-}
+
+    //! Defines a callback applicable to a Node.
+    //! Callbacks are stored as attributes and accept an AZStd::function<CallbackSignature> stored as an
+    //! opaque value. Callbacks can be validated and invokved from DOM values using InvokeOnDomValue
+    //! and InvokeOnDomNode.
+    template<typename CallbackSignature>
+    class CallbackAttributeDefinition : public AttributeDefinition<AZStd::function<CallbackSignature>>
+    {
+    public:
+        using ErrorType = AZStd::fixed_string<128>;
+        using FunctionType = AZStd::function<CallbackSignature>;
+
+        constexpr CallbackAttributeDefinition(AZStd::string_view name)
+            : AttributeDefinition<FunctionType>(name)
+        {
+        }
+
+        template<typename T>
+        struct Traits;
+
+        template<typename Result, typename... Args>
+        struct Traits<Result(Args...)>
+        {
+            using ResultType = AZ::Outcome<Result, ErrorType>;
+
+            static ResultType Invoke(const AZStd::function<Result(Args...)>& fn, Args... args)
+            {
+                return AZ::Success(fn(args...));
+            }
+        };
+
+        template <typename... Args>
+        struct Traits<void(Args...)>
+        {
+            using ResultType = AZ::Outcome<void, ErrorType>;
+
+            static ResultType Invoke(const AZStd::function<void(Args...)>& fn, Args... args)
+            {
+                fn(args...);
+                return AZ::Success();
+            }
+        };
+
+        using CallbackTraits = Traits<CallbackSignature>;
+
+        //! Attempts to call a function with this attribute's callback signature stored in a DOM value as an opaque type.
+        //! Invokes the method with the specified args if our callback signature is found in the value, otherwise returns an error message.
+        template<typename... Args>
+        typename CallbackTraits::ResultType InvokeOnDomValue(const AZ::Dom::Value& value, Args... args) const
+        {
+            if (!value.IsOpaqueValue())
+            {
+                return AZ::Failure<ErrorType>("This property is holding a value and not a callback");
+            }
+
+            const AZStd::any& wrapper = value.GetOpaqueValue();
+            if (!wrapper.is<FunctionType>())
+            {
+                return AZ::Failure<ErrorType>("This property does not contain a callback with the correct signature");
+            }
+
+            return CallbackTraits::Invoke(AZStd::any_cast<FunctionType>(wrapper), args...);
+        }
+
+        //! Attemps to read this attribute from the specified DOM value, which must be a Node.
+        //! Invokes the method with the specified args if this attribute is specified, otherwise returns an error message.
+        template<typename... Args>
+        typename CallbackTraits::ResultType InvokeOnDomNode(const AZ::Dom::Value& value, Args... args) const
+        {
+            auto attributeIt = value.FindMember(this->GetName());
+            if (attributeIt == value.MemberEnd())
+            {
+                return AZ::Failure<ErrorType>(ErrorType::format("No \"%s\" attribute found", this->m_name.data()));
+            }
+            return this->InvokeOnDomValue(attributeIt->second, args...);
+        }
+    };
+} // namespace AZ::DocumentPropertyEditor

+ 98 - 1
Code/Framework/AzFramework/AzFramework/DocumentPropertyEditor/PropertyEditorNodes.h

@@ -39,6 +39,103 @@ namespace AZ::DocumentPropertyEditor::Nodes
     struct PropertyEditor : NodeDefinition
     {
         static constexpr AZStd::string_view Name = "PropertyEditor";
-        static constexpr auto Type = AttributeDefinition<AZStd::string_view>("type");
+        static constexpr auto Type = AttributeDefinition<AZStd::string_view>("Type");
+        static constexpr auto OnChanged = CallbackAttributeDefinition<void(const Dom::Value&)>("OnChanged");
+    };
+
+    template<typename T>
+    struct NumericEditor
+    {
+        static_assert(AZStd::is_floating_point_v<T> || AZStd::is_integral_v<T>, "Numeric editors must have a numeric type");
+        static constexpr auto Min = AttributeDefinition<T>("Min");
+        static constexpr auto Max = AttributeDefinition<T>("Max");
+        static constexpr auto Step = AttributeDefinition<T>("Step");
+        static constexpr auto Suffix = AttributeDefinition<AZStd::string_view>("Suffix");
+        static constexpr auto SoftMin = AttributeDefinition<T>("SoftMin");
+        static constexpr auto SoftMax = AttributeDefinition<T>("SoftMax");
+        static constexpr auto Decimals = AttributeDefinition<int>("Decimals");
+        static constexpr auto DisplayDecimals = AttributeDefinition<int>("DisplayDecimals");
+    };
+
+    struct Button : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "Button";
+    };
+
+    struct CheckBox : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "CheckBox";
+    };
+
+    struct Color : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "Color";
+    };
+
+    struct ComboBox : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "ComboBox";
+    };
+
+    struct RadioButton : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "RadioButton";
+    };
+
+    struct EntityId : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "EntityId";
+    };
+
+    struct LayoutPadding : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "LayoutPadding";
+    };
+
+    struct LineEdit : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "LineEdit";
+    };
+
+    struct MultiLineEdit : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "MultiLineEdit";
+    };
+
+    struct Quaternion : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "Quaternion";
+    };
+
+    template<typename T>
+    struct Slider : NumericEditor<T>
+    {
+        static constexpr AZStd::string_view Name = "Slider";
+    };
+
+    template<typename T>
+    struct SpinBox : NumericEditor<T>
+    {
+        static constexpr AZStd::string_view Name = "SpinBox";
+    };
+
+    struct Crc : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "Crc";
+    };
+
+    struct Vector2 : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "Vector2";
+    };
+
+    struct Vector3 : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "Vector3";
+    };
+
+    struct Vector4 : PropertyEditorDefinition
+    {
+        static constexpr AZStd::string_view Name = "Vector4";
     };
 } // namespace AZ::DocumentPropertyEditor::Nodes

+ 2 - 2
Code/Framework/AzFramework/AzFramework/Network/AssetProcessorConnection.cpp

@@ -73,10 +73,10 @@ namespace AzFramework
             m_retryAfterDisconnect = false;
             m_isBusyDisconnecting = false;
 
-            m_sendThread.m_desc.m_name = "APConnection::SendThread";
+            m_sendThread.m_desc.m_name = "APConnectSend";
             m_sendThread.m_main = AZStd::bind(&AssetProcessorConnection::SendThread, this);
 
-            m_recvThread.m_desc.m_name = "APConnection::RecvThread";
+            m_recvThread.m_desc.m_name = "APConnectRecv";
             m_recvThread.m_main = AZStd::bind(&AssetProcessorConnection::RecvThread, this);
             
             // Put the AP send and receive threads on a core not shared by the main thread or render thread.

+ 3 - 23
Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSceneQueries.h

@@ -84,15 +84,7 @@ namespace AzPhysics
         };
 
         //! Bitwise operators for HitFlags
-        inline HitFlags operator|(HitFlags lhs, HitFlags rhs)
-        {
-            return static_cast<HitFlags>(static_cast<AZ::u16>(lhs) | static_cast<AZ::u16>(rhs));
-        }
-
-        inline HitFlags operator&(HitFlags lhs, HitFlags rhs)
-        {
-            return static_cast<HitFlags>(static_cast<AZ::u16>(lhs) & static_cast<AZ::u16>(rhs));
-        }
+        AZ_DEFINE_ENUM_BITWISE_OPERATORS(HitFlags)
 
         //! Flag used to mark which members are valid in a SceneQueryHit object.
         //! Example: if SceneQueryHit::m_resultFlags & ResultFlags::Distance is true,
@@ -109,21 +101,9 @@ namespace AzPhysics
             Position = (1 << 5),
             Normal = (1 << 6)
         };
-        //! Bitwise operators for ResultFlags
-        inline ResultFlags operator|(ResultFlags lhs, ResultFlags rhs)
-        {
-            return static_cast<ResultFlags>(static_cast<AZ::u8>(lhs) | static_cast<AZ::u8>(rhs));
-        }
 
-        inline ResultFlags operator|=(ResultFlags& lhs, ResultFlags rhs)
-        {
-            return (lhs = (lhs | rhs));
-        }
-
-        inline ResultFlags operator&(ResultFlags lhs, ResultFlags rhs)
-        {
-            return static_cast<ResultFlags>(static_cast<AZ::u8>(lhs) & static_cast<AZ::u8>(rhs));
-        }
+        //! Bitwise operators for ResultFlags
+        AZ_DEFINE_ENUM_BITWISE_OPERATORS(ResultFlags)
 
         //! Callback used for directed scene queries: RayCasts and ShapeCasts
         using FilterCallback = AZStd::function<QueryHitType(const SimulatedBody* body, const Physics::Shape* shape)>;

+ 2 - 9
Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsTypes.h

@@ -104,17 +104,10 @@ namespace AzPhysics
 
         DEFAULT = COMPUTE_COM | COMPUTE_INERTIA | COMPUTE_MASS
     };
+
     //! Bitwise operators for MassComputeFlags
-    inline MassComputeFlags operator|(MassComputeFlags lhs, MassComputeFlags rhs)
-    {
-        return aznumeric_cast<MassComputeFlags>(aznumeric_cast<AZ::u8>(lhs) | aznumeric_cast<AZ::u8>(rhs));
-    }
+    AZ_DEFINE_ENUM_BITWISE_OPERATORS(MassComputeFlags)
 
-    inline MassComputeFlags operator&(MassComputeFlags lhs, MassComputeFlags rhs)
-    {
-        return aznumeric_cast<MassComputeFlags>(aznumeric_cast<AZ::u8>(lhs) & aznumeric_cast<AZ::u8>(rhs));
-    }
-    
     //! Variant to allow support for the system to either create the Shape(s) or use the provide Shape(s) that have been created externally.
     //! Can be one of the following.
     //! @code{ .cpp }

+ 19 - 1
Code/Framework/AzFramework/AzFramework/Physics/HeightfieldProviderBus.h

@@ -46,6 +46,8 @@ namespace Physics
         uint16_t m_padding{ 0 }; //!< available for future use.
     };
 
+    using UpdateHeightfieldSampleFunction = AZStd::function<void(int32_t, int32_t, const Physics::HeightMaterialPoint&)>;
+
     //! An interface to provide heightfield values.
     class HeightfieldProviderRequests
         : public AZ::ComponentBus
@@ -104,6 +106,9 @@ namespace Physics
         //! Returns the list of heights and materials used by the height field.
         //! @return the rows*columns vector of the heights and materials.
         virtual AZStd::vector<Physics::HeightMaterialPoint> GetHeightsAndMaterials() const = 0;
+
+        //! Updates the list of heights and materials within the region. Pass Null region to update the entire list.
+        virtual void UpdateHeightsAndMaterials(const UpdateHeightfieldSampleFunction& updateHeightsMaterialsCallback, const AZ::Aabb& region) const = 0;
     };
 
     using HeightfieldProviderRequestsBus = AZ::EBus<HeightfieldProviderRequests>;
@@ -115,9 +120,20 @@ namespace Physics
     public:
         static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
 
+        enum class HeightfieldChangeMask : AZ::u8
+        {
+            None = 0,
+            Settings = (1 << 0),
+            HeightData = (1 << 1),
+            MaterialData = (1 << 2),
+            SurfaceData = (1 << 3),
+            Unspecified = 0xff
+        };
+
         //! Called whenever the heightfield data changes.
         //! @param the AABB of the area of data that changed.
-        virtual void OnHeightfieldDataChanged([[maybe_unused]] const AZ::Aabb& dirtyRegion)
+        virtual void OnHeightfieldDataChanged([[maybe_unused]] const AZ::Aabb& dirtyRegion, 
+            [[maybe_unused]] Physics::HeightfieldProviderNotifications::HeightfieldChangeMask changeMask)
         {
         }
 
@@ -125,5 +141,7 @@ namespace Physics
         ~HeightfieldProviderNotifications() = default;
     };
 
+    AZ_DEFINE_ENUM_BITWISE_OPERATORS(HeightfieldProviderNotifications::HeightfieldChangeMask)
+
     using HeightfieldProviderNotificationBus = AZ::EBus<HeightfieldProviderNotifications>;
 } // namespace Physics

+ 1 - 1
Code/Framework/AzFramework/AzFramework/Physics/Mocks/MockHeightfieldProviderBus.h

@@ -28,6 +28,6 @@ namespace UnitTest
             Physics::HeightfieldProviderNotificationBus::Handler::BusDisconnect();
         }
 
-        MOCK_METHOD1(OnHeightfieldDataChanged, void(const AZ::Aabb&));
+        MOCK_METHOD2(OnHeightfieldDataChanged, void(const AZ::Aabb&, Physics::HeightfieldProviderNotifications::HeightfieldChangeMask));
     };
 } // namespace UnitTest

+ 15 - 0
Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp

@@ -413,6 +413,21 @@ namespace Physics
         return m_samples;
     }
 
+    void HeightfieldShapeConfiguration::ModifySample(int32_t row, int32_t column, const Physics::HeightMaterialPoint& point)
+    {
+        const int32_t index = row * m_numColumns + column;
+        if (row < m_numRows && column < m_numColumns && index < m_samples.size())
+        {
+            m_samples[index] = point;
+        }
+        else
+        {
+            AZ_Error("HeightfieldShapeConfiguration", false,
+                "Trying to modify a sample out of range. Row: %d, Col: %d, NumColumns: %d, NumRows: %d",
+                row, column, m_numColumns, m_numRows);
+        }
+    }
+
     void HeightfieldShapeConfiguration::SetSamples(const AZStd::vector<Physics::HeightMaterialPoint>& samples)
     {
         m_samples = samples;

+ 1 - 0
Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h

@@ -228,6 +228,7 @@ namespace Physics
         int32_t GetNumRows() const;
         void SetNumRows(int32_t numRows);
         const AZStd::vector<Physics::HeightMaterialPoint>& GetSamples() const;
+        void ModifySample(int32_t row, int32_t column, const Physics::HeightMaterialPoint& point);
         void SetSamples(const AZStd::vector<Physics::HeightMaterialPoint>& samples);
         float GetMinHeightBounds() const;
         void SetMinHeightBounds(float minBounds);

+ 2 - 0
Code/Framework/AzFramework/AzFramework/azframework_files.cmake

@@ -144,6 +144,8 @@ set(FILES
     DocumentPropertyEditor/DocumentSchema.h
     DocumentPropertyEditor/PropertyEditorNodes.cpp
     DocumentPropertyEditor/PropertyEditorNodes.h
+    DocumentPropertyEditor/CvarAdapter.cpp
+    DocumentPropertyEditor/CvarAdapter.h
     FileFunc/FileFunc.h
     FileFunc/FileFunc.cpp
     Font/FontInterface.h

+ 3 - 3
Code/Framework/AzFramework/Tests/DocumentPropertyEditor/AdapterBuilderTests.cpp

@@ -14,9 +14,9 @@
 
 namespace AZ::DocumentPropertyEditor::Tests
 {
-    using AdapterBuilderTests = DocumentPropertyEditorTestFixture;
+    using AdapterBuilderDpeTests = DocumentPropertyEditorTestFixture;
 
-    TEST_F(AdapterBuilderTests, VisitSimpleStructure)
+    TEST_F(AdapterBuilderDpeTests, VisitSimpleStructure)
     {
         AdapterBuilder builder;
         builder.BeginAdapter();
@@ -54,7 +54,7 @@ namespace AZ::DocumentPropertyEditor::Tests
         EXPECT_TRUE(Dom::Utils::DeepCompareIsEqual(expectedDom, domFromBuilder));
     }
 
-    TEST_F(AdapterBuilderTests, VisitNestedRows)
+    TEST_F(AdapterBuilderDpeTests, VisitNestedRows)
     {
         AdapterBuilder builder;
         builder.BeginAdapter();

+ 167 - 0
Code/Framework/AzFramework/Tests/DocumentPropertyEditor/CvarAdapterTests.cpp

@@ -0,0 +1,167 @@
+/*
+ * 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/Console/Console.h>
+#include <AzCore/Console/IConsole.h>
+#include <AzCore/Console/IConsoleTypes.h>
+#include <AzCore/Interface/Interface.h>
+#include <AzFramework/DocumentPropertyEditor/AdapterBuilder.h>
+#include <AzFramework/DocumentPropertyEditor/CvarAdapter.h>
+#include <AzFramework/DocumentPropertyEditor/PropertyEditorNodes.h>
+#include <Tests/DocumentPropertyEditor/DocumentPropertyEditorFixture.h>
+
+namespace AZ::DocumentPropertyEditor::Tests
+{
+    AZ_CVAR(int32_t, dpe_TestInt, 1, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "DPE test int32");
+    AZ_CVAR(uint8_t, dpe_TestUint, 22, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "DPE test uint8");
+    AZ_CVAR(double, dpe_TestDbl, 4.0, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "DPE test double");
+    AZ_CVAR(CVarFixedString, dpe_TestString, "test", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "DPE test string");
+    AZ_CVAR(bool, dpe_TestBool, false, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "DPE test bool");
+    AZ_CVAR(AZ::Vector2, dpe_TestVec2, AZ::Vector2::CreateZero(), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "DPE test vec2");
+    AZ_CVAR(AZ::Vector3, dpe_TestVec3, AZ::Vector3::CreateOne(), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "DPE test vec3");
+    AZ_CVAR(AZ::Color, dpe_TestColor, AZ::Color(), nullptr, ConsoleFunctorFlags::DontReplicate, "DPE test color");
+
+    class CvarAdapterDpeTests : public DocumentPropertyEditorTestFixture
+    {
+    public:
+        void SetUp() override
+        {
+            DocumentPropertyEditorTestFixture::SetUp();
+            m_console = AZStd::make_unique<AZ::Console>();
+            m_console->LinkDeferredFunctors(AZ::ConsoleFunctorBase::GetDeferredHead());
+            AZ::Interface<AZ::IConsole>::Register(m_console.get());
+            m_adapter = AZStd::make_unique<CvarAdapter>();
+        }
+
+        void TearDown() override
+        {
+            m_adapter.reset();
+            AZ::Interface<AZ::IConsole>::Unregister(m_console.get());
+            m_console.reset();
+            DocumentPropertyEditorTestFixture::TearDown();
+        }
+
+        Dom::Value GetEntryRow(AZStd::string_view cvarName)
+        {
+            Dom::Value rows = m_adapter->GetContents();
+            for (auto it = rows.ArrayBegin(); it != rows.ArrayEnd(); ++it)
+            {
+                Dom::Value label = (*it)[0].GetNodeValue();
+                if (label.GetString() == cvarName)
+                {
+                    return *it;
+                }
+            }
+            return {};
+        }
+
+        Dom::Value GetEntryValue(AZStd::string_view cvarName)
+        {
+            Dom::Value row = GetEntryRow(cvarName);
+            EXPECT_FALSE(row.IsNull());
+            return row[1].GetNodeValue();
+        }
+
+        void SetEntryValue(AZStd::string_view cvarName, Dom::Value value)
+        {
+            Dom::Value row = GetEntryRow(cvarName);
+            ASSERT_FALSE(row.IsNull());
+            auto result = Nodes::PropertyEditor::OnChanged.InvokeOnDomNode(row[1], value);
+            EXPECT_TRUE(result.IsSuccess());
+            AZ_Error("CvarAdapterDpeTests", result.IsSuccess(), "%s", result.GetError().c_str());
+        }
+
+        AZStd::unique_ptr<AZ::Console> m_console;
+        AZStd::unique_ptr<CvarAdapter> m_adapter;
+    };
+
+    TEST_F(CvarAdapterDpeTests, IntCvar)
+    {
+        EXPECT_EQ(static_cast<int32_t>(dpe_TestInt), GetEntryValue("dpe_TestInt").GetInt64());
+        SetEntryValue("dpe_TestInt", Dom::Value(42));
+        EXPECT_EQ(42, dpe_TestInt);
+        EXPECT_EQ(42, GetEntryValue("dpe_TestInt").GetInt64());
+    }
+
+    TEST_F(CvarAdapterDpeTests, UintCvar)
+    {
+        EXPECT_EQ(static_cast<uint8_t>(dpe_TestUint), GetEntryValue("dpe_TestUint").GetUint64());
+        SetEntryValue("dpe_TestUint", Dom::Value(42));
+        EXPECT_EQ(42, dpe_TestUint);
+        EXPECT_EQ(42, GetEntryValue("dpe_TestUint").GetUint64());
+    }
+
+    TEST_F(CvarAdapterDpeTests, DoubleCvar)
+    {
+        EXPECT_EQ(static_cast<double>(dpe_TestDbl), GetEntryValue("dpe_TestDbl").GetDouble());
+        SetEntryValue("dpe_TestDbl", Dom::Value(6.28));
+        EXPECT_EQ(6.28, dpe_TestDbl);
+        EXPECT_EQ(6.28, GetEntryValue("dpe_TestDbl").GetDouble());
+    }
+
+    TEST_F(CvarAdapterDpeTests, StringCvar)
+    {
+        EXPECT_EQ(static_cast<CVarFixedString>(dpe_TestString), GetEntryValue("dpe_TestString").GetString());
+        SetEntryValue("dpe_TestString", Dom::Value("new string", true));
+        EXPECT_EQ("new string", static_cast<CVarFixedString>(dpe_TestString));
+        EXPECT_EQ("new string", GetEntryValue("dpe_TestString").GetString());
+    }
+
+    TEST_F(CvarAdapterDpeTests, BoolCvar)
+    {
+        EXPECT_EQ(static_cast<bool>(dpe_TestBool), GetEntryValue("dpe_TestBool").GetBool());
+        SetEntryValue("dpe_TestBool", Dom::Value(true));
+        EXPECT_EQ(true, static_cast<bool>(dpe_TestBool));
+        EXPECT_EQ(true, GetEntryValue("dpe_TestBool").GetBool());
+    }
+
+    TEST_F(CvarAdapterDpeTests, Vec2Cvar)
+    {
+        Dom::Value value = GetEntryValue("dpe_TestVec2");
+        EXPECT_EQ(static_cast<AZ::Vector2>(dpe_TestVec2), AZ::Vector2((float)value[0].GetDouble(), (float)value[1].GetDouble()));
+        value[0].SetDouble(2.0);
+        value[1].SetDouble(4.5);
+        SetEntryValue("dpe_TestVec2", value);
+        value = GetEntryValue("dpe_TestVec2");
+        EXPECT_EQ(2.0, GetEntryValue("dpe_TestVec2")[0].GetDouble());
+        EXPECT_EQ(4.5, GetEntryValue("dpe_TestVec2")[1].GetDouble());
+        EXPECT_EQ(AZ::Vector2(2.0f, 4.5f), static_cast<AZ::Vector2>(dpe_TestVec2));
+    }
+
+    TEST_F(CvarAdapterDpeTests, Vec3Cvar)
+    {
+        Dom::Value value = GetEntryValue("dpe_TestVec3");
+        EXPECT_EQ(
+            static_cast<AZ::Vector3>(dpe_TestVec3),
+            AZ::Vector3((float)value[0].GetDouble(), (float)value[1].GetDouble(), (float)value[2].GetDouble()));
+        value[1].SetDouble(5.0);
+        SetEntryValue("dpe_TestVec3", value);
+        value = GetEntryValue("dpe_TestVec3");
+        EXPECT_EQ(5.0, GetEntryValue("dpe_TestVec3")[1].GetDouble());
+        EXPECT_EQ(5.f, static_cast<AZ::Vector3>(dpe_TestVec3).GetY());
+    }
+
+    TEST_F(CvarAdapterDpeTests, ColorCvar)
+    {
+        Dom::Value value = GetEntryValue("dpe_TestColor");
+        EXPECT_EQ(
+            static_cast<AZ::Color>(dpe_TestColor),
+            AZ::Color((float)value[0].GetDouble(), (float)value[1].GetDouble(), (float)value[2].GetDouble(), (float)value[3].GetDouble()));
+        value[0].SetDouble(0.0);
+        value[1].SetDouble(1.0);
+        value[2].SetDouble(0.5);
+        value[3].SetDouble(0.25);
+        SetEntryValue("dpe_TestColor", value);
+        value = GetEntryValue("dpe_TestColor");
+        EXPECT_EQ(0.0, GetEntryValue("dpe_TestColor")[0].GetDouble());
+        EXPECT_EQ(1.0, GetEntryValue("dpe_TestColor")[1].GetDouble());
+        EXPECT_EQ(0.5, GetEntryValue("dpe_TestColor")[2].GetDouble());
+        EXPECT_EQ(0.25, GetEntryValue("dpe_TestColor")[3].GetDouble());
+        EXPECT_EQ(AZ::Color(0.f, 1.f, 0.5f, 0.25f), static_cast<AZ::Color>(dpe_TestColor));
+    }
+} // namespace AZ::DocumentPropertyEditor::Tests

+ 57 - 0
Code/Framework/AzFramework/Tests/DocumentPropertyEditor/SchemaTests.cpp

@@ -0,0 +1,57 @@
+/*
+ * 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/DOM/DomUtils.h>
+#include <AzCore/std/any.h>
+#include <AzFramework/DocumentPropertyEditor/AdapterBuilder.h>
+#include <AzFramework/DocumentPropertyEditor/PropertyEditorNodes.h>
+#include <Tests/DocumentPropertyEditor/DocumentPropertyEditorFixture.h>
+
+namespace AZ::DocumentPropertyEditor::Tests
+{
+    class SchemaDpeTests : public DocumentPropertyEditorTestFixture
+    {
+    public:
+        static constexpr auto intAttr = AttributeDefinition<int>("intAttr");
+        static constexpr auto doubleAttr = AttributeDefinition<double>("doubleAttr");
+        static constexpr auto strAttr = AttributeDefinition<AZStd::string_view>("strAttr");
+        static constexpr auto fnAttr = CallbackAttributeDefinition<int(int, int)>("fnAttr");
+    };
+
+    TEST_F(SchemaDpeTests, ValueToDom)
+    {
+        Dom::Value v;
+        v = intAttr.ValueToDom(2);
+        EXPECT_EQ(2, v.GetInt64());
+        v = doubleAttr.ValueToDom(4.5);
+        EXPECT_EQ(4.5, v.GetDouble());
+        v = strAttr.ValueToDom("test string");
+        EXPECT_EQ("test string", v.GetString());
+    }
+
+    TEST_F(SchemaDpeTests, InvokeCallback)
+    {
+        Dom::Value v = fnAttr.ValueToDom(
+            [](int x, int y)
+            {
+                return x + y;
+            });
+        EXPECT_EQ(5, fnAttr.InvokeOnDomValue(v, 2, 3).GetValue());
+        EXPECT_EQ(0, fnAttr.InvokeOnDomValue(v, 5, -5).GetValue());
+        EXPECT_FALSE(fnAttr.InvokeOnDomValue(Dom::Value(), 1, 2).IsSuccess());
+        EXPECT_FALSE(fnAttr
+                         .InvokeOnDomValue(
+                             Dom::Value::FromOpaqueValue(AZStd::any(
+                                 AZStd::function<int(int)>([](int x)
+                                 {
+                                     return x;
+                                 }))),
+                             1, 2)
+                         .IsSuccess());
+    }
+} // namespace AZ::DocumentPropertyEditor::Tests

+ 2 - 0
Code/Framework/AzFramework/Tests/frameworktests_files.cmake

@@ -34,4 +34,6 @@ set(FILES
     CameraState.cpp
     InputTests.cpp
     DocumentPropertyEditor/AdapterBuilderTests.cpp
+    DocumentPropertyEditor/SchemaTests.cpp
+    DocumentPropertyEditor/CvarAdapterTests.cpp
 )

+ 36 - 0
Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h

@@ -12,6 +12,7 @@
 #include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
 #include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
 #include <AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h>
+#include <AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h>
 #include <AzToolsFramework/ViewportSelection/EditorDefaultSelection.h>
 #include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
 #include <type_traits>
@@ -53,4 +54,39 @@ namespace UnitTest
     //! dependent on AzToolsFramework::ToolsApplication.
     using IndirectCallManipulatorViewportInteractionFixture =
         IndirectCallManipulatorViewportInteractionFixtureMixin<ToolsApplicationFixture>;
+
+    //! Fixture to provide the direct call viewport interaction that is dependent on AllocatorsTestFixture.
+    //! \tparam FixtureT The fixture that provides the AllocatorsTestFixture functionality.
+    template<typename FixtureT>
+    class DirectCallManipulatorViewportInteractionFixtureMixin : public FixtureT
+    {
+        using DirectCallManipulatorViewportInteraction = AzManipulatorTestFramework::DirectCallManipulatorViewportInteraction;
+        using ImmediateModeActionDispatcher = AzManipulatorTestFramework::ImmediateModeActionDispatcher;
+
+    public:
+        void SetUp() override
+        {
+            FixtureT::SetUp();
+            m_viewportManipulatorInteraction =
+                AZStd::make_unique<DirectCallManipulatorViewportInteraction>(AZStd::make_shared<NullDebugDisplayRequests>());
+            m_actionDispatcher = AZStd::make_unique<ImmediateModeActionDispatcher>(*m_viewportManipulatorInteraction);
+            m_cameraState =
+                AzFramework::CreateIdentityDefaultCamera(AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize);
+        }
+
+        void TearDown() override
+        {
+            m_actionDispatcher.reset();
+            m_viewportManipulatorInteraction.reset();
+            FixtureT::TearDown();
+        }
+
+        AzFramework::CameraState m_cameraState;
+        AZStd::unique_ptr<ImmediateModeActionDispatcher> m_actionDispatcher;
+        AZStd::unique_ptr<DirectCallManipulatorViewportInteraction> m_viewportManipulatorInteraction;
+    };
+
+    //! Fixture to provide the direct call viewport interaction that inherits from AllocatorsTestFixture for minimal overhead.
+    using DirectCallManipulatorViewportInteractionFixture =
+        DirectCallManipulatorViewportInteractionFixtureMixin<AllocatorsTestFixture>;
 } // namespace UnitTest

+ 3 - 0
Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h

@@ -26,6 +26,9 @@ namespace AzManipulatorTestFramework
         // ManipulatorViewportInteractionInterface ...
         const ViewportInteractionInterface& GetViewportInteraction() const override;
         const ManipulatorManagerInterface& GetManipulatorManager() const override;
+        // make non-const overloads visible
+        using ManipulatorViewportInteraction::GetManipulatorManager;
+        using ManipulatorViewportInteraction::GetViewportInteraction;
 
     private:
         AZStd::shared_ptr<CustomManipulatorManager> m_customManager;

+ 2 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp

@@ -71,6 +71,7 @@
 #include <AzToolsFramework/UI/EditorEntityUi/EditorEntityUiSystemComponent.h>
 #include <AzToolsFramework/Undo/UndoCacheInterface.h>
 #include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
+#include <AzToolsFramework/Viewport/ViewBookmarkSystemComponent.h>
 #include <Entity/EntityUtilityComponent.h>
 #include <AzToolsFramework/Script/LuaSymbolsReporterSystemComponent.h>
 #include <Prefab/ProceduralPrefabSystemComponent.h>
@@ -275,6 +276,7 @@ namespace AzToolsFramework
                 azrtti_typeid<Prefab::PrefabSystemComponent>(),
                 azrtti_typeid<Prefab::ProceduralPrefabSystemComponent>(),
                 azrtti_typeid<EditorEntityFixupComponent>(),
+                azrtti_typeid<AzToolsFramework::ViewBookmarkSystemComponent>(),
                 azrtti_typeid<Components::EditorComponentAPIComponent>(),
                 azrtti_typeid<Components::EditorLevelComponentAPIComponent>(),
                 azrtti_typeid<Components::EditorEntityActionComponent>(),

+ 5 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp

@@ -56,6 +56,9 @@
 #include <AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.h>
 #include <AzToolsFramework/Entity/EntityUtilityComponent.h>
 #include <AzToolsFramework/Script/LuaSymbolsReporterSystemComponent.h>
+#include <AzToolsFramework/Viewport/SharedViewBookmarkComponent.h>
+#include <AzToolsFramework/Viewport/LocalViewBookmarkComponent.h>
+#include <AzToolsFramework/Viewport/ViewBookmarkSystemComponent.h>
 #include <Prefab/ProceduralPrefabSystemComponent.h>
 
 AZ_DEFINE_BUDGET(AzToolsFramework);
@@ -84,6 +87,8 @@ namespace AzToolsFramework
             Prefab::PrefabSystemComponent::CreateDescriptor(),
             Prefab::EditorPrefabComponent::CreateDescriptor(),
             Prefab::ProceduralPrefabSystemComponent::CreateDescriptor(),
+            AzToolsFramework::ViewBookmarkSystemComponent::CreateDescriptor(),
+            AzToolsFramework::LocalViewBookmarkComponent::CreateDescriptor(),
             Components::EditorEntityActionComponent::CreateDescriptor(),
             Components::EditorEntityIconComponent::CreateDescriptor(),
             Components::EditorInspectorComponent::CreateDescriptor(),

+ 5 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h

@@ -43,6 +43,11 @@ namespace AzToolsFramework
 
         //! Returns whether the entity id provided is part of the focused sub-tree.
         virtual bool IsInFocusSubTree(AZ::EntityId entityId) const = 0;
+
+        //! Verifies if the entityId provided matches with the current focus root.
+        //! @return True if the entity provided is the focus root, false otherwise.
+        virtual bool IsFocusRoot(AZ::EntityId entityId) const = 0;
+
     };
 
 } // namespace AzToolsFramework

+ 14 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp

@@ -126,6 +126,20 @@ namespace AzToolsFramework
         return AzToolsFramework::IsInFocusSubTree(entityId, m_focusRoot);
     }
 
+    bool FocusModeSystemComponent::IsFocusRoot(AZ::EntityId entityId) const
+    {
+        if (m_focusRoot.IsValid())
+        {
+            return (entityId == m_focusRoot);
+        }
+        else
+        {
+            AZ::EntityId parentId;
+            EditorEntityInfoRequestBus::EventResult(parentId, entityId, &EditorEntityInfoRequestBus::Events::GetParent);
+            return !parentId.IsValid();
+        }
+    }
+
     void FocusModeSystemComponent::OnEntityInfoUpdatedAddChildEnd(AZ::EntityId parentId, AZ::EntityId childId)
     {
         // If the parent's entityId is in the list and the child isn't, add the child to the list.

+ 1 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h

@@ -46,6 +46,7 @@ namespace AzToolsFramework
         void SetFocusRoot(AZ::EntityId entityId) override;
         void ClearFocusRoot(AzFramework::EntityContextId entityContextId) override;
         AZ::EntityId GetFocusRoot(AzFramework::EntityContextId entityContextId) override;
+        bool IsFocusRoot(AZ::EntityId entityId) const override;
         const EntityIdList& GetFocusedEntities(AzFramework::EntityContextId entityContextId) override;
         bool IsInFocusSubTree(AZ::EntityId entityId) const override;
 

+ 7 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/SourceControl/PerforceComponent.cpp

@@ -80,7 +80,13 @@ namespace AzToolsFramework
 
         // set up signals before we start thread.
         m_shutdownThreadSignal = false;
-        m_WorkerThread = AZStd::thread(AZStd::bind(&PerforceComponent::ThreadWorker, this));
+        m_WorkerThread = AZStd::thread(
+            { /*m_name =*/ "Perforce worker" },
+            [this]
+            {
+                ThreadWorker();
+            }
+        );
 
         SourceControlConnectionRequestBus::Handler::BusConnect();
         SourceControlCommandBus::Handler::BusConnect();

+ 14 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp

@@ -28,6 +28,7 @@
 #include <AzToolsFramework/API/ToolsApplicationAPI.h>
 #include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
 #include <AzToolsFramework/Entity/EditorEntityContextBus.h>
+#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
 #include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
 #include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
 #include <AzToolsFramework/ToolsComponents/TransformComponentBus.h>
@@ -927,6 +928,12 @@ namespace AzToolsFramework
 
             AZ::EntityId actualValue = static_cast<AZ::EntityId>(*((AZ::EntityId*)newValue));
 
+            if (!actualValue.IsValid())
+            {
+                // Handled by the calling code.
+                return AZ::Success();
+            }
+
             // Prevent setting the parent to the entity itself.
             if (actualValue == GetEntityId())
             {
@@ -1177,6 +1184,12 @@ namespace AzToolsFramework
             return AZ::Edit::PropertyRefreshLevels::EntireTree;
         }
 
+        bool TransformComponent::ShowClearButtonHandler()
+        {
+            // Hide the clear button if the current entity is the focus root, which is the default value.
+            return(!m_focusModeInterface->IsFocusRoot(GetParentId()));
+        }
+
         void TransformComponent::Reflect(AZ::ReflectContext* context)
         {
             // reflect data for script, serialization, editing..
@@ -1215,6 +1228,7 @@ namespace AzToolsFramework
                             Attribute(AZ::Edit::Attributes::ChangeValidate, &TransformComponent::ValidatePotentialParent)->
                             Attribute(AZ::Edit::Attributes::ChangeNotify, &TransformComponent::ParentChangedInspector)->
                             Attribute(AZ::Edit::Attributes::SliceFlags, AZ::Edit::SliceFlags::DontGatherReference | AZ::Edit::SliceFlags::NotPushableOnSliceRoot)->
+                            Attribute(AZ::Edit::Attributes::ShowClearButtonHandler, &TransformComponent::ShowClearButtonHandler)->
                         DataElement(AZ::Edit::UIHandlers::Default, &TransformComponent::m_editorTransform, "Values", "")->
                             Attribute(AZ::Edit::Attributes::ChangeNotify, &TransformComponent::TransformChangedInspector)->
                             Attribute(AZ::Edit::Attributes::AutoExpand, true)->

+ 2 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h

@@ -161,6 +161,8 @@ namespace AzToolsFramework
             void UpdateCachedWorldTransform();
             void ClearCachedWorldTransform();
 
+            bool ShowClearButtonHandler();
+
             // SliceEntityHierarchyRequestBus
             AZ::EntityId GetSliceEntityParentId() override;
             AZStd::vector<AZ::EntityId> GetSliceEntityChildren() override;

+ 31 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp

@@ -39,6 +39,7 @@ AZ_POP_DISABLE_WARNING
 #include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
 #include <AzToolsFramework/Entity/EditorEntityRuntimeActivationBus.h>
 #include <AzToolsFramework/Entity/SliceEditorEntityOwnershipServiceBus.h>
+#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
 #include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
 #include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
 #include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
@@ -501,6 +502,11 @@ namespace AzToolsFramework
         m_readOnlyEntityPublicInterface = AZ::Interface<ReadOnlyEntityPublicInterface>::Get();
         AZ_Assert(m_readOnlyEntityPublicInterface != nullptr, "EntityPropertyEditor requires a ReadOnlyEntityPublicInterface instance on Initialize.");
 
+        m_focusModeInterface = AZ::Interface<AzToolsFramework::FocusModeInterface>::Get();
+        AZ_Assert(m_focusModeInterface != nullptr, "EntityPropertyEditor requires a FocusModeInterface instance on Initialize.");
+
+        m_containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get();
+
         setObjectName("EntityPropertyEditor");
         setAcceptDrops(true);
 
@@ -5666,15 +5672,40 @@ namespace AzToolsFramework
         AZ_PROFILE_FUNCTION(AzToolsFramework);
         AzToolsFramework::EditorInspectorComponentNotificationBus::MultiHandler::BusConnect(entityId);
         AzToolsFramework::PropertyEditorEntityChangeNotificationBus::MultiHandler::BusConnect(entityId);
+        AzFramework::EntityContextId editorEntityContextId = AzFramework::EntityContextId::CreateNull();
+        EditorEntityContextRequestBus::BroadcastResult(
+            editorEntityContextId, &EditorEntityContextRequestBus::Events::GetEditorEntityContextId);
+        AzToolsFramework::FocusModeNotificationBus::Handler::BusConnect(editorEntityContextId);
     }
 
     void EntityPropertyEditor::DisconnectFromEntityBuses(const AZ::EntityId& entityId)
     {
         AZ_PROFILE_FUNCTION(AzToolsFramework);
+        AzToolsFramework::FocusModeNotificationBus::Handler::BusDisconnect();
         AzToolsFramework::EditorInspectorComponentNotificationBus::MultiHandler::BusDisconnect(entityId);
         AzToolsFramework::PropertyEditorEntityChangeNotificationBus::MultiHandler::BusDisconnect(entityId);
     }
 
+    void EntityPropertyEditor::OnEditorFocusChanged(
+        [[maybe_unused]] AZ::EntityId previousFocusEntityId, [[maybe_unused]] AZ::EntityId newFocusEntityId)
+    {
+        // We need to wait for the Container Entity System to update before checking
+        QTimer::singleShot( 1, this, [this]()
+            {
+                bool enable = true;
+                for (AZ::EntityId entityId : m_overrideSelectedEntityIds)
+                {
+                    if (!m_focusModeInterface->IsInFocusSubTree(entityId) ||
+                        m_containerEntityInterface->IsUnderClosedContainerEntity(entityId))
+                    {
+                        enable = false;
+                        break;
+                    }
+                }
+                SetEditorUiEnabled(enable);
+            });
+    }
+
     static void SetPropertyEditorState(Ui::EntityPropertyEditorUI* propertyEditorUi, const bool on)
     {
         // enable/disable all widgets relating to the entity inspector that should

+ 12 - 1
Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx

@@ -28,8 +28,10 @@
 #include <AzToolsFramework/API/EntityPropertyEditorRequestsBus.h>
 #include <AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h>
 #include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
+#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
 #include <AzToolsFramework/Entity/EditorEntityContextBus.h>
 #include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityBus.h>
+#include <AzToolsFramework/FocusMode/FocusModeNotificationBus.h>
 #include <AzToolsFramework/ToolsComponents/ComponentMimeData.h>
 #include <AzToolsFramework/ToolsComponents/EditorInspectorComponentBus.h>
 #include <AzQtComponents/Components/O3DEStylesheet.h>
@@ -64,7 +66,9 @@ namespace AzToolsFramework
     class ComponentModeCollectionInterface;
     struct SourceControlFileInfo;
     class ReadOnlyEntityPublicInterface;
-
+    class FocusModeInterface;
+    class ContainerEntityInterface;
+ 
     namespace AssetBrowser
     {
         class ProductAssetBrowserEntry;
@@ -119,6 +123,7 @@ namespace AzToolsFramework
         , public AZ::TickBus::Handler
         , private EditorWindowUIRequestBus::Handler
         , private ReadOnlyEntityPublicNotificationBus::Handler
+        , public FocusModeNotificationBus::Handler
     {
         Q_OBJECT;
     public:
@@ -159,6 +164,9 @@ namespace AzToolsFramework
         void SetPropertyEditingComplete(InstanceDataNode* pNode) override;
         void SealUndoStack() override;
 
+        // FocusModeNotificationBus overrides ...
+        void OnEditorFocusChanged(AZ::EntityId previousFocusEntityId, AZ::EntityId newFocusEntityId) override;
+
         // Context menu population for entity component properties.
         void RequestPropertyContextMenu(InstanceDataNode* node, const QPoint& globalPos) override;
 
@@ -635,6 +643,9 @@ namespace AzToolsFramework
         // Reordering row widgets within the RPE.
         static constexpr float MoveFadeSeconds = 0.5f;
 
+        FocusModeInterface* m_focusModeInterface = nullptr;
+        ContainerEntityInterface* m_containerEntityInterface = nullptr;
+
         ReorderState m_currentReorderState = ReorderState::Inactive;
         ComponentEditor* m_reorderRowWidgetEditor = nullptr;
         InstanceDataNode* m_nodeToMove = nullptr;

+ 9 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp

@@ -331,6 +331,7 @@ namespace AzToolsFramework
 
     void PropertyEntityIdCtrl::SetCurrentEntityId(const AZ::EntityId& newEntityId, bool emitChange, const AZStd::string& nameOverride)
     {
+        m_entityIdLineEdit->setClearButtonEnabled(HasClearButton());
         m_entityIdLineEdit->SetEntityId(newEntityId, nameOverride);
         m_componentsSatisfyingServices.clear();
 
@@ -515,6 +516,14 @@ namespace AzToolsFramework
                 GUI->SetIncompatibleServices(incompatibleServices);
             }
         }
+        else if (attrib == AZ::Edit::Attributes::ShowClearButtonHandler)
+        {
+            bool value;
+            if (attrValue->Read<bool>(value))
+            {
+                GUI->SetHasClearButton(value);
+            }
+        }
     }
 
     void EntityIdPropertyHandler::WriteGUIValuesIntoProperty(size_t index, PropertyEntityIdCtrl* GUI, property_t& instance, InstanceDataNode* node)

+ 4 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.hxx

@@ -72,6 +72,9 @@ namespace AzToolsFramework
 
         void SetAcceptedEntityContext(AzFramework::EntityContextId contextId);
 
+        void SetHasClearButton(bool value){ m_hasClearButton = value; }
+        bool HasClearButton(){ return m_hasClearButton; }
+
     signals:
         void OnEntityIdChanged(AZ::EntityId newEntityId);
 
@@ -99,6 +102,7 @@ namespace AzToolsFramework
         AzFramework::EntityContextId m_acceptedEntityContextId;
         AZStd::list<AZStd::string> m_componentsSatisfyingServices;
 
+        bool m_hasClearButton{ true };
         QIcon m_pickerIcon;
     };
 

+ 6 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.cpp

@@ -402,6 +402,12 @@ namespace AzToolsFramework
     {
         Initialize(groupName, pParent, depth, labelWidth);
         ChangeSourceNode(node);
+
+        // Need to invoke RefreshAttributesFromNode manually since it won't be called
+        // by this version of Initialize so that any change notify (along with other attributes)
+        // will be respected when toggling the group element
+        RefreshAttributesFromNode(true);
+
         CreateGroupToggleSwitch();
     }
 

+ 1 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/Mocks/MockFocusModeInterface.h

@@ -25,5 +25,6 @@ namespace UnitTest
         MOCK_METHOD1(GetFocusRoot, AZ::EntityId(AzFramework::EntityContextId entityContextId));
         MOCK_METHOD1(GetFocusedEntities, const AzToolsFramework::EntityIdList&(AzFramework::EntityContextId entityContextId));
         MOCK_CONST_METHOD1(IsInFocusSubTree, bool(AZ::EntityId entityId));
+        MOCK_CONST_METHOD1(IsFocusRoot, bool(AZ::EntityId entityId));
     };
 } // namespace UnitTest

+ 51 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/LocalViewBookmarkComponent.cpp

@@ -0,0 +1,51 @@
+/*
+ * 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/RTTI/ReflectContext.h>
+#include <AzCore/Serialization/EditContext.h>
+#include <Viewport/ViewBookmarkLoaderInterface.h>
+#include <AzToolsFramework/Viewport/LocalViewBookmarkComponent.h>
+
+namespace AzToolsFramework
+{
+    void LocalViewBookmarkComponent::Reflect(AZ::ReflectContext* context)
+    {
+        ViewBookmark::Reflect(context);
+
+        if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serializeContext->Class<LocalViewBookmarkComponent, EditorComponentBase>()->Field(
+                "LocalBookmarkFileName", &LocalViewBookmarkComponent::m_localBookmarksFileName);
+            if (AZ::EditContext* editContext = serializeContext->GetEditContext())
+            {
+                editContext
+                    ->Class<LocalViewBookmarkComponent>(
+                        "Local View Bookmark Component",
+                        "The Local View Bookmark Component allows the user to store bookmarks in a custom setreg file.")
+                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "Local View Bookmarks")
+                    ->Attribute(AZ::Edit::Attributes::AddableByUser, true)
+                    ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Level"))
+                    ->Attribute(AZ::Edit::Attributes::Category, "View Bookmarks")
+                    ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
+                    ->DataElement(
+                        AZ::Edit::UIHandlers::Default, &LocalViewBookmarkComponent::m_localBookmarksFileName, "Local Bookmarks File Name", "");
+            }
+        }
+    }
+
+    const AZStd::string& LocalViewBookmarkComponent::GetLocalBookmarksFileName() const
+    {
+        return m_localBookmarksFileName;
+    }
+
+    void LocalViewBookmarkComponent::SetLocalBookmarksFileName(AZStd::string localBookmarksFileName)
+    {
+        m_localBookmarksFileName = AZStd::move(localBookmarksFileName);
+    }
+
+} // namespace AzToolsFramework

+ 31 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/LocalViewBookmarkComponent.h

@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+#pragma once
+
+#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
+
+namespace AzToolsFramework
+{
+    //! @class LocalViewBookmarkComponent.
+    //! @brief Component that stores the name of the local View bookmark file associated to the prefab.
+    class LocalViewBookmarkComponent : public AzToolsFramework::Components::EditorComponentBase
+    {
+    public:
+
+        AZ_EDITOR_COMPONENT(LocalViewBookmarkComponent, "{28E5C3B7-3732-4EFB-985E-3F578A83A357}", EditorComponentBase);
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        const AZStd::string& GetLocalBookmarksFileName() const;
+        void SetLocalBookmarksFileName(AZStd::string localBookmarksFileName);
+
+    private:
+        //! name of the local View bookmark file associated to the prefab. located in project/user/SettingsRegistry/ViewBookmarks.
+        AZStd::string m_localBookmarksFileName;
+    };
+} // namespace AzToolsFramework

+ 514 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/LocalViewBookmarkLoader.cpp

@@ -0,0 +1,514 @@
+/*
+ * 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 <API/ToolsApplicationAPI.h>
+#include <AzCore/Settings/SettingsRegistry.h>
+#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
+#include <AzCore/StringFunc/StringFunc.h>
+#include <AzCore/Utils/Utils.h>
+#include <Entity/PrefabEditorEntityOwnershipInterface.h>
+#include <Prefab/PrefabSystemComponentInterface.h>
+#include <Viewport/LocalViewBookmarkLoader.h>
+
+namespace AzToolsFramework
+{
+    static constexpr const char* ViewBookmarksRegistryPath = "/O3DE/ViewBookmarks/";
+    static constexpr const char* LocalBookmarksKey = "LocalBookmarks";
+    static constexpr const char* LastKnownLocationKey = "LastKnownLocation";
+
+    // Temporary value until there is UI to expose the fields.
+    static constexpr int NumOfDefaultLocationsInLevel = 12;
+
+    void LocalViewBookmarkLoader::RegisterViewBookmarkLoaderInterface()
+    {
+        AZ::Interface<ViewBookmarkLoaderInterface>::Register(this);
+    }
+
+    void LocalViewBookmarkLoader::UnregisterViewBookmarkLoaderInterface()
+    {
+        AZ::Interface<ViewBookmarkLoaderInterface>::Unregister(this);
+    }
+
+    void LocalViewBookmarkLoader::SaveBookmarkSettingsFile()
+    {
+        auto registry = AZ::SettingsRegistry::Get();
+        if (!registry)
+        {
+            AZ_Warning("LocalViewBookmarkLoader", false, "Unable to access global settings registry. Editor Preferences cannot be saved");
+            return;
+        }
+
+        // Resolve path to user project folder
+        AZ::IO::FixedMaxPath editorBookmarkFilePath = AZ::IO::FixedMaxPath(AZ::Utils::GetProjectPath()) / "user/Registry/ViewBookmarks/";
+
+        editorBookmarkFilePath /= m_bookmarkfileName;
+
+        AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings;
+        dumperSettings.m_prettifyOutput = true;
+
+        AZStd::string bookmarkKey = "/" + m_bookmarkfileName;
+
+        dumperSettings.m_includeFilter = [&bookmarkKey](AZStd::string_view path)
+        {
+            AZStd::string_view o3dePrefixPath(bookmarkKey);
+            return o3dePrefixPath.starts_with(path.substr(0, o3dePrefixPath.size()));
+        };
+
+        AZStd::string stringBuffer;
+        AZ::IO::ByteContainerStream stringStream(&stringBuffer);
+        if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(*registry, "", stringStream, dumperSettings))
+        {
+            AZ_Warning(
+                "LocalViewBookmarkLoader", false, R"(Unable to save changes to the Editor Preferences registry file at "%s"\n)",
+                editorBookmarkFilePath.c_str());
+            return;
+        }
+
+        bool saved = false;
+        constexpr auto configurationMode =
+            AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY;
+        if (AZ::IO::SystemFile outputFile; outputFile.Open(editorBookmarkFilePath.c_str(), configurationMode))
+        {
+            saved = outputFile.Write(stringBuffer.data(), stringBuffer.size()) == stringBuffer.size();
+        }
+
+        // Once written to the desired file remove the key from the settings registry
+        registry->Remove(bookmarkKey + "/");
+        AZ_Warning(
+            "LocalViewBookmarkLoader", saved, R"(Unable to save Local View Bookmark file to path "%s"\n)", editorBookmarkFilePath.c_str());
+    }
+
+    bool LocalViewBookmarkLoader::SaveBookmark(const ViewBookmark& bookmark)
+    {
+        return SaveLocalBookmark(bookmark, ViewBookmarkType::Standard);
+    }
+
+    bool LocalViewBookmarkLoader::ModifyBookmarkAtIndex(const ViewBookmark& bookmark, int index)
+    {
+        if (index < 0 || index > m_localBookmarkCount)
+        {
+            return false;
+        }
+
+        LoadDefaultLocalViewBookmarks();
+
+        AZStd::string finalPath = "/" + m_bookmarkfileName + "/LocalBookmarks/" + AZStd::to_string(index);
+
+        bool success = false;
+        if (auto registry = AZ::SettingsRegistry::Get())
+        {
+            success = registry->SetObject(finalPath, bookmark);
+        }
+
+        // If we managed to add the bookmark
+        if (success)
+        {
+            SaveBookmarkSettingsFile();
+            LoadViewBookmarks();
+        }
+        return success;
+    }
+
+    bool LocalViewBookmarkLoader::SaveLastKnownLocation(const ViewBookmark& bookmark)
+    {
+        return SaveLocalBookmark(bookmark, ViewBookmarkType::LastKnownLocation);
+    }
+
+    bool LocalViewBookmarkLoader::LoadViewBookmarks()
+    {
+        struct ViewBookmarkVisitor : AZ::SettingsRegistryInterface::Visitor
+        {
+            ViewBookmarkVisitor()
+                : m_viewBookmarksKey{ "/O3DE/ViewBookmarks" } {};
+
+            AZ::SettingsRegistryInterface::VisitResponse Traverse(
+                AZStd::string_view path,
+                AZStd::string_view,
+                AZ::SettingsRegistryInterface::VisitAction action,
+                AZ::SettingsRegistryInterface::Type) override
+            {
+                if (action == AZ::SettingsRegistryInterface::VisitAction::Begin)
+                {
+                    // Strip off the last JSON pointer key from the path and if it matches the viewmark key then add an entry
+                    // to the ViewBookmark Map
+                    AZStd::optional<AZStd::string_view> localBookmarksID = AZ::StringFunc::TokenizeLast(path, "/");
+                    if (path == m_viewBookmarksKey && localBookmarksID && !localBookmarksID->empty())
+                    {
+                        AZStd::string_view bookmarkKey = localBookmarksID.value();
+
+                        if (auto existingBookmarkEntry = m_bookmarkMap.find(bookmarkKey) == m_bookmarkMap.end())
+                        {
+                            m_bookmarkMap.insert(AZStd::make_pair(bookmarkKey, AZStd::vector<ViewBookmark>{}));
+                        }
+                    }
+                }
+
+                return AZ::SettingsRegistryInterface::VisitResponse::Continue;
+            }
+
+            using AZ::SettingsRegistryInterface::Visitor::Visit;
+            void Visit(AZStd::string_view path, AZStd::string_view valueIndex, AZ::SettingsRegistryInterface::Type, double value) override
+            {
+                AZ::StringFunc::TokenizeLast(path, "/");
+                AZStd::optional<AZStd::string_view> dataType = AZ::StringFunc::TokenizeLast(path, "/");
+                AZStd::optional<AZStd::string_view> bookmarkIndexStr = AZ::StringFunc::TokenizeLast(path, "/");
+                AZStd::optional<AZStd::string_view> bookmarkType;
+                if (bookmarkIndexStr == LastKnownLocationKey)
+                {
+                    bookmarkType = bookmarkIndexStr;
+                }
+                else
+                {
+                    // differentiate between local Bookmarks and LastKnownLocation
+                    bookmarkType = AZ::StringFunc::TokenizeLast(path, "/");
+                }
+                AZStd::optional<AZStd::string_view> localBookmarksID = AZ::StringFunc::TokenizeLast(path, "/");
+
+                if (path == m_viewBookmarksKey && localBookmarksID && !localBookmarksID->empty())
+                {
+                    auto setVec3Fn = [value](AZ::Vector3& inout, int currentIndex)
+                    {
+                        switch (currentIndex)
+                        {
+                        case 0:
+                            inout.SetX(aznumeric_cast<float>(value));
+                            break;
+                        case 1:
+                            inout.SetY(aznumeric_cast<float>(value));
+                            break;
+                        case 2:
+                            inout.SetZ(aznumeric_cast<float>(value));
+                            break;
+                        default:
+                            AZ_Warning("LocalViewBookmarkLoader", false, "Trying to set an invalid index in a Vector3, index = %d", currentIndex);
+                            break;
+                        }
+                    };
+
+                    if (bookmarkType == LastKnownLocationKey)
+                    {
+                        int currentIndex = stoi(AZStd::string(valueIndex));
+                        if (dataType == "Position")
+                        {
+                            setVec3Fn(m_lastKnownLocation.m_position, currentIndex);
+                        }
+                        else if (dataType == "Rotation")
+                        {
+                            setVec3Fn(m_lastKnownLocation.m_rotation, currentIndex);
+                        }
+                    }
+                    else if (bookmarkType == LocalBookmarksKey)
+                    {
+                        auto existingBookmarkEntry = m_bookmarkMap.find(localBookmarksID.value());
+                        if (existingBookmarkEntry != m_bookmarkMap.end())
+                        {
+                            AZStd::vector<ViewBookmark>& bookmarks = existingBookmarkEntry->second;
+                            // if it is the first bookmark and it is the Position data it means it is the first one
+                            // and we have to create the Bookmark.
+                            if (valueIndex == "0" && dataType == "Position")
+                            {
+                                ViewBookmark bookmark;
+                                bookmark.m_position.SetX(aznumeric_cast<float>(value));
+                                bookmarks.push_back(bookmark);
+                            }
+                            else
+                            {
+                                int bookmarkIndex = stoi(AZStd::string(bookmarkIndexStr->data()));
+                                ViewBookmark& bookmark = bookmarks.at(bookmarkIndex);
+                                int currentIndex = stoi(AZStd::string(valueIndex));
+
+                                if (dataType == "Position")
+                                {
+                                    setVec3Fn(bookmark.m_position, currentIndex);
+                                }
+                                else if (dataType == "Rotation")
+                                {
+                                    setVec3Fn(bookmark.m_rotation, currentIndex);
+                                }
+                            }
+                        }
+                    }
+                }
+            };
+
+            const AZ::SettingsRegistryInterface::FixedValueString m_viewBookmarksKey;
+            AZStd::unordered_map<AZStd::string, AZStd::vector<ViewBookmark>> m_bookmarkMap;
+            ViewBookmark m_lastKnownLocation;
+        };
+
+        if (LocalViewBookmarkComponent* bookmarkComponent = RetrieveLocalViewBookmarkComponent())
+        {
+            // Get the file we want to merge into the settings registry.
+            if (!bookmarkComponent->GetLocalBookmarksFileName().empty())
+            {
+                auto registry = AZ::SettingsRegistry::Get();
+                if (!registry)
+                {
+                    AZ_Warning(
+                        "LocalViewBookmarkLoader", false, "Unable to access global settings registry. Editor Preferences cannot be saved");
+                    return false;
+                }
+
+                auto projectUserRegistryPath = AZ::IO::FixedMaxPath(AZ::Utils::GetProjectPath()) / "user/Registry/ViewBookmarks";
+                projectUserRegistryPath /= AZ::IO::FixedMaxPathString(bookmarkComponent->GetLocalBookmarksFileName());
+
+                // Merge the current viewBookmark file into the settings registry.
+                bool isMerged = registry->MergeSettingsFile(
+                    projectUserRegistryPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, "/O3DE/ViewBookmarks");
+
+                if (isMerged)
+                {
+                    m_bookmarkfileName = bookmarkComponent->GetLocalBookmarksFileName();
+                    using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
+                    AZStd::string bookmarkKey = ViewBookmarksRegistryPath + m_bookmarkfileName;
+                    auto viewBookmarkSettingsKey = FixedValueString::format("%s",bookmarkKey.c_str());
+                    ViewBookmarkVisitor viewBookmarkVisitor;
+
+                    const bool visitedViewBookmarks = registry->Visit(viewBookmarkVisitor, viewBookmarkSettingsKey);
+
+                    if (visitedViewBookmarks)
+                    {
+                        m_localBookmarks = viewBookmarkVisitor.m_bookmarkMap.at(m_bookmarkfileName);
+                        m_localBookmarkCount = m_localBookmarks.size() - 1;
+                        m_lastKnownLocation = viewBookmarkVisitor.m_lastKnownLocation;
+                    }
+
+                    // once loaded we can remove the data from the settings registry.
+                    registry->Remove(bookmarkKey + "/");
+                    return visitedViewBookmarks;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    AZStd::optional<ViewBookmark> LocalViewBookmarkLoader::LoadBookmarkAtIndex(int index)
+    {
+        LoadViewBookmarks();
+        if (index >= 0 && index < m_localBookmarks.size())
+        {
+            return AZStd::optional<ViewBookmark>(m_localBookmarks.at(index));
+        }
+        AZ_Warning("LocalViewBookmarkLoader", false, "Couldn't load View Bookmark from file.");
+        return AZStd::nullopt;
+    }
+
+    bool LocalViewBookmarkLoader::RemoveBookmarkAtIndex(int index)
+    {
+        if (index < 0 || index > m_localBookmarkCount)
+        {
+            return false;
+        }
+
+        AZStd::string finalPath = "/" + m_bookmarkfileName + "/LocalBookmarks/" + AZStd::to_string(index);
+
+        bool success = false;
+        if (auto registry = AZ::SettingsRegistry::Get())
+        {
+            success = registry->Remove(finalPath);
+        }
+
+        if (!success)
+        {
+            AZ_Warning("LocalViewBookmarkLoader", false, "couldn't remove View Bookmark at index %d", index);
+            return false;
+        }
+
+        // If we managed to remove the bookmark
+        SaveBookmarkSettingsFile();
+        LoadViewBookmarks();
+
+        return success;
+
+    }
+
+    AZStd::optional<ViewBookmark> LocalViewBookmarkLoader::LoadLastKnownLocation() const
+    {
+        return m_lastKnownLocation;
+    }
+
+    LocalViewBookmarkComponent* LocalViewBookmarkLoader::RetrieveLocalViewBookmarkComponent()
+    {
+        AZ::EntityId levelEntityId;
+        AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
+            levelEntityId, &AzToolsFramework::ToolsApplicationRequests::GetCurrentLevelEntityId);
+
+        if (!levelEntityId.IsValid())
+        {
+            return nullptr;
+        }
+
+        AZ::Entity* levelEntity = nullptr;
+        AZ::ComponentApplicationBus::BroadcastResult(levelEntity, &AZ::ComponentApplicationBus::Events::FindEntity, levelEntityId);
+
+        if (!levelEntity)
+        {
+            return nullptr;
+        }
+
+        LocalViewBookmarkComponent* bookmarkComponent = levelEntity->FindComponent<LocalViewBookmarkComponent>();
+        if (bookmarkComponent)
+        {
+            return bookmarkComponent;
+        }
+
+        // If we didn't find a component then we add it and return it.
+        levelEntity->Deactivate();
+        levelEntity->CreateComponent<LocalViewBookmarkComponent>();
+        levelEntity->Activate();
+        bookmarkComponent = levelEntity->FindComponent<LocalViewBookmarkComponent>();
+        
+        AZ_Assert(bookmarkComponent, "Couldn't create LocalViewBookmarkComponent.");
+        return bookmarkComponent;
+    }
+
+    AZStd::string LocalViewBookmarkLoader::GenerateBookmarkFileName() const
+    {
+        auto* prefabEditorEntityOwnershipInterface = AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get();
+        AZ_Assert(prefabEditorEntityOwnershipInterface != nullptr, "PrefabEditorEntityOwnershipInterface is not found.");
+        AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId();
+
+        if (rootPrefabTemplateId == AzToolsFramework::Prefab::InvalidTemplateId)
+        {
+            return AZStd::string();
+        }
+
+        auto* prefabSystemComponent = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
+        AZ_Assert(
+            prefabSystemComponent != nullptr,
+            "Prefab System Component Interface could not be found. "
+            "It is a requirement for the LocalViewBookmarkLoader class. "
+            "Check that it is being correctly initialized.");
+
+        auto prefabTemplate = prefabSystemComponent->FindTemplate(rootPrefabTemplateId);
+        AZStd::string prefabTemplateName = prefabTemplate->get().GetFilePath().Filename().Stem().Native();
+
+        // To generate the file name in which we will store the view Bookmarks we use the name of the prefab + the timestamp
+        // e.g. LevelName_1639763579377.setreg
+        AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now();
+        AZStd::string sTime = AZStd::string::format("%llu", now.time_since_epoch().count());
+        return prefabTemplateName.data() + AZStd::string("_") + sTime + ".setreg";
+    }
+
+    bool LocalViewBookmarkLoader::LoadDefaultLocalViewBookmarks()
+    {
+        // Write to the settings registry
+        auto registry = AZ::SettingsRegistry::Get();
+        if (!registry)
+        {
+            AZ_Warning("LocalViewBookmarkLoader", false, "Couldn't load Settings Registry");
+            return false;
+        }
+
+        LocalViewBookmarkComponent* bookmarkComponent = RetrieveLocalViewBookmarkComponent();
+        if (!bookmarkComponent)
+        {
+            AZ_Warning("LocalViewBookmarkLoader", false, "Couldn't find a LocalViewBookmarkComponent");
+            return false;
+        }
+
+        // if the field is not empty then we have a file linked to the prefab.
+        if (!bookmarkComponent->GetLocalBookmarksFileName().empty())
+        {
+            m_bookmarkfileName = bookmarkComponent->GetLocalBookmarksFileName();
+
+            AZ::IO::FixedMaxPath editorBookmarkFilePath = AZ::IO::FixedMaxPath(AZ::Utils::GetProjectPath()) / "user/Registry/ViewBookmarks/";
+            editorBookmarkFilePath /= m_bookmarkfileName;
+            AZ::IO::SystemFile outputFile;
+
+            //If the file doesn't exist but we got a valid filename from source control then let's create the file.
+            if (!outputFile.Exists(editorBookmarkFilePath.c_str()))
+            {
+                constexpr auto configurationMode = AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH |
+                    AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY;
+                outputFile.Open(editorBookmarkFilePath.c_str(), configurationMode);
+
+                // Initialize default locations to 0. This is a temporary solution to match the 12 locations of the legacy system.
+                // Once there is a UI for the view bookmarks these lines should be removed.
+                for (int i = 0; i < NumOfDefaultLocationsInLevel; i++)
+                {
+                    AZStd::string finalPath =
+                        "/" + m_bookmarkfileName + "/LocalBookmarks/" + AZStd::to_string(m_localBookmarkCount++);
+                    registry->SetObject(finalPath, ViewBookmark());
+                }
+
+                LoadViewBookmarks();
+                return true;
+            }
+            else
+            {
+                LoadViewBookmarks();
+
+                for (int i = 0; i < m_localBookmarks.size(); i++)
+                {
+                    AZStd::string finalPath = "/" + m_bookmarkfileName + "/LocalBookmarks/" + AZStd::to_string(i);
+                    registry->SetObject(finalPath, m_localBookmarks.at(i));
+                }
+
+                return true;
+            }
+        }
+        else // if the field is empty we don't have a file linked to the prefab, so we create one and we save it in the
+             // component
+        {
+            m_bookmarkfileName = GenerateBookmarkFileName();
+
+            // Initialize default locations to 0
+            for (int i = 0; i < NumOfDefaultLocationsInLevel; i++)
+            {
+                AZStd::string finalPath = "/" + m_bookmarkfileName + "/LocalBookmarks/" + AZStd::to_string(m_localBookmarkCount++);
+                registry->SetObject(finalPath, ViewBookmark());
+            }
+
+            LoadViewBookmarks();
+            bookmarkComponent->SetLocalBookmarksFileName(m_bookmarkfileName);
+            return true;
+        }
+    }
+
+    bool LocalViewBookmarkLoader::SaveLocalBookmark(const ViewBookmark& bookmark, ViewBookmarkType bookmarkType)
+    {
+        LoadDefaultLocalViewBookmarks();
+
+        AZStd::string finalPath;
+
+        switch (bookmarkType)
+        {
+        case ViewBookmarkType::Standard:
+            finalPath = "/" + m_bookmarkfileName + "/LocalBookmarks/" + AZStd::to_string(m_localBookmarkCount++);
+            break;
+        case ViewBookmarkType::LastKnownLocation:
+            finalPath = "/" + m_bookmarkfileName + "/LastKnownLocation";
+            break;
+        }
+
+        bool success = false;
+        // Write to the settings registry
+        if (auto registry = AZ::SettingsRegistry::Get())
+        {
+            success = registry->SetObject(finalPath, bookmark);
+        }
+
+        if (!success)
+        {
+             AZ_Warning(
+                 "LocalViewBookmarkLoader", false, "View Bookmark x=%.4f, y=%.4f, z=%.4f couldn't be saved", bookmark.m_position.GetX(),
+                 bookmark.m_position.GetY(), bookmark.m_position.GetZ());
+            return false; 
+        }
+
+        // If we managed to add the bookmark
+        SaveBookmarkSettingsFile();
+
+        //Once we have written into our viewbookmark file let's load the new values.
+        LoadViewBookmarks();
+
+        return success;
+    }
+} // namespace AzToolsFramework

+ 58 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/LocalViewBookmarkLoader.h

@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+#include <AzCore/Settings/SettingsRegistryImpl.h>
+#include <Viewport/LocalViewBookmarkComponent.h>
+#include <Viewport/ViewBookmarkLoaderInterface.h>
+
+namespace AzToolsFramework
+{
+    //! @class LocalViewBookmarkLoader.
+    //! @brief class used to load/store local ViewBookmarks from project/user/Registry/ViewBookmarks.
+    class LocalViewBookmarkLoader final : public ViewBookmarkLoaderInterface
+    {
+    public:
+        AZ_CLASS_ALLOCATOR(LocalViewBookmarkLoader, AZ::SystemAllocator, 0);
+        AZ_RTTI(LocalViewBookmarkLoader, "{A64F2300-0958-4430-9EEA-1D457997E618}", ViewBookmarkLoaderInterface);
+
+        enum class ViewBookmarkType : int
+        {
+            Standard,
+            LastKnownLocation
+        };
+
+        void RegisterViewBookmarkLoaderInterface();
+        void UnregisterViewBookmarkLoaderInterface();
+
+        bool SaveBookmark(const ViewBookmark& bookmark) override;
+        bool ModifyBookmarkAtIndex(const ViewBookmark& bookmark, int index) override;
+        bool SaveLastKnownLocation(const ViewBookmark& bookmark) override;
+        bool RemoveBookmarkAtIndex(int index) override;
+
+        AZStd::optional<ViewBookmark> LoadBookmarkAtIndex(int index) override;
+        AZStd::optional<ViewBookmark> LoadLastKnownLocation() const override;
+
+    private:
+        bool LoadViewBookmarks() override;
+        void SaveBookmarkSettingsFile() override;
+        bool SaveLocalBookmark(const ViewBookmark& bookmark, ViewBookmarkType bookmarkType);
+        bool LoadDefaultLocalViewBookmarks();
+
+        LocalViewBookmarkComponent* RetrieveLocalViewBookmarkComponent();
+
+        AZStd::string GenerateBookmarkFileName() const;
+
+    private:
+        AZStd::vector<ViewBookmark> m_localBookmarks;
+        AZStd::optional<ViewBookmark> m_lastKnownLocation = AZStd::nullopt;
+        size_t m_localBookmarkCount = 0;
+        AZStd::string m_bookmarkfileName;
+    };
+
+} // namespace AzToolsFramework

+ 111 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/SharedViewBookmarkComponent.cpp

@@ -0,0 +1,111 @@
+/*
+ * 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/RTTI/BehaviorContext.h>
+#include <AzCore/Serialization/EditContext.h>
+#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Utils/Utils.h>
+#include <AzToolsFramework/Viewport/SharedViewBookmarkComponent.h>
+
+namespace AzToolsFramework
+{
+    void EditorViewBookmarks::Reflect(AZ::ReflectContext* context)
+    {
+        if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serializeContext->Class<EditorViewBookmarks>()->Field("ViewBookmarks", &EditorViewBookmarks::m_viewBookmarks);
+
+            if (AZ::EditContext* editContext = serializeContext->GetEditContext())
+            {
+                editContext->Class<EditorViewBookmarks>("EditorViewBookmarks", "")
+                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "Editor View Bookmarks")
+                    ->DataElement(AZ::Edit::UIHandlers::Default, &EditorViewBookmarks::m_viewBookmarks, "View Bookmarks", "")
+                    ->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, true)
+                    ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
+                    ->Attribute(AZ::Edit::Attributes::IndexedChildNameLabelOverride, &EditorViewBookmarks::GetBookmarkLabel);
+            }
+        }
+    }
+
+    AZStd::string EditorViewBookmarks::GetBookmarkLabel(int index) const
+    {
+        return AZStd::string::format("View Bookmark %d", index);
+    }
+
+    void SharedViewBookmarkComponent::Reflect(AZ::ReflectContext* context)
+    {
+        EditorViewBookmarks::Reflect(context);
+
+        if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serializeContext->RegisterGenericType<EditorViewBookmarks>();
+
+            serializeContext->Class<SharedViewBookmarkComponent, EditorComponentBase>()->Version(0)->Field(
+                "ViewBookmarks", &SharedViewBookmarkComponent::m_viewBookmark);
+
+            if (AZ::EditContext* editContext = serializeContext->GetEditContext())
+            {
+                editContext
+                    ->Class<SharedViewBookmarkComponent>(
+                        "Shared View Bookmark Component", "The ViewBookmark Component allows to store bookmarks for a prefab")
+                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+                    ->Attribute(AZ::Edit::Attributes::AddableByUser, false)
+                    ->Attribute(AZ::Edit::Attributes::Category, "View Bookmarks")
+                    ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
+                    ->DataElement(
+                        AZ::Edit::UIHandlers::Default, &SharedViewBookmarkComponent::m_viewBookmark, "ViewBookmarks", "ViewBookmarks")
+                    ->Attribute(AZ::Edit::Attributes::AutoExpand, false);
+            }
+        }
+    }
+
+    AZStd::optional<ViewBookmark> SharedViewBookmarkComponent::GetBookmarkAtIndex(int index) const
+    {
+        if (index >= 0 && index < m_viewBookmark.m_viewBookmarks.size())
+        {
+            return AZStd::optional<ViewBookmark>(m_viewBookmark.m_viewBookmarks[index]);
+        }
+        return AZStd::nullopt;
+    }
+
+    void SharedViewBookmarkComponent::AddBookmark(ViewBookmark viewBookmark)
+    {
+        m_viewBookmark.m_viewBookmarks.push_back(AZStd::move(viewBookmark));
+    }
+
+    bool SharedViewBookmarkComponent::RemoveBookmarkAtIndex(int index)
+    {
+        if (index >= 0 && index < m_viewBookmark.m_viewBookmarks.size())
+        {
+            m_viewBookmark.m_viewBookmarks.erase(m_viewBookmark.m_viewBookmarks.cbegin() + index);
+            return true;
+        }
+
+        return false;
+    }
+
+    bool SharedViewBookmarkComponent::ModifyBookmarkAtIndex(int index, const ViewBookmark& newBookmark)
+    {
+        if (index >= 0 && index < m_viewBookmark.m_viewBookmarks.size())
+        {
+            m_viewBookmark.m_viewBookmarks[index] = newBookmark;
+            return true;
+        }
+        return false;
+    }
+
+    void SharedViewBookmarkComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
+    {
+        services.push_back(AZ_CRC_CE("EditorViewbookmarkingService"));
+    }
+
+    void SharedViewBookmarkComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services)
+    {
+        services.push_back(AZ_CRC_CE("EditorViewbookmarkingService"));
+    }
+
+} // namespace AzToolsFramework

+ 55 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/SharedViewBookmarkComponent.h

@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+#pragma once
+
+#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
+#include <Viewport/ViewBookmarkLoaderInterface.h>
+
+namespace AzToolsFramework
+{
+    //! @class EditorViewBookmarks.
+    //! @brief struct that stores a vector of View bookmarks.
+    struct EditorViewBookmarks final
+    {
+        AZ_CLASS_ALLOCATOR(EditorViewBookmarks, AZ::SystemAllocator, 0);
+        AZ_TYPE_INFO(EditorViewBookmarks, "{EA0B8FF9-F706-4115-8226-E3F54F1EE8A1}");
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        AZStd::string GetBookmarkLabel(int index) const;
+
+        AZStd::vector<ViewBookmark> m_viewBookmarks;
+    };
+
+    //! @class SharedViewBookmarkComponent.
+    //! @brief component that stores a vector of View bookmarks stored in the prefab.
+    //! so they can be shared in version control easily.
+    class SharedViewBookmarkComponent : public AzToolsFramework::Components::EditorComponentBase
+    {
+    public:
+        static constexpr const char* const ViewBookmarkComponentTypeId = "{6959832F-9382-4C7D-83AC-380DA9F138DE}";
+
+        AZ_EDITOR_COMPONENT(SharedViewBookmarkComponent, ViewBookmarkComponentTypeId, EditorComponentBase);
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        AZStd::optional<ViewBookmark> GetBookmarkAtIndex(int index) const;
+        void AddBookmark(ViewBookmark viewBookmark);
+        bool RemoveBookmarkAtIndex(int index);
+        bool ModifyBookmarkAtIndex(int index, const ViewBookmark& newBookmark);
+
+    protected:
+        static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services);
+        static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services);
+
+    private:
+        //! A user editable list of View Bookmarks
+        EditorViewBookmarks m_viewBookmark;
+    };
+
+} // namespace AzToolsFramework

+ 88 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewBookmarkLoaderInterface.h

@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Math/Vector3.h>
+#include <AzCore/Interface/Interface.h>
+#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Serialization/EditContext.h>
+
+
+namespace AzToolsFramework
+{
+    //! @class ViewBookmark
+    //! @brief struct that store viewport camera properties that can be serialized and loaded
+    struct ViewBookmark
+    {
+        AZ_CLASS_ALLOCATOR(ViewBookmark, AZ::SystemAllocator, 0);
+        AZ_TYPE_INFO(ViewBookmark, "{9D6601B9-922F-4E90-BEB2-4D3D709DADD7}");
+
+        ViewBookmark() = default;
+
+        static void Reflect(AZ::ReflectContext* context)
+        {
+            if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+            {
+                serializeContext->Class<ViewBookmark>()
+                    ->Version(0)
+                    ->Field("Position", &ViewBookmark::m_position)
+                    ->Field("Rotation", &ViewBookmark::m_rotation);
+
+                if (AZ::EditContext* editContext = serializeContext->GetEditContext())
+                {
+                    editContext->Class<ViewBookmark>("ViewBookmark Data", "")
+                        ->ClassElement(AZ::Edit::ClassElements::EditorData, "ViewBookmark")
+                        ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
+                        ->DataElement(AZ::Edit::UIHandlers::Vector3, &ViewBookmark::m_position, "Position", "")
+                        ->DataElement(AZ::Edit::UIHandlers::Vector3, &ViewBookmark::m_rotation, "Rotation", "");
+                }
+            }
+        }
+
+        bool operator==(const ViewBookmark& other) const
+        {
+            return m_position == other.m_position && m_rotation == other.m_rotation;
+        }
+
+        bool operator!=(const ViewBookmark& other) const
+        {
+            return !(*this == other);
+        }
+
+        bool IsZero() const
+        {
+            return m_position == AZ::Vector3::CreateZero() && m_rotation == AZ::Vector3::CreateZero();
+        }
+
+        AZ::Vector3 m_position = AZ::Vector3::CreateZero();
+
+        //! Rotation in radians.
+        AZ::Vector3 m_rotation = AZ::Vector3::CreateZero();
+
+    };
+
+    //! @class ViewBookmarkIntereface
+    //! @brief Interface for saving/loading View Bookmarks.
+    class ViewBookmarkLoaderInterface
+    {
+    public:
+        AZ_RTTI(ViewBookmarkLoaderInterface, "{71E7E178-4107-4975-A6E6-1C4B005C981A}")
+
+        virtual bool SaveBookmark(const ViewBookmark& bookmark) = 0;
+        virtual bool ModifyBookmarkAtIndex(const ViewBookmark& bookmark, int index) = 0;
+        virtual bool SaveLastKnownLocation(const ViewBookmark& bookmark) = 0;
+        virtual bool LoadViewBookmarks() = 0;
+        virtual AZStd::optional<ViewBookmark> LoadBookmarkAtIndex(int index) = 0;
+        virtual AZStd::optional<ViewBookmark> LoadLastKnownLocation() const = 0;
+        virtual bool RemoveBookmarkAtIndex(int index) = 0;
+
+    private:
+        virtual void SaveBookmarkSettingsFile() = 0;
+    };
+} // namespace AzToolsFramework

+ 36 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewBookmarkSystemComponent.cpp

@@ -0,0 +1,36 @@
+/*
+ * 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 <Viewport/ViewBookmarkSystemComponent.h>
+
+namespace AzToolsFramework
+{
+    void ViewBookmarkSystemComponent::Activate()
+    {
+        m_viewBookmarkLoader.RegisterViewBookmarkLoaderInterface();
+    }
+
+    void ViewBookmarkSystemComponent::Deactivate()
+    {
+        m_viewBookmarkLoader.UnregisterViewBookmarkLoaderInterface();
+    }
+
+    void ViewBookmarkSystemComponent::Reflect(AZ::ReflectContext* context)
+    {
+        if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serialize->Class<ViewBookmarkSystemComponent, AZ::Component>()->Version(0);
+        }
+    }
+
+    void ViewBookmarkSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
+    {
+        provided.push_back(AZ_CRC_CE("ViewBookmarkSystem"));
+    }
+
+} // namespace AzToolsFramework

+ 38 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewBookmarkSystemComponent.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Component/Component.h>
+#include <Viewport/LocalViewBookmarkLoader.h>
+
+namespace AzToolsFramework
+{
+    //! @class ViewBookmarkSystemComponent
+    //! @brief System Component that holds functionality for the ViewBookmarks
+    class ViewBookmarkSystemComponent final : public AZ::Component
+    {
+    public:
+        AZ_COMPONENT(ViewBookmarkSystemComponent, "{FDD852BA-5F9E-4676-B121-D4B2FDEA7F55}");
+
+        ViewBookmarkSystemComponent() = default;
+
+        virtual ~ViewBookmarkSystemComponent() = default;
+
+        // AZ::Component overrides ...
+        void Activate() override;
+        void Deactivate() override;
+
+        static void Reflect(AZ::ReflectContext* context);
+        static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
+
+    private:
+        //! Used for loading/saving View Bookmarks.
+        LocalViewBookmarkLoader m_viewBookmarkLoader;
+    };
+} // namespace AzToolsFramework

+ 23 - 7
Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp

@@ -117,10 +117,30 @@ namespace AzToolsFramework
     static EntityData EntityDataFromEntityId(const AZ::EntityId entityId)
     {
         bool visible = false;
-        EditorEntityInfoRequestBus::EventResult(visible, entityId, &EditorEntityInfoRequestBus::Events::IsVisible);
-
         bool locked = false;
-        EditorEntityInfoRequestBus::EventResult(locked, entityId, &EditorEntityInfoRequestBus::Events::IsLocked);
+        bool iconHidden = false;
+
+        // Check to see if the given entity is an Editor entity or a Runtime entity.
+        bool isEditorEntity = false;
+        AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult(
+            isEditorEntity, &AzToolsFramework::EditorEntityContextRequests::IsEditorEntity, entityId);
+
+        if (isEditorEntity)
+        {
+            EditorEntityInfoRequestBus::EventResult(visible, entityId, &EditorEntityInfoRequestBus::Events::IsVisible);
+            EditorEntityInfoRequestBus::EventResult(locked, entityId, &EditorEntityInfoRequestBus::Events::IsLocked);
+            EditorEntityIconComponentRequestBus::EventResult(
+                iconHidden, entityId, &EditorEntityIconComponentRequests::IsEntityIconHiddenInViewport);
+        }
+        else
+        {
+            // If this is a runtime entity, default visible / locked / iconHidden to true. This will cause the entity to be displayed
+            // but not selectable assuming it is listening to the debug display bus.
+
+            visible = true;
+            locked = true;
+            iconHidden = true;
+        }
 
         bool inFocus = false;
         if (auto focusModeInterface = AZ::Interface<FocusModeInterface>::Get())
@@ -134,10 +154,6 @@ namespace AzToolsFramework
             descendantOfClosedContainer = containerEntityInterface->IsUnderClosedContainerEntity(entityId);
         }
 
-        bool iconHidden = false;
-        EditorEntityIconComponentRequestBus::EventResult(
-            iconHidden, entityId, &EditorEntityIconComponentRequests::IsEntityIconHiddenInViewport);
-
         AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
         AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM);
 

+ 9 - 0
Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake

@@ -487,6 +487,15 @@ set(FILES
     Viewport/EditorContextMenu.cpp
     Viewport/VertexContainerDisplay.h
     Viewport/VertexContainerDisplay.cpp
+    Viewport/LocalViewBookmarkComponent.h
+    Viewport/LocalViewBookmarkComponent.cpp
+    Viewport/SharedViewBookmarkComponent.h
+    Viewport/SharedViewBookmarkComponent.cpp
+    Viewport/LocalViewBookmarkLoader.h
+    Viewport/LocalViewBookmarkLoader.cpp
+    Viewport/ViewBookmarkLoaderInterface.h
+    Viewport/ViewBookmarkSystemComponent.h
+    Viewport/ViewBookmarkSystemComponent.cpp
     Viewport/ViewportInteractionHelpers.h
     Viewport/ViewportInteractionHelpers.cpp
     Viewport/ViewportMessages.h

+ 109 - 29
Code/Framework/AzToolsFramework/Tests/ManipulatorCoreTests.cpp

@@ -8,66 +8,95 @@
 
 #include <AzCore/Component/Entity.h>
 #include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/UnitTest/TestTypes.h>
+#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h>
 #include <AzTest/AzTest.h>
 #include <AzToolsFramework/Application/ToolsApplication.h>
 #include <AzToolsFramework/Manipulators/LinearManipulator.h>
-#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
 #include <AzToolsFramework/ToolsComponents/EditorLockComponent.h>
 #include <AzToolsFramework/ToolsComponents/EditorVisibilityComponent.h>
-#include <AzCore/UnitTest/TestTypes.h>
-
+#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
 #include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
 
-using namespace AzToolsFramework;
-
 namespace UnitTest
 {
-    class ManipulatorCoreFixture
-        : public ToolsApplicationFixture
+    class ManipulatorCoreFixture : public AllocatorsTestFixture
     {
     public:
-        void SetUpEditorFixtureImpl() override
+        void SetUp() override
         {
-            m_linearManipulator = LinearManipulator::MakeShared(AZ::Transform::CreateIdentity());
+            AllocatorsTestFixture::SetUp();
+
+            m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
+
+            m_transformComponentDescriptor =
+                AZStd::unique_ptr<AZ::ComponentDescriptor>(AzToolsFramework::Components::TransformComponent::CreateDescriptor());
+            m_transformComponentDescriptor->Reflect(&(*m_serializeContext));
+
+            m_lockComponentDescriptor =
+                AZStd::unique_ptr<AZ::ComponentDescriptor>(AzToolsFramework::Components::EditorLockComponent::CreateDescriptor());
+            m_lockComponentDescriptor->Reflect(&(*m_serializeContext));
 
-            m_entityId = CreateDefaultEditorEntity("Default", &m_entity);
+            m_visibilityComponentDescriptor =
+                AZStd::unique_ptr<AZ::ComponentDescriptor>(AzToolsFramework::Components::EditorVisibilityComponent::CreateDescriptor());
+            m_visibilityComponentDescriptor->Reflect(&(*m_serializeContext));
 
-            if (const auto* transformComponent = m_entity->FindComponent<Components::TransformComponent>())
+            m_linearManipulator = AzToolsFramework::LinearManipulator::MakeShared(AZ::Transform::CreateIdentity());
+
+            m_entity = AZStd::make_unique<AZ::Entity>();
+            // add required components for the Editor entity
+            m_entity->CreateComponent<AzToolsFramework::Components::TransformComponent>();
+            m_entity->CreateComponent<AzToolsFramework::Components::EditorLockComponent>();
+            m_entity->CreateComponent<AzToolsFramework::Components::EditorVisibilityComponent>();
+
+            m_entity->Init();
+            m_entity->Activate();
+
+            if (const auto* transformComponent = m_entity->FindComponent<AzToolsFramework::Components::TransformComponent>())
             {
                 m_transformComponentId = transformComponent->GetId();
-                m_linearManipulator->AddEntityComponentIdPair(
-                    AZ::EntityComponentIdPair{ m_entityId, m_transformComponentId });
+                m_linearManipulator->AddEntityComponentIdPair(AZ::EntityComponentIdPair{ m_entityId, m_transformComponentId });
             }
 
-            if (const auto* lockComponent = m_entity->FindComponent<Components::EditorLockComponent>())
+            if (const auto* lockComponent = m_entity->FindComponent<AzToolsFramework::Components::EditorLockComponent>())
             {
                 m_lockComponentId = lockComponent->GetId();
-                m_linearManipulator->AddEntityComponentIdPair(
-                    AZ::EntityComponentIdPair{ m_entityId, m_lockComponentId });
+                m_linearManipulator->AddEntityComponentIdPair(AZ::EntityComponentIdPair{ m_entityId, m_lockComponentId });
             }
 
-            if (const auto* visibilityComponent = m_entity->FindComponent<Components::EditorVisibilityComponent>())
+            if (const auto* visibilityComponent = m_entity->FindComponent<AzToolsFramework::Components::EditorVisibilityComponent>())
             {
                 m_visibiltyComponentId = visibilityComponent->GetId();
-                m_linearManipulator->AddEntityComponentIdPair(
-                    AZ::EntityComponentIdPair{ m_entityId, m_visibiltyComponentId });
+                m_linearManipulator->AddEntityComponentIdPair(AZ::EntityComponentIdPair{ m_entityId, m_visibiltyComponentId });
             }
 
-            m_editorEntityComponentChangeDetector
-                = AZStd::make_unique<EditorEntityComponentChangeDetector>(m_entityId);
+            m_editorEntityComponentChangeDetector = AZStd::make_unique<EditorEntityComponentChangeDetector>(m_entityId);
         }
 
-        void TearDownEditorFixtureImpl() override
+        void TearDown() override
         {
+            m_editorEntityComponentChangeDetector.reset();
+            m_linearManipulator.reset();
+            m_entity.reset();
+            m_transformComponentDescriptor.reset();
+            m_lockComponentDescriptor.reset();
+            m_visibilityComponentDescriptor.reset();
+            m_serializeContext.reset();
+
+            AllocatorsTestFixture::TearDown();
         }
 
-        AZStd::shared_ptr<LinearManipulator> m_linearManipulator;
-        AZ::Entity* m_entity = nullptr;
         AZ::EntityId m_entityId;
+        AZStd::unique_ptr<AZ::Entity> m_entity;
+        AZStd::shared_ptr<AzToolsFramework::LinearManipulator> m_linearManipulator;
         AZStd::unique_ptr<EditorEntityComponentChangeDetector> m_editorEntityComponentChangeDetector;
+        AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
         AZ::ComponentId m_transformComponentId;
+        AZStd::unique_ptr<AZ::ComponentDescriptor> m_transformComponentDescriptor;
         AZ::ComponentId m_lockComponentId;
+        AZStd::unique_ptr<AZ::ComponentDescriptor> m_lockComponentDescriptor;
         AZ::ComponentId m_visibiltyComponentId;
+        AZStd::unique_ptr<AZ::ComponentDescriptor> m_visibilityComponentDescriptor;
     };
 
     TEST_F(ManipulatorCoreFixture, AllEntityIdComponentPairsRemovedFromManipulatorAfterRemoveEntity)
@@ -98,7 +127,7 @@ namespace UnitTest
 
         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
         // When
-         m_linearManipulator->RemoveEntityComponentIdPair(entityLockComponentIdPair);
+        m_linearManipulator->RemoveEntityComponentIdPair(entityLockComponentIdPair);
         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -118,11 +147,9 @@ namespace UnitTest
 
         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
         // When
-        m_linearManipulator->OnLeftMouseDown(
-            AzToolsFramework::ViewportInteraction::MouseInteraction{}, 0.0f);
+        m_linearManipulator->OnLeftMouseDown(AzToolsFramework::ViewportInteraction::MouseInteraction{}, 0.0f);
 
-        m_linearManipulator->OnLeftMouseUp(
-            AzToolsFramework::ViewportInteraction::MouseInteraction{});
+        m_linearManipulator->OnLeftMouseUp(AzToolsFramework::ViewportInteraction::MouseInteraction{});
         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -134,4 +161,57 @@ namespace UnitTest
         EXPECT_TRUE(m_editorEntityComponentChangeDetector->PropertyDisplayInvalidated());
         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
     }
+
+    using ManipulatorCoreInteractionFixture = DirectCallManipulatorViewportInteractionFixtureMixin<ManipulatorCoreFixture>;
+
+    TEST_F(ManipulatorCoreInteractionFixture, TestInteraction)
+    {
+        // setup viewport/camera
+        m_cameraState.m_viewportSize = AzFramework::ScreenSize(1280, 720);
+        AzFramework::SetCameraTransform(m_cameraState, AZ::Transform::CreateIdentity());
+
+        AzToolsFramework::ManipulatorViews views;
+        views.emplace_back(AzToolsFramework::CreateManipulatorViewSphere(
+            // note: use a small radius for the manipulator view/bounds to ensure precise mouse movement
+            AZ::Color{}, 0.001f,
+            [](const AzToolsFramework::ViewportInteraction::MouseInteraction&, bool, const AZ::Color&)
+            {
+                return AZ::Color{};
+            }));
+
+        m_linearManipulator->SetViews(views);
+        m_linearManipulator->Register(m_viewportManipulatorInteraction->GetManipulatorManagerId());
+
+        // the initial starting position of the manipulator
+        const auto initialTransformWorld = AZ::Transform::CreateTranslation(AZ::Vector3(0.0f, 10.0f, 0.0f));
+        // where the linear manipulator should end up
+        const auto finalTransformWorld = AZ::Transform::CreateTranslation(AZ::Vector3(2.0f, 10.0f, 0.0f));
+
+        // calculate the position in screen space of the initial position of the manipulator
+        const auto initialPositionScreen = AzFramework::WorldToScreen(initialTransformWorld.GetTranslation(), m_cameraState);
+        // calculate the position in screen space of the final position of the manipulator
+        const auto finalPositionScreen = AzFramework::WorldToScreen(finalTransformWorld.GetTranslation(), m_cameraState);
+
+        m_linearManipulator->SetSpace(AZ::Transform::CreateIdentity());
+        m_linearManipulator->SetLocalTransform(initialTransformWorld);
+        m_linearManipulator->InstallMouseMoveCallback(
+            [this](const AzToolsFramework::LinearManipulator::Action& action)
+            {
+                // move the manipulator
+                m_linearManipulator->SetLocalPosition(action.LocalPosition());
+            });
+
+        // press and drag the mouse (starting where the surface manipulator is)
+        m_actionDispatcher->CameraState(m_cameraState)
+            ->MousePosition(initialPositionScreen)
+            ->MouseLButtonDown()
+            ->MousePosition(finalPositionScreen)
+            ->MouseLButtonUp();
+
+        // read back the position of the manipulator now
+        const AZ::Transform finalManipulatorTransform = m_linearManipulator->GetLocalTransform();
+
+        // ensure final world positions match
+        EXPECT_THAT(finalManipulatorTransform, IsCloseTolerance(finalTransformWorld, 0.01f));
+    }
 } // namespace UnitTest

+ 4 - 1
Code/Legacy/CryCommon/ISystem.h

@@ -1053,7 +1053,10 @@ void* GetModuleShutdownISystemSymbol();
 //   Interface of the DLL.
 extern "C"
 {
-    CRYSYSTEM_API ISystem* CreateSystemInterface(const SSystemInitParams& initParams);
+#if !defined(AZ_MONOLITHIC_BUILD)
+    CRYSYSTEM_API
+#endif
+    ISystem* CreateSystemInterface(const SSystemInitParams& initParams);
 }
 
 // Description:

+ 4 - 1
Code/Legacy/CrySystem/DllMain.cpp

@@ -63,7 +63,10 @@ AZ_POP_DISABLE_WARNING
 
 extern "C"
 {
-CRYSYSTEM_API ISystem* CreateSystemInterface(const SSystemInitParams& startupParams)
+#if !defined(AZ_MONOLITHIC_BUILD)
+CRYSYSTEM_API
+#endif
+ISystem* CreateSystemInterface(const SSystemInitParams& startupParams)
 {
     CSystem* pSystem = NULL;
 

+ 1 - 1
Code/Tools/AssetProcessor/native/tests/AssetProcessorMessagesTests.cpp

@@ -205,7 +205,7 @@ namespace AssetProcessorMessagesTests
             AZStd::atomic_bool finished = false;
             auto start = AZStd::chrono::monotonic_clock::now();
 
-            auto thread = AZStd::thread([&finished, &func]()
+            auto thread = AZStd::thread({/*m_name =*/ "MessageTests"}, [&finished, &func]()
                 {
                     func();
                     finished = true;

+ 4 - 0
Code/Tools/ProjectManager/Source/Application.cpp

@@ -22,6 +22,7 @@
 #include <QDir>
 #include <QMessageBox>
 #include <QInputDialog>
+#include <QIcon>
 
 namespace O3DE::ProjectManager
 {
@@ -69,6 +70,9 @@ namespace O3DE::ProjectManager
             AZ_Warning("ProjectManager", false, "Failed to init logging");
         }
 
+        // Set window icon after QGuiApplication is created otherwise QPixmap for the icon fails to intialize
+        QApplication::setWindowIcon(QIcon(":/ProjectManager-Icon.ico"));
+
         m_pythonBindings = AZStd::make_unique<PythonBindings>(GetEngineRoot());
 
         if (!m_pythonBindings->PythonStarted())

+ 1 - 0
Code/Tools/SerializeContextTools/Converter.cpp

@@ -577,6 +577,7 @@ namespace AZ
             AZ::IO::FixedMaxPath gemModuleSourcePath;
             AZ::ModuleManagerRequestBus::Broadcast([&gemModuleSourcePath, &gemName, gemModuleClassId = entity.m_moduleClassId](AZ::ModuleManagerRequests* request)
             {
+                AZ_UNUSED(gemModuleClassId);
                 auto EnumerateGemModules = [&gemModuleSourcePath, &gemName, &gemModuleClassId](const AZ::ModuleData& moduleData) -> bool
                 {
                     AZ::Module* moduleInst = moduleData.GetModule();

+ 0 - 24
Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderCapabilitiesConfigFile.cpp

@@ -1,24 +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 <AtomShaderCapabilitiesConfigFile.h>
-
-namespace AZ::ShaderBuilder::AtomShaderConfig
-{
-    void CapabilitiesConfigFile::Reflect(AZ::ReflectContext* context)
-    {
-        if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
-        {
-            serializeContext->Class<CapabilitiesConfigFile>()
-                ->Version(0)
-                ->Field("DescriptorCounts", &CapabilitiesConfigFile::m_descriptorCounts)
-                ->Field("MaxSpaces", &CapabilitiesConfigFile::m_maxSpaces)
-                ;
-        }
-    }
-}

+ 0 - 40
Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderCapabilitiesConfigFile.h

@@ -1,40 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#pragma once
-
-#include <AzCore/Preprocessor/Enum.h>
-#include <AzCore/RTTI/ReflectContext.h>
-#include <AzCore/Serialization/SerializeContext.h>
-#include <AzCore/Serialization/DataPatch.h>
-#include <AzCore/std/string/string.h>
-#include <AzCore/std/containers/unordered_map.h>
-
-namespace AZ::ShaderBuilder::AtomShaderConfig
-{
-    AZ_ENUM(DescriptorSpace,
-            Sets,
-            Spaces,
-            Samplers,
-            Textures,
-            Buffers);
-
-    struct CapabilitiesConfigFile final
-    {
-        AZ_RTTI(CapabilitiesConfigFile, "{D3A25140-0F6C-4547-B4E4-0C7B7DE852E6}");
-
-        static void Reflect(AZ::ReflectContext* context);
-
-        //! string key: stringifed version of DescriptorSpace.
-        //! int value : -1 for unlimited, or by-specification minimal guaranteed capacity.
-        AZStd::unordered_map<AZStd::string, int> m_descriptorCounts;
-
-        //! The max number of spaces supported by the API.
-        int m_maxSpaces = -1;
-    };
-}

+ 0 - 136
Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp

@@ -1,136 +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 "AtomShaderConfig.h"
-
-#include <AzCore/IO/SystemFile.h>
-#include <AzFramework/StringFunc/StringFunc.h>
-#include <AzFramework/Platform/PlatformDefaults.h>
-
-#include <AzCore/Serialization/Json/JsonUtils.h>
-
-
-namespace AZ
-{
-    namespace ShaderBuilder
-    {
-        namespace AtomShaderConfig
-        {
-            [[maybe_unused]] static constexpr char AtomShaderConfigName[] = "AtomShaderConfig";
-
-            bool MutateToFirstAbsoluteFolderThatExists(AZStd::string& relativeFolder, AZStd::vector<AZStd::string>& watchFolders)
-            {
-                if (!AzFramework::StringFunc::Path::IsRelative(relativeFolder.c_str()))
-                {
-                    return true;
-                }
-                for (AZStd::string folder : watchFolders)
-                {
-                    AzFramework::StringFunc::Path::Normalize(relativeFolder); // this is an external input, so defense is indicated.
-                    AzFramework::StringFunc::Path::Normalize(folder);
-                    AZStd::string absoluteOutput;
-                    AzFramework::StringFunc::Path::Join(folder.c_str(),
-                        relativeFolder.c_str(),
-                        absoluteOutput,
-                        true   /* join overlapping */,
-                        false  /* case insensitive */);
-                    if (AZ::IO::SystemFile::Exists(absoluteOutput.c_str()))
-                    {
-                        relativeFolder = std::move(absoluteOutput);
-                        return true;
-                    }
-                }
-                return false;
-            }
-
-            AZStd::string GetAssetConfigPath(const char* platformFolder)
-            {
-                bool success = false;
-                AZStd::vector<AZStd::string> scanFoldersVector;
-                AzToolsFramework::AssetSystemRequestBus::BroadcastResult(success,
-                    &AzToolsFramework::AssetSystemRequestBus::Events::GetScanFolders,
-                    scanFoldersVector);
-                AZ_Warning(AtomShaderConfigName, success, "Could not acquire a list of scan folders from the database.");
-                if (success)
-                {
-                    // platform specific shader build user configuration
-                    static constexpr char ConfigFileName[] = "AtomShaderCapabilities.json";
-                    static constexpr char ConfigPalFolder[] = "Config/Platform";
-                    AZStd::string assetRoot = ConfigPalFolder;
-                    if (MutateToFirstAbsoluteFolderThatExists(assetRoot, scanFoldersVector))
-                    {
-                        AZStd::string configFile;
-                        AzFramework::StringFunc::Path::Join(assetRoot.c_str(), platformFolder, configFile);
-                        AzFramework::StringFunc::Path::Join(configFile.c_str(), ConfigFileName, configFile);
-                        return configFile;
-                    }
-                }
-                return {};
-            }
-
-            CapabilitiesConfigFile GetMinDescriptorSetsFromConfigFile(const char* platformFolder)
-            {
-                CapabilitiesConfigFile limits;
-                AZStd::string configFilePath = GetAssetConfigPath(platformFolder);
-                if (IO::SystemFile::Exists(configFilePath.c_str()))
-                {
-                    Outcome loadResult = JsonSerializationUtils::LoadObjectFromFile(limits, configFilePath);
-                    AZ_Warning(AtomShaderConfigName, loadResult.IsSuccess(), "Failed to load capabilities settings from file [%s]", configFilePath.c_str());
-                }
-                return limits;
-            }
-
-            // @config argument comes from a platform abstracted folder
-            AZStd::string FormatSupplementaryArgumentsFromConfigAtomShader(const CapabilitiesConfigFile& config)
-            {
-                AZStd::string commandLineArguments;
-                // the map config.m_counts is the deserialized JSON data from the config file about hardware capabilities.
-                // the keys are unsanitized, therefore they could be anything in the wild.
-                // proceed if any element of the map's values has is a non -1:
-                if (AZStd::any_of(AZStd::begin(config.m_descriptorCounts), AZStd::end(config.m_descriptorCounts), [](auto pair) { return pair.second != -1; }))
-                {
-                    commandLineArguments = " --min-descriptors=";
-                    // for each key that indeed corresponds to an element of the DescriptorSpace enumerators, let's fetch it
-                    // and convert it to a string:
-                    AZStd::array<AZStd::string, AzEnumTraits<DescriptorSpace>::Count> valuesAsString = { {"-1","-1","-1","-1","-1"} };
-                    for (const auto& enumElement : DescriptorSpaceMembers)
-                    {
-                        auto iterator = config.m_descriptorCounts.find(enumElement.m_string);
-                        if (iterator != config.m_descriptorCounts.end())
-                        {
-                            valuesAsString[enumElement.m_value] = AZStd::to_string(iterator->second);
-                        }
-                    }
-                    AzFramework::StringFunc::Join(commandLineArguments,
-                        AZStd::begin(valuesAsString),
-                        AZStd::end(valuesAsString),
-                        ",");
-                }
-
-                if (config.m_maxSpaces != -1)
-                {
-                    commandLineArguments += AZStd::string::format(" --max-spaces=%d", config.m_maxSpaces);
-                }
-                return commandLineArguments;
-            }
-
-            void AddParametersFromConfigFile(AZStd::string& parameters, const AssetBuilderSDK::PlatformInfo& platform)
-            {
-                auto platformId = static_cast<AzFramework::PlatformId>(
-                    AzFramework::PlatformHelper::GetPlatformIndexFromName(platform.m_identifier.c_str()));
-                // The platforms available don't match the PAL folders. But the tags enrich it just enough to be able to rehabilitate android:
-                const char* palFolder = platform.HasTag("android") ? "Android"
-                    : AzFramework::PlatformIdToPalFolder(platformId);
-
-                CapabilitiesConfigFile minDescriptors = GetMinDescriptorSetsFromConfigFile(palFolder);
-                parameters += FormatSupplementaryArgumentsFromConfigAtomShader(minDescriptors);
-            }
-
-        } // namespace AtomShaderConfig
-    } // namespace ShaderBuilder
-} //namespace AZ

+ 0 - 32
Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.h

@@ -1,32 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include <AssetBuilderSDK/AssetBuilderSDK.h>
-
-#include "AtomShaderCapabilitiesConfigFile.h"
-
-namespace AZ
-{
-    namespace ShaderBuilder
-    {
-        namespace AtomShaderConfig
-        {
-            bool MutateToFirstAbsoluteFolderThatExists(AZStd::string& relativeFolder, AZStd::vector<AZStd::string>& watchFolders);
-
-            AZStd::string GetAssetConfigPath(const char* platformFolder);
-
-            CapabilitiesConfigFile GetMinDescriptorSetsFromConfigFile(const char* platformFolder);
-
-            // @config argument comes from a platform abstracted folder
-            AZStd::string FormatSupplementaryArgumentsFromConfigAtomShader(const CapabilitiesConfigFile& config);
-
-            void AddParametersFromConfigFile(AZStd::string& parameters, const AssetBuilderSDK::PlatformInfo& platform);
-        } // namespace AtomShaderConfig
-    } // namespace ShaderBuilder
-} //namespace AZ

+ 3 - 2
Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp

@@ -120,9 +120,10 @@ namespace AZ
 
         namespace SubProducts = ShaderBuilderUtility::AzslSubProducts;
 
-        Outcome<SubProducts::Paths> AzslCompiler::EmitFullData(const AZStd::string& parameters, const AZStd::string& outputFile /* = ""*/) const
+        Outcome<SubProducts::Paths> AzslCompiler::EmitFullData(const AZStd::vector<AZStd::string>& azslcArguments, const AZStd::string& outputFile /* = ""*/) const
         {
-            bool success = Compile("--full " + parameters, outputFile);
+            const auto azslArgsStr = RHI::ShaderBuildArguments::ListAsString(azslcArguments);
+            bool success = Compile(azslArgsStr, outputFile);
             if (!success)
             {
                 return Failure();

+ 2 - 1
Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.h

@@ -35,7 +35,8 @@ namespace AZ
             AzslCompiler(const AZStd::string& inputFilePath);
 
             //! compile with --full and generate all .json files
-            Outcome<ShaderBuilderUtility::AzslSubProducts::Paths> EmitFullData(const AZStd::string& parameters, const AZStd::string& outputFile = "") const;
+            Outcome<ShaderBuilderUtility::AzslSubProducts::Paths> EmitFullData(const AZStd::vector<AZStd::string>& azslcArguments,
+                const AZStd::string& outputFile = "") const;
             //! compile to HLSL independently
             bool EmitShader(AZ::IO::GenericStream& outputStream, const AZStd::string& extraCompilerParams) const;
             //! compile with --ia independently and populate document @output

+ 3 - 5
Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp

@@ -13,6 +13,7 @@
 
 #include <Atom/RHI.Edit/ShaderPlatformInterface.h>
 #include <Atom/RHI.Edit/Utils.h>
+#include <Atom/RHI.Edit/ShaderBuildOptions.h>
 
 #include <Atom/RPI.Reflect/Asset/AssetHandler.h>
 #include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
@@ -26,8 +27,6 @@
 #include <AzCore/Settings/SettingsRegistry.h>
 
 #include <CommonFiles/Preprocessor.h>
-#include <CommonFiles/GlobalBuildOptions.h>
-#include <Editor/AtomShaderCapabilitiesConfigFile.h>
 
 namespace AZ
 {
@@ -45,9 +44,8 @@ namespace AZ
 
             PreprocessorOptions::Reflect(context);
             RHI::ShaderCompilerProfiling::Reflect(context);
-            AtomShaderConfig::CapabilitiesConfigFile::Reflect(context);
-            GlobalBuildOptions::Reflect(context);
-            RHI::ShaderCompilerArguments::Reflect(context);
+            RHI::ShaderBuildArguments::Reflect(context);
+            RHI::ShaderBuildOptions::Reflect(context);
         }
 
         void AzslShaderBuilderSystemComponent::GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided)

+ 0 - 81
Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/GlobalBuildOptions.cpp

@@ -1,81 +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 <CommonFiles/GlobalBuildOptions.h>
-
-#include <AzFramework/StringFunc/StringFunc.h>
-#include <AzFramework/API/ApplicationAPI.h>
-
-#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
-
-#include <AzCore/Serialization/Json/JsonUtils.h>
-
-namespace AZ
-{
-    namespace ShaderBuilder
-    {
-        void GlobalBuildOptions::Reflect(AZ::ReflectContext* context)
-        {
-            if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
-            {
-                serializeContext->Class<GlobalBuildOptions>()
-                    ->Version(1)
-                    ->Field("PreprocessorOptions", &GlobalBuildOptions::m_preprocessorSettings)
-                    ->Field("ShaderCompilerArguments", &GlobalBuildOptions::m_compilerArguments);
-            }
-        }
-
-        namespace
-        {
-            // this function wraps BroadcastResult on GetSourceInfoBySourcePath
-            // return value: whether the search query succeeded or not
-            bool MutateToAbsolutePathIfFound(AZStd::string& relativePathToSearch)
-            {
-                bool found = false;
-                if (AzFramework::StringFunc::Path::IsRelative(relativePathToSearch.c_str()))
-                {
-                    AZ::Data::AssetInfo sourceInfo;
-                    AZStd::string watchFolder;
-                    AzToolsFramework::AssetSystemRequestBus::BroadcastResult(found,
-                                                                             &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath,
-                                                                             relativePathToSearch.c_str(),
-                                                                             sourceInfo,
-                                                                             watchFolder);
-                    if (found)
-                    {
-                        AZStd::string absoluteOutput;
-                        AzFramework::StringFunc::Path::Join(watchFolder.c_str(), relativePathToSearch.c_str(), absoluteOutput);
-                        relativePathToSearch = std::move(absoluteOutput);
-                    }
-                }
-                return found;
-            }
-        }
-
-        GlobalBuildOptions ReadBuildOptions(const char* builderName, const char* optionalIncludeFolder)
-        {
-            GlobalBuildOptions output;
-            // try to parse some config file for eventual additional options
-            AZStd::string globalBuildOption = "Config/shader_global_build_options.json";
-            bool found = MutateToAbsolutePathIfFound(globalBuildOption);
-            if (found)
-            {
-                // load settings in a temporary object to be able to do some input treatment, before merging with the final options
-                Outcome loadResult = AZ::JsonSerializationUtils::LoadObjectFromFile(output, globalBuildOption);
-                AZ_Warning(builderName, loadResult.IsSuccess(), "Failed to load shader-build environment include paths settings from file [%s]", globalBuildOption.c_str());
-                AZ_Warning(builderName, loadResult.IsSuccess(), "  Details: %s", loadResult.GetError().c_str());
-            }
-            else
-            {
-                AZ_TracePrintf(builderName, "config file [%s] not found.", globalBuildOption.c_str());
-            }
-            InitializePreprocessorOptions(output.m_preprocessorSettings, builderName, optionalIncludeFolder);
-            return output;
-        }
-    }
-}

+ 0 - 37
Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/GlobalBuildOptions.h

@@ -1,37 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#pragma once
-
-#include <CommonFiles/Preprocessor.h>
-#include <Atom/RHI.Edit/ShaderCompilerArguments.h>
-
-namespace AZ
-{
-    namespace ShaderBuilder
-    {
-        //! represents the json config file contents of project-wide shader_global_build_options's file.
-        struct GlobalBuildOptions final
-        {
-            AZ_RTTI(GlobalBuildOptions, "{F7F1247D-A417-43E1-9B52-84DD226A9E1A}");
-
-            static void Reflect(AZ::ReflectContext* context);
-
-            //! include paths and defines
-            PreprocessorOptions m_preprocessorSettings;
-
-            //! command line arguments related to warnings, optimizations, matrices order and others.
-            RHI::ShaderCompilerArguments m_compilerArguments;
-        };
-
-        //! Reads the global options used when compiling shaders. The options are defined in <GameProject>/Config/shader_global_build_options.json
-        //! @param builderName: A string with the name of the builder calling this API. Used for trace debugging.
-        //! @param optionalIncludeFolder: An additional directory to add to the list of include folders for the C-preprocessor.
-        GlobalBuildOptions ReadBuildOptions(const char* builderName, const char* optionalIncludeFolder = nullptr);
-    }
-}

+ 130 - 57
Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp

@@ -196,8 +196,76 @@ namespace AZ
         // McppBinder ends
         ///////////////////////////////////////////////////////////////////////
 
-        bool PreprocessFile(const AZStd::string& fullPath, PreprocessorData& outputData, const PreprocessorOptions& options
-            , bool collectDiagnostics, bool preprocessIncludedFiles)
+        // @returns true if a string starts with "-I", which is how the C-preprocessor understands include paths.  Examples:
+        // "-Isome/dir" (true)
+        // "-I/full/path/" (true)
+        // "-DMacro" (false)
+        static bool IsArgumentAnIncludeDirectory(const AZStd::string& argument)
+        {
+            if (argument.size() < 2)
+            {
+                return false;
+            }
+            return (argument[0] == '-') && (argument[1] == 'I');
+        }
+
+        // Transforms relative include path arguments. If the argument is not an include path the same argument is returned.
+        // @param argument A single command line arguments for the C-preprocessor.
+        // @param rootDir The root directory that will be joined with the relative path.
+        // @returns A copy of @argument if it is NOT an include path argument. If it is a include path then:
+        //      - If the directory is an absolute path:
+        //          - and it exists, a copy of @argument is returned.
+        //          - and it doesn't exist, an empty string is returned.
+        //      - If the directory is a relative path, it is transformed into an absolute directory by joining @rootDir with the relative path.
+        //          - If the directory exists a string as an include path argument is returned.
+        //          - If the directory doesn't exist and empty string is returned.
+        static AZStd::string NormalizeIncludePathArgument(const AZStd::string& argument, const AZ::IO::FixedMaxPath& rootDir)
+        {
+            if (!IsArgumentAnIncludeDirectory(argument))
+            {
+                return argument;
+            }
+
+            AZStd::string includeDirectory = argument.substr(2);
+            // Trim spaces at both ends.
+            AZ::StringFunc::TrimWhiteSpace(includeDirectory, true, true);
+            if (AZ::StringFunc::Path::IsRelative(includeDirectory.c_str()))
+            {
+                AZ::IO::FixedMaxPath absoluteDirectory = rootDir / includeDirectory;
+                if (!AZ::IO::SystemFile::Exists(absoluteDirectory.c_str()))
+                {
+                    AZ_Error("Preprocessor", false, "The directory argument: %s, doesn't exist as an absolute path: %s. Skipping...",
+                        argument.c_str(), absoluteDirectory.c_str());
+                    return {};
+                }
+                return AZStd::string::format("-I%s", absoluteDirectory.c_str());
+            }
+
+            // It's an absolute directory. Does it exist?
+            if (!AZ::IO::SystemFile::Exists(includeDirectory.c_str()))
+            {
+                AZ_Error("Preprocessor", false, "The absolute directory argument: %s, doesn't exist as an absolute path: %s. Skipping...",
+                    argument.c_str(), includeDirectory.c_str());
+                return {};
+            }
+
+            // The aboslute directory exists, return the argument as is.
+            return argument;
+        }
+
+        AZStd::vector<AZStd::string> AppendIncludePathsToArgumentList(const AZStd::vector<AZStd::string>& preprocessorArguments, AZStd::vector<AZStd::string> includePaths)
+        {
+            auto newList = preprocessorArguments;
+            for (const AZStd::string& folder : includePaths)
+            {
+                newList.push_back(AZStd::string::format("-I%s", folder.c_str()));
+            }
+            return newList;
+        }
+
+        bool PreprocessFile(const AZStd::string& fullPath, PreprocessorData& outputData
+            , const AZStd::vector<AZStd::string>& preprocessorArguments
+            , bool collectDiagnostics)
         {
             // create a wrapper instance
             McppBinder mcpp(outputData, collectDiagnostics);
@@ -205,36 +273,40 @@ namespace AZ
             // create the argc/argv
             const char* processName = "builder";
             const char* inputPath = fullPath.c_str();
-            // let's create the equivalent of that expression but in dynamic form:
-            //const char* argv[] = { processName, szInPath, "-C", "-+", "-D macro1"..., "-I path"..., NULL };
-            AZStd::vector< const char* > argv;
-            argv.reserve(5 + options.m_predefinedMacros.size() * 2 + options.m_projectIncludePaths.size() * 2);
+
+            AZStd::vector< AZStd::string > argv;
+            argv.reserve(2 /*processName + inputPath*/ + preprocessorArguments.size());
             argv.push_back(processName);
             argv.push_back(inputPath);
-            if (!preprocessIncludedFiles)
-            {
-                argv.push_back("-z");
-            }
-            argv.push_back("-C");  // conserve comments
-            argv.push_back("-+");  // C++ mode
-            for (const AZStd::string& macroDef : options.m_predefinedMacros)
-            {
-                argv.push_back("-D");
-                argv.push_back(&macroDef[0]); // pointers to the string data will be stable for the duration of the call
-            }
-            for (const AZStd::string& folder : options.m_projectIncludePaths)
+
+            // The include directories in C-preprocessor arguments, when relative, are relative
+            // to the current project.
+            const AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
+            for (const auto& cppArgument : preprocessorArguments)
             {
-                argv.push_back("-I");
-                argv.push_back(&folder[0]);  // pointers to the string data will be stable for the duration of the call
+                auto normalizedArgument = NormalizeIncludePathArgument(cppArgument, projectPath);
+                if (normalizedArgument.empty())
+                {
+                    // An empty string means there was an error. The proper message is produced by NormalizePreprocessorIncludePath().
+                    return false;
+                }
+                argv.emplace_back(AZStd::move(normalizedArgument));
             }
-            argv.push_back(nullptr); // usual argv terminator
+
             // output the command line:
             AZStd::string stringifiedCommandLine;
-            AZ::StringFunc::Join(stringifiedCommandLine, argv.begin(), argv.end() - 1, " ");
+            AZ::StringFunc::Join(stringifiedCommandLine, argv.begin(), argv.end(), " ");
             AZ_TracePrintf("Preprocessor", "%s", stringifiedCommandLine.c_str());
             // when we don't specify an -o outfile, mcpp uses stdout.
-            // the trick is that since we hijacked putc & puts, stdout will not be written. 
-            bool result = mcpp.StartPreprocessWithCommandLine(aznumeric_cast<int>(argv.size()) - 1, argv.data());
+            // the trick is that since we hijacked putc & puts, stdout will not be written.
+            AZStd::vector< const char* > argsOfCstr;
+            argsOfCstr.reserve(argv.size() + 1);
+            for (const auto& arg : argv)
+            {
+                argsOfCstr.push_back(&arg[0]);
+            }
+            argsOfCstr.push_back(nullptr); // usual argv terminator
+            bool result = mcpp.StartPreprocessWithCommandLine(aznumeric_cast<int>(argsOfCstr.size()) - 1, argsOfCstr.data());
             return result;
         }
 
@@ -280,56 +352,55 @@ namespace AZ
             }
         }
 
-        // populate options with scan folders and contents of parsing shader_global_build_options.json
-        void InitializePreprocessorOptions(
-            PreprocessorOptions& options, [[maybe_unused]] const char* builderName, const char* optionalIncludeFolder)
+        AZStd::vector<AZStd::string> BuildListOfIncludeDirectories([[maybe_unused]] const char* builderName, const char* optionalIncludeFolder)
         {
             AZ_TraceContext("Init include-paths lookup options", "preprocessor");
 
-            // get the scan folders of the projects:
-            bool success = true;
-            AZStd::vector<AZStd::string> scanFoldersVector;
-            AzToolsFramework::AssetSystemRequestBus::BroadcastResult(success,
-                &AzToolsFramework::AssetSystemRequestBus::Events::GetScanFolders,
-                scanFoldersVector);
-            AZ_Warning(builderName, success, "Preprocessor option: Could not acquire a list of scan folders from the database.");
+            AZStd::vector<AZStd::string> includePaths;
 
-            // Add the project path to list of include paths
-            AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
-            auto FindPath = [](AZ::IO::PathView searchPath)
+            if (optionalIncludeFolder)
+            {
+                if (AZ::IO::SystemFile::Exists(optionalIncludeFolder))
+                {
+                    includePaths.emplace_back(AZStd::move(AZ::IO::Path(optionalIncludeFolder).LexicallyNormal().Native()));
+                }
+            }
+
+            auto PathCompare = [](AZ::IO::PathView searchPath)
             {
                 return [searchPath](AZStd::string_view includePathView)
                 {
                     return searchPath == AZ::IO::PathView(includePathView);
                 };
             };
-            if (auto it = AZStd::find_if(options.m_projectIncludePaths.begin(), options.m_projectIncludePaths.end(), FindPath(projectPath));
-                it == options.m_projectIncludePaths.end())
-            {
-                options.m_projectIncludePaths.emplace_back(projectPath.c_str(), projectPath.Native().size());
-            }
-            if (optionalIncludeFolder)
+
+            // Add the project path to list of include paths
+            AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
+            if (auto it = AZStd::find_if(includePaths.begin(), includePaths.end(), PathCompare(projectPath));
+                it == includePaths.end())
             {
-                if (auto it = AZStd::find_if(options.m_projectIncludePaths.begin(), options.m_projectIncludePaths.end(), FindPath(optionalIncludeFolder));
-                    it == options.m_projectIncludePaths.end())
-                {
-                    if (AZ::IO::SystemFile::Exists(optionalIncludeFolder))
-                    {
-                        options.m_projectIncludePaths.emplace_back(AZStd::move(AZ::IO::Path(optionalIncludeFolder).LexicallyNormal().Native()));
-                    }
-                }
+                includePaths.emplace_back(projectPath.c_str(), projectPath.Native().size());
             }
+
+            // get the scan folders of the projects:
+            bool success = true;
+            AZStd::vector<AZStd::string> scanFoldersVector;
+            AzToolsFramework::AssetSystemRequestBus::BroadcastResult(success,
+                &AzToolsFramework::AssetSystemRequestBus::Events::GetScanFolders,
+                scanFoldersVector);
+            AZ_Warning(builderName, success, "Preprocessor option: Could not acquire a list of scan folders from the database.");
+
             // but while we transfer to the set, we're going to keep only folders where +/ShaderLib exists
             for (AZ::IO::Path shaderScanFolder : scanFoldersVector)
             {
                 shaderScanFolder /= "ShaderLib";
-                if (auto it = AZStd::find_if(options.m_projectIncludePaths.begin(), options.m_projectIncludePaths.end(), FindPath(shaderScanFolder));
-                    it == options.m_projectIncludePaths.end())
+                if (auto it = AZStd::find_if(includePaths.begin(), includePaths.end(), PathCompare(shaderScanFolder));
+                    it == includePaths.end())
                 {
                     // the folders constructed this fashion constitute the base of automatic include search paths
                     if (AZ::IO::SystemFile::Exists(shaderScanFolder.c_str()))
                     {
-                        options.m_projectIncludePaths.emplace_back(AZStd::move(shaderScanFolder.LexicallyNormal().Native()));
+                        includePaths.emplace_back(AZStd::move(shaderScanFolder.LexicallyNormal().Native()));
                     }
                 }
             }
@@ -337,14 +408,16 @@ namespace AZ
             // finally the <engineroot>/Gems fallback
             AZ::IO::Path engineGemsFolder(AZStd::string_view{ AZ::Utils::GetEnginePath() });
             engineGemsFolder /= "Gems";
-            if (auto it = AZStd::find_if(options.m_projectIncludePaths.begin(), options.m_projectIncludePaths.end(), FindPath(engineGemsFolder));
-                it == options.m_projectIncludePaths.end())
+            if (auto it = AZStd::find_if(includePaths.begin(), includePaths.end(), PathCompare(engineGemsFolder));
+                it == includePaths.end())
             {
                 if (AZ::IO::SystemFile::Exists(engineGemsFolder.c_str()))
                 {
-                    options.m_projectIncludePaths.emplace_back(AZStd::move(engineGemsFolder.Native()));
+                    includePaths.emplace_back(AZStd::move(engineGemsFolder.Native()));
                 }
             }
+
+            return includePaths;
         }
 
     } // namespace ShaderBuilder

+ 10 - 20
Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.h

@@ -67,38 +67,28 @@ namespace AZ
             //!   or "output diagnostics to std.err" or "enable digraphs/trigraphs"...
         };
 
-        //! You can use this canonicalized way to initialize preprocessor options
-        //! It will populate your option with a default base of include folders given by the Asset Processor scan folders.
-        //! This is going to look for a Config/shader_global_build_options.json in one of the scan folders
-        //!  (that file can specify additional include files and preprocessor macros).
-        //! @param options: Outout parameter, will contain the preprocessor options.
         //! @param builderName: Used for debugging.
-        //! @param optionalIncludeFolder: If not null, will be added to the list of include folders for the c-preprocessor in @options.
-        void InitializePreprocessorOptions(PreprocessorOptions& options, const char* builderName, const char* optionalIncludeFolder = nullptr);
+        //! @param optionalIncludeFolder: If not null, will be added at the beginning of the returned list of include folders.
+        //! @returns A list of fully qualified directory paths that will be given to the c-preprocessor to find the included files in .azsl files.
+        AZStd::vector<AZStd::string> BuildListOfIncludeDirectories(const char* builderName, const char* optionalIncludeFolder = nullptr);
+
+        // @returns A new list of command arguments for the C-Preprocessor where each string in @includePaths
+        //     is appended to @preprocessorArguments as "-I<path>".
+        AZStd::vector<AZStd::string> AppendIncludePathsToArgumentList(const AZStd::vector<AZStd::string>& preprocessorArguments, AZStd::vector<AZStd::string> includePaths);
 
         /**
         * Runs the preprocessor on the given source file path, and stores results in outputData.
         * @param fullPath   The file to preprocess
         * @param outputData Collects data from the preprocessor. This will be filled out as much as possible, even if preprocessing fails.
-        * @param options    Control of macros to define and paths to solve includes
+        * @param preprocessorArguments The command line arguments for the C-preprocessor.
         * @param collectDiagnostics If true, warnings and errors will be collected in outputData.diagnostics instead of using AZ_Warning and AZ_Error.
-        * @param preprocessIncludedFiles  By default MCPP follows the chain of included files
-        *        and extracts the content of each file and dumps it in the output.
-        *        Setting this flag to false will prevent mcpp from preprocessing the included files,
-        *        so the produced content will come only from the file given as input to MCPP.
-        *        Setting to false is handy, for example, for the SrgLayoutBuilder from creating SRGs from included files.
-        *        REMARK: You can make the argument of why not simply leave the @m_projectIncludePaths empty?
-        *        It will cause MCPP to error because it won't find the included files. So, in reality the chain
-        *        of included files is validated, but their content won't make it into the output.
-        *        A change is required in azslc so it skips #include lines. SEE: [ATOM-5302]
         * @return false if the preprocessor failed
         */
         bool PreprocessFile(
             const AZStd::string& fullPath,
             PreprocessorData& outputData,
-            const PreprocessorOptions& options,
-            bool collectDiagnostics = false,
-            bool preprocessIncludedFiles = true);
+            const AZStd::vector<AZStd::string>& preprocessorArguments,
+            bool collectDiagnostics = false);
 
         //! Replace all ocurrences of #line "whatever" by #line "whatwewant"
         void MutateLineDirectivesFileOrigin(

+ 28 - 42
Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp

@@ -9,7 +9,6 @@
 #include "ShaderAssetBuilder.h"
 
 #include <CommonFiles/Preprocessor.h>
-#include <CommonFiles/GlobalBuildOptions.h>
 
 #include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
 #include <Atom/RPI.Reflect/Shader/ShaderAssetCreator.h>
@@ -50,7 +49,7 @@
 #include "ShaderVariantAssetBuilder.h"
 #include "ShaderBuilderUtility.h"
 #include "ShaderPlatformInterfaceRequest.h"
-#include "AtomShaderConfig.h"
+#include "ShaderBuildArgumentsManager.h"
 
 #include <AssetBuilderSDK/AssetBuilderSDK.h>
 #include <AssetBuilderSDK/SerializationDependencies.h>
@@ -196,10 +195,10 @@ namespace AZ
                 // report the failure.
             }
 
-            GlobalBuildOptions buildOptions = ReadBuildOptions(ShaderAssetBuilderName);
+            auto projectIncludePaths = BuildListOfIncludeDirectories(ShaderAssetBuilderName);
 
             AZStd::unordered_set<AZStd::string> includedFiles;
-            GetListOfIncludedFiles(azslFullPath, buildOptions.m_preprocessorSettings.m_projectIncludePaths, includedFilesParser, includedFiles);
+            GetListOfIncludedFiles(azslFullPath, projectIncludePaths, includedFilesParser, includedFiles);
             for (auto includePath : includedFiles)
             {
                 AssetBuilderSDK::SourceFileDependency includeFileDependency;
@@ -340,7 +339,15 @@ namespace AZ
             // The directory where the Azsl file was found must be added to the list of include paths
             AZStd::string azslFolderPath;
             AzFramework::StringFunc::Path::GetFolderPath(azslFullPath.c_str(), azslFolderPath);
-            GlobalBuildOptions buildOptions = ReadBuildOptions(ShaderAssetBuilderName, azslFolderPath.c_str());
+            auto projectIncludePaths = BuildListOfIncludeDirectories(ShaderAssetBuilderName, azslFolderPath.c_str());
+
+            ShaderBuildArgumentsManager buildArgsManager;
+            buildArgsManager.Init();
+            // A job always runs on behalf of an Asset Processing platform (aka PlatformInfo).
+            // Let's merge the shader build arguments of the current PlatformInfo with the global
+            // set of arguments.
+            const auto platformName = ShaderBuilderUtility::GetPlatformNameFromPlatformInfo(request.m_platformInfo);
+            buildArgsManager.PushArgumentScope(platformName);
 
             // Request the list of valid shader platform interfaces for the target platform.
             AZStd::vector<RHI::ShaderPlatformInterface*> platformInterfaces = ShaderBuilderUtility::DiscoverEnabledShaderPlatformInterfaces(
@@ -410,17 +417,14 @@ namespace AZ
             // Remark: In general, the work done by the ShaderVariantAssetBuilder is similar, but it will start from the HLSL file created; in step 2, mentioned above; by this builder,
             // for each supervariant. 
 
-            // At this moment We have global build options that should be merged with the build options that are common
-            // to all the supervariants of this shader.
-            buildOptions.m_compilerArguments.Merge(shaderSourceData.m_compiler);
-            buildOptions.m_preprocessorSettings.m_predefinedMacros.insert(
-                buildOptions.m_preprocessorSettings.m_predefinedMacros.end(),
-                shaderSourceData.m_definitions.begin(), shaderSourceData.m_definitions.end());
-
             for (RHI::ShaderPlatformInterface* shaderPlatformInterface : platformInterfaces)
             {
                 AZStd::string apiName(shaderPlatformInterface->GetAPIName().GetCStr());
                 AZ_TraceContext("Platform API", apiName);
+
+                buildArgsManager.PushArgumentScope(apiName);
+                buildArgsManager.PushArgumentScope(shaderSourceData.m_removeBuildArguments, shaderSourceData.m_addBuildArguments, shaderSourceData.m_definitions);
+
                 // Signal the begin of shader data for an RHI API.
                 shaderAssetCreator.BeginAPI(shaderPlatformInterface->GetAPIType());
 
@@ -440,21 +444,12 @@ namespace AZ
                     return;
                 }
 
-                // Cache common AZSLC invokation arguments related with the current RHI Backend.
-                // Each supervariant can, optionally, remove or add more arguments for AZSLc.
-                AZStd::string commonAzslcCompilerParameters =
-                    shaderPlatformInterface->GetAzslCompilerParameters(buildOptions.m_compilerArguments);
-                commonAzslcCompilerParameters += " ";
-                commonAzslcCompilerParameters +=
-                    shaderPlatformInterface->GetAzslCompilerWarningParameters(buildOptions.m_compilerArguments);
-                AtomShaderConfig::AddParametersFromConfigFile(commonAzslcCompilerParameters, request.m_platformInfo);
-
                 // The register number only makes sense if the platform uses "spaces",
                 // since the register Id of the resource will not change even if the pipeline layout changes.
                 // We can pass in a default ShaderCompilerArguments because all we care about is whether the shaderPlatformInterface
                 // appends the "--use-spaces" flag.
-                const bool platformUsesRegisterSpaces =
-                    (AzFramework::StringFunc::Find(commonAzslcCompilerParameters, "--use-spaces") != AZStd::string::npos);
+                const auto& azslcArguments = buildArgsManager.GetCurrentArguments().m_azslcArguments;
+                const bool platformUsesRegisterSpaces = RHI::ShaderBuildArguments::HasArgument(azslcArguments, "--use-spaces");
 
                 uint32_t supervariantIndex = 0;
                 for (const auto& supervariantInfo : supervariantList)
@@ -466,21 +461,14 @@ namespace AZ
                         return;
                     }
 
+                    buildArgsManager.PushArgumentScope(supervariantInfo.m_removeBuildArguments, supervariantInfo.m_addBuildArguments, supervariantInfo.m_definitions);
+
                     shaderAssetCreator.BeginSupervariant(supervariantInfo.m_name);
 
-                    // Let's combine the global macro definitions, with the macro definitions particular to this
-                    // supervariant. Two steps:
-                    // 1- Supervariants can specify which macros to remove from the global definitions.
-                    AZStd::vector<AZStd::string> macroDefinitionNamesToRemove = supervariantInfo.GetCombinedListOfMacroDefinitionNamesToRemove();
-                    PreprocessorOptions preprocessorOptions = buildOptions.m_preprocessorSettings;
-                    preprocessorOptions.RemovePredefinedMacros(macroDefinitionNamesToRemove);
-                    // 2- Supervariants can specify which macros to add.
-                    AZStd::vector<AZStd::string> macroDefinitionsToAdd = supervariantInfo.GetMacroDefinitionsToAdd();
-                    preprocessorOptions.m_predefinedMacros.insert(
-                        preprocessorOptions.m_predefinedMacros.end(), macroDefinitionsToAdd.begin(), macroDefinitionsToAdd.end());
                     // Run the preprocessor.
                     PreprocessorData output;
-                    const bool preprocessorSuccess = PreprocessFile(prependedAzslFilePath, output, preprocessorOptions, true, true);
+                    auto preprocessorArguments = AppendIncludePathsToArgumentList(buildArgsManager.GetCurrentArguments().m_preprocessorArguments, projectIncludePaths);
+                    const bool preprocessorSuccess = PreprocessFile(prependedAzslFilePath, output, preprocessorArguments,  true);
                     RHI::ReportMessages(ShaderAssetBuilderName, output.diagnostics, !preprocessorSuccess);
                     // Dump the preprocessed string as a flat AZSL file with extension .azslin, which will be given to AZSLc to generate the HLSL file.
                     AZStd::string superVariantAzslinStemName = shaderFileName;
@@ -498,15 +486,11 @@ namespace AZ
                     }
                     AZ_TracePrintf(ShaderAssetBuilderName, "Preprocessed AZSL File: %s \n", prependedAzslFilePath.c_str());
 
-                    // Before transpiling the flat-AZSL(.azslin) file into HLSL it is necessary
-                    // to setup the AZSLc arguments as required by the current supervariant.
-                    AZStd::string azslcCompilerParameters = supervariantInfo.GetCustomizedArgumentsForAzslc(commonAzslcCompilerParameters);
-
                     // Ready to transpile the azslin file into HLSL.
                     ShaderBuilder::AzslCompiler azslc(azslinFullPath);
                     AZStd::string hlslFullPath = AZStd::string::format("%s_%s.hlsl", superVariantAzslinStemName.c_str(), apiName.c_str());
                     AzFramework::StringFunc::Path::Join(request.m_tempDirPath.c_str(), hlslFullPath.c_str(), hlslFullPath, true);
-                    auto emitFullOutcome = azslc.EmitFullData(azslcCompilerParameters, hlslFullPath);
+                    auto emitFullOutcome = azslc.EmitFullData(buildArgsManager.GetCurrentArguments().m_azslcArguments, hlslFullPath);
                     if (!emitFullOutcome.IsSuccess())
                     {
                         response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
@@ -608,7 +592,7 @@ namespace AZ
 
                     RHI::Ptr<RHI::PipelineLayoutDescriptor> pipelineLayoutDescriptor =
                         ShaderBuilderUtility::BuildPipelineLayoutDescriptorForApi(
-                            ShaderAssetBuilderName, srgLayoutList, shaderEntryPoints, buildOptions.m_compilerArguments, rootConstantData,
+                            ShaderAssetBuilderName, srgLayoutList, shaderEntryPoints, buildArgsManager.GetCurrentArguments(), rootConstantData,
                             shaderPlatformInterface, bindingDependencies);
                     if (!pipelineLayoutDescriptor)
                     {
@@ -674,7 +658,7 @@ namespace AZ
                     ShaderVariantCreationContext shaderVariantCreationContext = {
                         *shaderPlatformInterface,
                         request.m_platformInfo,
-                        buildOptions.m_compilerArguments,
+                        buildArgsManager.GetCurrentArguments(),
                         request.m_tempDirPath,
                         shaderAssetBuildTimestamp,
                         shaderSourceData,
@@ -734,11 +718,13 @@ namespace AZ
                         }
                     }
 
-
+                    buildArgsManager.PopArgumentScope();
                     supervariantIndex++;
 
                 } // end for the supervariant
 
+                buildArgsManager.PopArgumentScope(); // Pop  .shader arguments
+                buildArgsManager.PopArgumentScope(); // Pop rhi api arguments.
                 shaderAssetCreator.EndAPI();
 
             } // end for all ShaderPlatformInterfaces

+ 237 - 0
Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuildArgumentsManager.cpp

@@ -0,0 +1,237 @@
+/*
+ * 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 "ShaderBuildArgumentsManager.h"
+
+#include <AzCore/Settings/SettingsRegistry.h>
+#include <AzCore/Utils/Utils.h>
+#include <AzCore/Serialization/Json/JsonUtils.h>
+#include <AzCore/IO/FileIO.h>
+
+#include <Atom/RPI.Edit/Common/JsonUtils.h>
+#include <Atom/RHI.Edit/ShaderBuildOptions.h>
+
+namespace AZ
+{
+    namespace ShaderBuilder
+    {
+        static AZStd::string ResolvePathAliases(AZStd::string_view inPath)
+        {
+            AZ::IO::FixedMaxPath resolvedPath;
+            
+            auto fileIO = AZ::IO::FileIOBase::GetInstance();
+            const bool success = fileIO->ResolvePath(resolvedPath, inPath);
+            
+            if (success)
+            {
+                return AZStd::string(resolvedPath.c_str());
+            }
+
+            return { inPath };
+        }
+
+        void ShaderBuildArgumentsManager::Init()
+        {
+            AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> removeBuildArgumentsMap;
+            AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> addBuildArgumentsMap;
+            auto configFiles = DiscoverConfigurationFiles();
+            for (auto const& [scopeName, jsonFilePath] : configFiles)
+            {
+                AZ::RHI::ShaderBuildOptions shaderBuildOptions;
+                if (!AZ::RPI::JsonUtils::LoadObjectFromFile(jsonFilePath.c_str(), shaderBuildOptions))
+                {
+                    AZ_Error(
+                        LogName, false, "Failed to load shader build options file=<%s> for scope=<%s>", jsonFilePath.c_str(),
+                        scopeName.c_str());
+                    continue;
+                }
+                const auto addedDefinitionCount = shaderBuildOptions.m_addBuildArguments.AppendDefinitions(shaderBuildOptions.m_definitions);
+                AZ_Assert(addedDefinitionCount >= 0, "Failed to add definitions");
+
+                removeBuildArgumentsMap.emplace(scopeName, AZStd::move(shaderBuildOptions.m_removeBuildArguments));
+                addBuildArgumentsMap.emplace(scopeName, AZStd::move(shaderBuildOptions.m_addBuildArguments));
+            }
+            Init(AZStd::move(removeBuildArgumentsMap), AZStd::move(addBuildArgumentsMap));
+        }
+
+        void ShaderBuildArgumentsManager::Init(AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> && removeBuildArgumentsMap
+                                             , AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> && addBuildArgumentsMap)
+        {
+            m_removeBuildArgumentsMap.clear();
+            m_removeBuildArgumentsMap.swap(removeBuildArgumentsMap);
+
+            m_addBuildArgumentsMap.clear();
+            m_addBuildArgumentsMap.swap(addBuildArgumentsMap);
+
+            m_argumentsStack = {};
+            m_argumentsNameStack = {};
+            m_argumentsStack.push(m_addBuildArgumentsMap[""]);
+            m_argumentsNameStack.push("");
+        }
+
+        const AZ::RHI::ShaderBuildArguments& ShaderBuildArgumentsManager::PushArgumentsInternal(const AZStd::string& name, const AZ::RHI::ShaderBuildArguments& arguments)
+        {
+            m_argumentsNameStack.push(name);
+            m_argumentsStack.push(arguments);
+            return m_argumentsStack.top();
+        }
+
+        const AZ::RHI::ShaderBuildArguments& ShaderBuildArgumentsManager::PushArgumentScope(const AZStd::string& name)
+        {
+            AZ_Assert(!name.empty(), "This function requires non empty names");
+            const auto& currentTopName = m_argumentsNameStack.top();
+            auto newTopName = currentTopName.empty() ? name : AZStd::string::format("%s.%s", currentTopName.c_str(), name.c_str());
+
+            auto it = m_addBuildArgumentsMap.find(newTopName);
+            if (it == m_addBuildArgumentsMap.end())
+            {
+                // It is normal not to have arguments for a specific key. Because this class works as a stack we'll just push a copy
+                // of whatever is currently at the top of the stack.
+                return PushArgumentsInternal(newTopName, GetCurrentArguments());
+            }
+
+            // Init() guarantees that if there's an Add set of arguments, there is also a Remove set of arguments. BUT either of both, the Add and the Remove Sets can be empty,
+            // what matters is that they are valid instances of ShaderBuildArguments class.
+            auto removeIt = m_removeBuildArgumentsMap.find(newTopName);
+            AZ_Assert(removeIt != m_removeBuildArgumentsMap.end(), "There must be an instance of arguments to remove for %s", currentTopName.c_str());
+
+            auto newArguments = GetCurrentArguments() - removeIt->second;
+            return PushArgumentsInternal(newTopName, newArguments + it->second);
+        }
+
+        const AZ::RHI::ShaderBuildArguments& ShaderBuildArgumentsManager::PushArgumentScope(const AZ::RHI::ShaderBuildArguments& removeArguments,
+            const AZ::RHI::ShaderBuildArguments& addArguments, const AZStd::vector<AZStd::string>& definitions)
+        {
+            const AZStd::string anyName("?");
+            const auto& currentTopName = m_argumentsNameStack.top();
+            auto newTopName = currentTopName.empty() ? anyName : AZStd::string::format("%s.%s", currentTopName.c_str(), anyName.c_str());
+
+            auto newArguments = GetCurrentArguments() - removeArguments;
+            const auto addedDefinitionCount = newArguments.AppendDefinitions(definitions);
+            AZ_Assert(addedDefinitionCount >= 0, "Failed to add definitions");
+
+            return PushArgumentsInternal(newTopName, newArguments + addArguments);
+        }
+
+
+        const AZ::RHI::ShaderBuildArguments& ShaderBuildArgumentsManager::GetCurrentArguments() const
+        {
+            return m_argumentsStack.top();
+        }
+
+
+        void ShaderBuildArgumentsManager::PopArgumentScope()
+        {
+            // We always keep the global scope.
+            if (m_argumentsStack.size() > 1)
+            {
+                m_argumentsStack.pop();
+                m_argumentsNameStack.pop();
+            }
+        }
+
+        void DiscoverConfigurationFilesInDirectoryRecursively(const AZ::IO::FixedMaxPath& dirPath, const AZStd::string& keyName,
+            AZStd::unordered_map<AZStd::string, AZ::IO::FixedMaxPath>& discoveredFiles)
+        {
+            auto findFileCB = [&](const char * fileName, bool isFile) -> bool
+            {
+                if (fileName[0] == '.')
+                {
+                    return true;
+                }
+                AZ::IO::FixedMaxPath fullPath = dirPath / fileName;
+                if (isFile)
+                {
+                    discoveredFiles[keyName] = fullPath;
+                }
+                else
+                {
+                    AZStd::string subKeyName = AZStd::string::format("%s%s%s", keyName.c_str(), keyName.empty() ? "" : ".", fileName);
+                    DiscoverConfigurationFilesInDirectoryRecursively(fullPath, subKeyName, discoveredFiles);
+                }
+                return true;
+            };
+
+            AZ::IO::FixedMaxPath filter(dirPath);
+            filter /= "*";
+            AZ::IO::SystemFile::FindFiles(filter.c_str(), findFileCB);
+        }
+
+        AZStd::unordered_map<AZStd::string, AZ::IO::FixedMaxPath> ShaderBuildArgumentsManager::DiscoverConfigurationFilesInDirectory(const AZ::IO::FixedMaxPath& dirPath)
+        {
+            AZStd::unordered_map<AZStd::string, AZ::IO::FixedMaxPath> configurationFiles;
+
+            auto jsonPath = dirPath / ShaderBuildOptionsJson;
+            if (AZ::IO::SystemFile::Exists(jsonPath.c_str()))
+            {
+                // The global scope has no name.
+                configurationFiles[""] = jsonPath;
+            }
+
+            AZ::IO::FixedMaxPath platformsDirPath(dirPath);
+            platformsDirPath /= PlatformsDir;
+
+            DiscoverConfigurationFilesInDirectoryRecursively(platformsDirPath, "", configurationFiles);
+
+            return configurationFiles;
+        }
+
+
+        AZ::IO::FixedMaxPath ShaderBuildArgumentsManager::GetDefaultConfigDirectoryPath()
+        {
+            AZStd::string defaultConfigDirectory(DefaultConfigPathDirectory);
+            defaultConfigDirectory = ResolvePathAliases(defaultConfigDirectory);
+            // The default directory, which contains factory settings, must always exist.
+            AZ_Assert(AZ::IO::SystemFile::Exists(defaultConfigDirectory.c_str()), "The default directory with shader build arguments must exist: %s", defaultConfigDirectory.c_str());
+            return { defaultConfigDirectory };
+        }
+
+        AZ::IO::FixedMaxPath ShaderBuildArgumentsManager::GetUserConfigDirectoryPath()
+        {
+            AZStd::string userConfig;
+            auto settingsRegistry = AZ::SettingsRegistry::Get();
+            if (settingsRegistry)
+            {
+                settingsRegistry->Get(userConfig, ConfigPathRegistryKey);
+            }
+            if (userConfig.empty())
+            {
+                return {};
+            }
+            userConfig = ResolvePathAliases(userConfig);
+            return { userConfig };
+        }
+
+        AZStd::unordered_map<AZStd::string, AZ::IO::FixedMaxPath> ShaderBuildArgumentsManager::DiscoverConfigurationFiles()
+        {
+            const auto defaultConfigDirectoryPath = GetDefaultConfigDirectoryPath();
+            auto configFiles = DiscoverConfigurationFilesInDirectory(defaultConfigDirectoryPath);
+            auto userConfigPath = GetUserConfigDirectoryPath();
+            if (userConfigPath.empty() || (defaultConfigDirectoryPath == userConfigPath))
+            {
+                // The user chose not to customize the command line arguments.
+                // Let's return the Atom's default.
+                return configFiles;
+            }
+
+            auto userConfigFiles = DiscoverConfigurationFilesInDirectory(userConfigPath);
+
+            // Replace only the file paths that are customized by the user.
+            for (auto const& [key, val] : configFiles)
+            {
+                const auto itor = userConfigFiles.find(key);
+                if (itor == userConfigFiles.end())
+                {
+                    continue;
+                }
+                configFiles[key] = userConfigFiles[key];
+            }
+            return configFiles;
+        }
+    } // namespace ShaderBuilder
+} // AZ

+ 146 - 0
Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuildArgumentsManager.h

@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/base.h>
+#include <AzCore/IO/Path/Path.h>
+
+#include "CommonFiles/CommonTypes.h"
+#include <Atom/RHI.Edit/ShaderBuildArguments.h> 
+
+
+namespace UnitTest
+{
+    class ShaderBuildArgumentsTests;
+}
+
+namespace AZ
+{
+    namespace ShaderBuilder
+    {
+        //! This class manages a stack of ShaderBuildArguments.
+        //! It simplifies command line argument definition at each level
+        //! of the shader build hierarchy:
+        //! 
+        //! {
+        //! push(global arguments)
+        //!     {
+        //!     push(PlatformInfo arguments)
+        //!         {
+        //!         push(RHI arguments)
+        //!             {
+        //!             push(.shader arguments)
+        //!                 {
+        //!                 push(shader.supervariant arguments)
+        //!                 ...
+        //!                 -- build shader with current arguments. --
+        //!                 ...
+        //!                 pop()
+        //!                 }
+        //!             pop() 
+        //!             }
+        //!         pop()
+        //!         }
+        //!     pop()
+        //!     }
+        //! pop()
+        //! }
+        //!
+        //! At each push(), two set of arguments are necessary, the "remove" set and the "add" set.
+        //! The idea is that it allows deep customization of all the shader build arguments by removing
+        //! or adding arguments at each level.
+        class ShaderBuildArgumentsManager final
+        {
+        public:
+            AZ_CLASS_ALLOCATOR(ShaderBuildArgumentsManager, AZ::SystemAllocator, 0);
+
+            static constexpr char LogName[] = "ShaderBuildArgumentsManager";
+
+            // The value of this registry key is customizable by the user.
+            static constexpr char ConfigPathRegistryKey[] = "/O3DE/Atom/Shaders/Build/ConfigPath";
+
+            static constexpr char DefaultConfigPathDirectory[] = "@gemroot:AtomShader@/Config";
+            static constexpr char ShaderBuildOptionsJson[] = "shader_build_options.json";
+            static constexpr char PlatformsDir[] = "Platform";
+
+            //! Always loads all the factory arguments provided by the Atom Gem. In addition
+            //! it checks if the user customized all or some of the arguments with the registry key: @ConfigPathRegistryKey (see above)
+            void Init();
+
+            //! Pushes a new scope of arguments into the stack . The arguments to push are searched internally by the given @name,
+            //! but if such arguments are not found, which is a common situation, then the current set of arguments at the top of the stack
+            //! are pushed again on top of the stack, so subsequent calls to PopArgumentScope() work seamlessly.
+            //! @param name Substring of the internally owned set of arguments.
+            //! For example if the user wants to use the arguments for dx12 on Windows ("Windows.dx12"),
+            //! then it is expected that this function should be called twice, as follows:
+            //!     PushArguments("Windows")
+            //!     PushArguments("dx12")
+            //! The names come from the directory structure under the Platform/ folder:
+            //! - Platform/
+            //!   - Windows/  (Platform name)
+            //!     - dx12/   (RHI name)
+            //!     - vulkan/ (RHI name)
+            //! @returns The resulting (combined, with - and +) set of arguments at the top of the stack.
+            const AZ::RHI::ShaderBuildArguments& PushArgumentScope(const AZStd::string& name);
+
+            //! Similar to above, but the arguments being pushed are anonymous.
+            //! @param removeArguments List of arguments to remove from the top of the stack.
+            //! @param addArguments List of arguments to add to the top of the stack.
+            //! @param definitions Additional arguments, specialized for the C-preprocessor, of the form "MACRO", or "MACRO=VALUE".
+            //! @returns The resulting (combined, with - and +) set of arguments at the top of the stack.
+            const AZ::RHI::ShaderBuildArguments& PushArgumentScope(const AZ::RHI::ShaderBuildArguments& removeArguments,
+                                                               const AZ::RHI::ShaderBuildArguments& addArguments,
+                                                               const AZStd::vector<AZStd::string>& definitions);
+
+            //! @returns The resulting (combined, with - and +) set of arguments at the top of the stack.
+            const AZ::RHI::ShaderBuildArguments& GetCurrentArguments() const;
+
+            //! Your typical stack popping function.
+            //! @remark: The "" (global) arguments are never popped, regardless of how many times this function is called.
+            void PopArgumentScope();
+
+        private:
+            friend class ::UnitTest::ShaderBuildArgumentsTests;
+            void Init(AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> && removeBuildArgumentsMap
+                    , AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> && addBuildArgumentsMap);
+
+            //! @returns A fully qualified path where the factory settings, as provided by Atom, are found.
+            AZ::IO::FixedMaxPath GetDefaultConfigDirectoryPath();
+
+            //! @returns A fully qualified path where the user customized command line arguments are found.
+            //!     The returned path will be empty if the user did not customize the path in the registry.
+            AZ::IO::FixedMaxPath GetUserConfigDirectoryPath();
+
+            //! @param dirPath Starting directory for the search of  shader_build_options.json files.
+            //! @returns A map where the key is the name of the scope, and the value is a fully qualified file path.
+            //! Remarks: Posible scope names are:
+            //!     "global"
+            //!     "<platform>". Example "Android", "Windows", etc
+            //!     "<platform>.<rhi>". Example "Windows.dx12" or "Windows.vulkan".
+            AZStd::unordered_map<AZStd::string, AZ::IO::FixedMaxPath> DiscoverConfigurationFilesInDirectory(const AZ::IO::FixedMaxPath& dirPath);
+
+            AZStd::unordered_map<AZStd::string, AZ::IO::FixedMaxPath> DiscoverConfigurationFiles();
+
+            const AZ::RHI::ShaderBuildArguments& PushArgumentsInternal(const AZStd::string& name, const AZ::RHI::ShaderBuildArguments& arguments);
+
+            //! In this map we store which arguments should be removed for a fully qualified scope of arguments.
+            //! A fully qualified scope name can be:
+            //!     "Windows" or "Windows.dx12" or "Windows.vulkan".
+            AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> m_removeBuildArgumentsMap;
+
+            //! In this map we store which arguments should be added for a fully qualified scope of arguments.
+            //! A fully qualified scope name can be:
+            //!     "" (The global scope) or "Windows" or "Windows.dx12" or "Windows.vulkan".
+            AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> m_addBuildArgumentsMap;
+
+            AZStd::stack<AZ::RHI::ShaderBuildArguments> m_argumentsStack;
+            AZStd::stack<AZStd::string> m_argumentsNameStack;
+        };
+    } // ShaderBuilder namespace
+} // AZ

+ 15 - 3
Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp

@@ -37,7 +37,6 @@
 
 #include "ShaderPlatformInterfaceRequest.h"
 #include "ShaderBuilder_Traits_Platform.h"
-#include "AtomShaderConfig.h"
 
 #include "SrgLayoutUtility.h"
 
@@ -535,7 +534,7 @@ namespace AZ
 
             RHI::Ptr<RHI::PipelineLayoutDescriptor> BuildPipelineLayoutDescriptorForApi(
                 [[maybe_unused]] const char* builderName, const RPI::ShaderResourceGroupLayoutList& srgLayoutList, const MapOfStringToStageType& shaderEntryPoints,
-                const RHI::ShaderCompilerArguments& shaderCompilerArguments, const RootConstantData& rootConstantData,
+                const RHI::ShaderBuildArguments& shaderBuildArguments, const RootConstantData& rootConstantData,
                 RHI::ShaderPlatformInterface* shaderPlatformInterface, BindingDependencies& bindingDependencies /*inout*/)
             {
                 PruneNonEntryFunctions(bindingDependencies, shaderEntryPoints);
@@ -624,7 +623,7 @@ namespace AZ
 
                 // Build platform-specific PipelineLayoutDescriptor data, and finalize
                 if (!shaderPlatformInterface->BuildPipelineLayoutDescriptor(
-                        pipelineLayoutDescriptor, srgInfos, rootConstantInfo, shaderCompilerArguments))
+                        pipelineLayoutDescriptor, srgInfos, rootConstantInfo, shaderBuildArguments))
                 {
                     AZ_Error(builderName, false, "Failed to build pipeline layout descriptor");
                     return nullptr;
@@ -885,6 +884,19 @@ namespace AZ
                 return AZ::Success(AZStd::move(listOfFilePaths));
             }
 
+            AZStd::string GetPlatformNameFromPlatformInfo(const AssetBuilderSDK::PlatformInfo& platformInfo)
+            {
+                auto platformId = AZ::PlatformDefaults::PlatformHelper::GetPlatformIdFromName(platformInfo.m_identifier);
+                switch (platformId)
+                {
+                case AZ::PlatformDefaults::PlatformId::PC :
+                case AZ::PlatformDefaults::PlatformId::SERVER : // Fallthrough. "pc" and "server" are both treated as "Windows".
+                    return { "Windows" };
+                default:
+                    return AZ::PlatformDefaults::PlatformIdToPalFolder(platformId);
+                }
+            }
+
         }  // namespace ShaderBuilderUtility
     } // namespace ShaderBuilder
 } // AZ

+ 2 - 1
Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h

@@ -81,7 +81,7 @@ namespace AZ
                 const char* builderName,
                 const RPI::ShaderResourceGroupLayoutList& srgLayoutList,
                 const MapOfStringToStageType& shaderEntryPoints,
-                const RHI::ShaderCompilerArguments& shaderCompilerArguments,
+                const RHI::ShaderBuildArguments& shaderBuildArguments,
                 const RootConstantData& rootConstantData,
                 RHI::ShaderPlatformInterface* shaderPlatformInterface,
                 BindingDependencies& bindingDependencies /*inout*/);
@@ -141,6 +141,7 @@ namespace AZ
                 const uint32_t rhiUniqueIndex, const AZStd::string& platformIdentifier, const AZStd::string& shaderJsonPath,
                 const uint32_t supervariantIndex, RPI::ShaderAssetSubId shaderAssetSubId);
 
+            AZStd::string GetPlatformNameFromPlatformInfo(const AssetBuilderSDK::PlatformInfo& platformInfo);
 
             class IncludedFilesParser
             {

+ 26 - 15
Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp

@@ -53,9 +53,8 @@
 #include "AzslData.h"
 #include "AzslCompiler.h"
 #include <CommonFiles/Preprocessor.h>
-#include <CommonFiles/GlobalBuildOptions.h>
 #include <ShaderPlatformInterfaceRequest.h>
-#include "AtomShaderConfig.h"
+#include "ShaderBuildArgumentsManager.h"
 
 namespace AZ
 {
@@ -738,6 +737,8 @@ namespace AZ
 
             const auto& jobParameters = request.m_jobDescription.m_jobParameters;
             const AZStd::string& shaderSourceFileFullPath = jobParameters.at(ShaderSourceFilePathJobParam);
+            auto descriptorParseOutcome = ShaderBuilderUtility::LoadShaderDataJson(shaderSourceFileFullPath);
+            RPI::ShaderSourceData shaderSourceData = descriptorParseOutcome.TakeValue();
             AZStd::string shaderFileName;
             AzFramework::StringFunc::Path::GetFileName(shaderSourceFileFullPath.c_str(), shaderFileName);
 
@@ -769,10 +770,13 @@ namespace AZ
 
             auto supervariantList = ShaderBuilderUtility::GetSupervariantListFromShaderSourceData(shaderSourceDescriptor);
 
-            GlobalBuildOptions buildOptions = ReadBuildOptions(ShaderVariantAssetBuilderName);
-            // At this moment We have global build options that should be merged with the build options that are common
-            // to all the supervariants of this shader.
-            buildOptions.m_compilerArguments.Merge(shaderSourceDescriptor.m_compiler);
+            ShaderBuildArgumentsManager buildArgsManager;
+            buildArgsManager.Init();
+            // A job always runs on behalf of an Asset Processing platform (aka PlatformInfo).
+            // Let's merge the shader build arguments of the current PlatformInfo with the global
+            // set of arguments.
+            const auto platformName = ShaderBuilderUtility::GetPlatformNameFromPlatformInfo(request.m_platformInfo);
+            buildArgsManager.PushArgumentScope(platformName);
 
             //! The ShaderOptionGroupLayout is common across all RHIs & Supervariants
             RPI::Ptr<RPI::ShaderOptionGroupLayout> shaderOptionGroupLayout = nullptr;
@@ -780,7 +784,11 @@ namespace AZ
             // Generate shaders for each of those ShaderPlatformInterfaces.
             for (RHI::ShaderPlatformInterface* shaderPlatformInterface : platformInterfaces)
             {
-                AZ_TraceContext("ShaderPlatformInterface", shaderPlatformInterface->GetAPIName().GetCStr());
+                AZStd::string apiName(shaderPlatformInterface->GetAPIName().GetCStr());
+                AZ_TraceContext("Platform API", apiName);
+
+                buildArgsManager.PushArgumentScope(apiName);
+                buildArgsManager.PushArgumentScope(shaderSourceData.m_removeBuildArguments, shaderSourceData.m_addBuildArguments, shaderSourceData.m_definitions);
 
                 // Loop through all the Supervariants.
                 uint32_t supervariantIndexCounter = 0;
@@ -796,6 +804,8 @@ namespace AZ
                         return;
                     }
 
+                    buildArgsManager.PushArgumentScope(supervariantInfo.m_removeBuildArguments, supervariantInfo.m_addBuildArguments, supervariantInfo.m_definitions);
+
                     AZStd::string shaderStemNamePrefix = shaderFileName;
                     if (supervariantIndex.GetIndex() > 0)
                     {
@@ -856,10 +866,8 @@ namespace AZ
                     RHI::Ptr<RHI::PipelineLayoutDescriptor> pipelineLayoutDescriptor;
                     if (shaderPlatformInterface->VariantCompilationRequiresSrgLayoutData())
                     {
-                        AZStd::string azslcCompilerParameters =
-                            shaderPlatformInterface->GetAzslCompilerParameters(buildOptions.m_compilerArguments);
-                        const bool platformUsesRegisterSpaces =
-                            (AzFramework::StringFunc::Find(azslcCompilerParameters, "--use-spaces") != AZStd::string::npos);
+                        const auto& azslcArguments = buildArgsManager.GetCurrentArguments().m_azslcArguments;
+                        const bool platformUsesRegisterSpaces = RHI::ShaderBuildArguments::HasArgument(azslcArguments, "--use-spaces");
                     
                         RPI::ShaderResourceGroupLayoutList srgLayoutList;
                         RootConstantData rootConstantData;
@@ -884,7 +892,7 @@ namespace AZ
                         
                         pipelineLayoutDescriptor =
                             ShaderBuilderUtility::BuildPipelineLayoutDescriptorForApi(
-                                ShaderVariantAssetBuilderName, srgLayoutList, shaderEntryPoints, buildOptions.m_compilerArguments, rootConstantData,
+                                ShaderVariantAssetBuilderName, srgLayoutList, shaderEntryPoints, buildArgsManager.GetCurrentArguments(), rootConstantData,
                                 shaderPlatformInterface, bindingDependencies);
                         if (!pipelineLayoutDescriptor)
                         {
@@ -899,7 +907,7 @@ namespace AZ
                     // Setup the shader variant creation context:
                     ShaderVariantCreationContext shaderVariantCreationContext =
                     {
-                        *shaderPlatformInterface, request.m_platformInfo, buildOptions.m_compilerArguments, request.m_tempDirPath,
+                        *shaderPlatformInterface, request.m_platformInfo, buildArgsManager.GetCurrentArguments(), request.m_tempDirPath,
                         shaderVariantAssetBuildTimestamp,
                         shaderSourceDescriptor,
                         *shaderOptionGroupLayout.get(),
@@ -949,9 +957,12 @@ namespace AZ
                             response.m_outputProducts.push_back(AZStd::move(jobProduct));
                         }
                     }
+                    buildArgsManager.PopArgumentScope(); // Pop the supervariant build arguments.
                     supervariantIndexCounter++;
                 } // End of supervariant for block
-                
+
+                buildArgsManager.PopArgumentScope(); // Pop the .shader build arguments.
+                buildArgsManager.PopArgumentScope(); // Pop the RHI build arguments.
             }
 
             response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
@@ -1103,7 +1114,7 @@ namespace AZ
                 RHI::ShaderPlatformInterface::StageDescriptor descriptor;
                 bool shaderWasCompiled = creationContext.m_shaderPlatformInterface.CompilePlatformInternal(
                     creationContext.m_platformInfo, variantShaderSourcePath, shaderEntryName, assetBuilderShaderType,
-                    creationContext.m_tempDirPath, descriptor, creationContext.m_shaderCompilerArguments);
+                    creationContext.m_tempDirPath, descriptor, creationContext.m_shaderBuildArguments);
 
                 if (!shaderWasCompiled)
                 {

+ 1 - 1
Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.h

@@ -33,7 +33,7 @@ namespace AZ
         {
             RHI::ShaderPlatformInterface& m_shaderPlatformInterface;
             const AssetBuilderSDK::PlatformInfo& m_platformInfo;
-            const RHI::ShaderCompilerArguments& m_shaderCompilerArguments;
+            const RHI::ShaderBuildArguments& m_shaderBuildArguments;
             //! Used to write temporary files during shader compilation, like *.hlsl, or *.air, or *.metallib, etc.
             const AZStd::string& m_tempDirPath;
             //! Used to synchronize versions of the ShaderAsset and ShaderVariantAsset,

+ 2 - 0
Gems/Atom/Asset/Shader/Code/Tests/Common/ShaderBuilderTestFixture.cpp

@@ -11,6 +11,8 @@
 #include <AzCore/Memory/PoolAllocator.h>
 #include <AzCore/Name/NameDictionary.h>
 
+#include <AzslShaderBuilderSystemComponent.h>
+
 namespace UnitTest
 {
     void ShaderBuilderTestFixture::SetUp()

+ 8 - 0
Gems/Atom/Asset/Shader/Code/Tests/Common/ShaderBuilderTestFixture.h

@@ -9,6 +9,13 @@
 #pragma once
 
 #include <AzCore/UnitTest/TestTypes.h>
+#include <AzCore/Component/ComponentApplication.h> // Galib
+#include <AzFramework/IO/LocalFileIO.h>
+#include <AzCore/Serialization/Json/JsonSystemComponent.h>
+#include <AzCore/Serialization/Json/RegistrationContext.h>
+#include <AzCore/Serialization/ObjectStream.h>
+#include <AzCore/Serialization/SerializeContext.h>
+#include <AzCore/Serialization/Utils.h>
 
 namespace UnitTest
 {
@@ -25,6 +32,7 @@ namespace UnitTest
         void SetUp() override;
         void TearDown() override;
         ///////////////////////////////////////////////////////////////////////
+
     };
 } // namespace UnitTest
 

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác