diff --git a/AutomatedTesting/EngineFinder.cmake b/AutomatedTesting/EngineFinder.cmake index fbbe3d8cfe..eef3aa3cae 100644 --- a/AutomatedTesting/EngineFinder.cmake +++ b/AutomatedTesting/EngineFinder.cmake @@ -15,6 +15,8 @@ include_guard() # Read the engine name from the project_json file file(READ ${CMAKE_CURRENT_LIST_DIR}/project.json project_json) +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/project.json) + string(JSON LY_ENGINE_NAME_TO_USE ERROR_VARIABLE json_error GET ${project_json} engine) if(json_error) message(FATAL_ERROR "Unable to read key 'engine' from 'project.json', error: ${json_error}") @@ -30,6 +32,7 @@ endif() # Find a key that matches LY_ENGINE_NAME_TO_USE and use that as the engine path. if(EXISTS ${manifest_path}) file(READ ${manifest_path} manifest_json) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${manifest_path}) string(JSON engines_path_count ERROR_VARIABLE json_error LENGTH ${manifest_json} engines_path) if(json_error) diff --git a/AutomatedTesting/Gem/PythonTests/NvCloth/TestSuite_Active.py b/AutomatedTesting/Gem/PythonTests/NvCloth/TestSuite_Active.py index 86bfc48636..aae01e4652 100755 --- a/AutomatedTesting/Gem/PythonTests/NvCloth/TestSuite_Active.py +++ b/AutomatedTesting/Gem/PythonTests/NvCloth/TestSuite_Active.py @@ -24,12 +24,11 @@ from base import TestAutomationBase @pytest.mark.parametrize("launcher_platform", ['windows_editor']) @pytest.mark.parametrize("project", ["AutomatedTesting"]) class TestAutomation(TestAutomationBase): - @pytest.mark.xfail(reason="Running with atom null renderer is causing this test to fail") + def test_C18977329_NvCloth_AddClothSimulationToMesh(self, request, workspace, editor, launcher_platform): from . import C18977329_NvCloth_AddClothSimulationToMesh as test_module self._run_test(request, workspace, editor, test_module) - @pytest.mark.xfail(reason="Running with atom null renderer is causing this test to fail") def test_C18977330_NvCloth_AddClothSimulationToActor(self, request, workspace, editor, launcher_platform): from . import C18977330_NvCloth_AddClothSimulationToActor as test_module self._run_test(request, workspace, editor, test_module) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/assetpipeline/CMakeLists.txt index f453a38486..f47d57b7bd 100644 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/CMakeLists.txt @@ -13,13 +13,6 @@ add_subdirectory(asset_processor_tests) if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) ## AP Python Tests ## - ly_add_pytest( - NAME AssetPipelineTests.AuxiliaryContent - PATH ${CMAKE_CURRENT_LIST_DIR}/auxiliary_content_tests/auxiliary_content_tests.py - EXCLUDE_TEST_RUN_TARGET_FROM_IDE - TEST_SUITE periodic - ) - ly_add_pytest( NAME AssetPipelineTests.BankInfoParser PATH ${CMAKE_CURRENT_LIST_DIR}/wwise_bank_dependency_tests/bank_info_parser_tests.py diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/auxiliary_content_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/auxiliary_content_tests.py deleted file mode 100755 index 452dc66352..0000000000 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/auxiliary_content_tests.py +++ /dev/null @@ -1,96 +0,0 @@ -""" -All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -its licensors. - -For complete copyright and license terms please see the LICENSE at the root of this -distribution (the "License"). All use of this software is governed by the License, -or, if provided, by the license below or the license accompanying this file. Do not -remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - -""" -import pytest -import ly_test_tools - -import os -import sys -import shutil -import subprocess -import glob -from ly_test_tools.builtin.helpers import * -from ly_test_tools.environment.process_utils import * -from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP - -logger = logging.getLogger(__name__) - -project_list = ['AutomatedTesting'] - -@pytest.mark.system -@pytest.mark.SUITE_periodic -class TestAuxiliaryContent: - @pytest.fixture(autouse=True) - def setup_teardown(self, request, workspace, project): - path_to_dev = workspace.paths.engine_root() - os.chdir(path_to_dev) - auxiliaryContentDirName = str.lower(project) + f"_{ASSET_PROCESSOR_PLATFORM_MAP[workspace.asset_processor_platform]}_paks" - self.auxiliaryContentPath = os.path.join(path_to_dev, auxiliaryContentDirName) - - def teardown(): - if (os.path.exists(self.auxiliaryContentPath)): - shutil.rmtree(self.auxiliaryContentPath) - - request.addfinalizer(teardown) - - @staticmethod - def scanForLevelPak(path_toscan): - files = glob.glob('{0}/**/level.pak'.format(path_toscan), recursive=True) - return len(files) - - @pytest.mark.parametrize('level', ['alldependencies']) - @pytest.mark.parametrize('project', project_list) - def test_CreateAuxiliaryContent_DontSkipLevelPaks(self, workspace, level): - """ - This test ensure that Auxiliary Content contain level.pak files - - Test Steps: - 1. Run auxiliary content against project under test - 2. Validate auxiliary content exists - 3. Verifies that level.pak exists - """ - - path_to_dev = workspace.paths.engine_root() - bin_path = workspace.paths.build_directory() - - auxiliaryContentScriptPath = os.path.join(path_to_dev, 'BuildReleaseAuxiliaryContent.py') - subprocess.check_call(['python', auxiliaryContentScriptPath, - "--buildFolder={0}".format(bin_path), - "--platforms=pc", - f"--project-path={workspace.project}"]) - - assert os.path.exists(self.auxiliaryContentPath) - assert not self.scanForLevelPak(self.auxiliaryContentPath) == 0 - - @pytest.mark.parametrize('level', ['alldependencies']) - @pytest.mark.parametrize('project', project_list) - def test_CreateAuxiliaryContent_SkipLevelPaks(self, workspace, level): - """ - This test ensure that Auxiliary Content contain no level.pak file - - Test Steps: - 1. Run auxiliary content against project under test with skiplevelPaks flag - 2. Validate auxiliary content exists - 3. Validate level.pak was added to auxiliary content - """ - - path_to_dev = workspace.paths.engine_root() - bin_path = workspace.paths.build_directory() - - auxiliaryContentScriptPath = os.path.join(path_to_dev, 'BuildReleaseAuxiliaryContent.py') - subprocess.check_call(['python', auxiliaryContentScriptPath, - "--buildFolder={0}".format(bin_path), - "--platforms=pc", - "--skiplevelPaks", - f"--project-path={workspace.project}"]) - assert os.path.exists(self.auxiliaryContentPath) - - assert self.scanForLevelPak(self.auxiliaryContentPath) == 0 diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py b/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py index 57cdc8f9c5..40291b2114 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py @@ -102,7 +102,7 @@ def C4044695_PhysXCollider_AddMultipleSurfaceFbx(): # 6) Check if multiple material slots show up under Materials section in the PhysX Collider component pte = collider_component.get_property_tree() def get_surface_count(): - count = pte.get_container_count("Collider Configuration|Physics Material|Mesh Surfaces") + count = pte.get_container_count("Collider Configuration|Physics Materials|Slots") return count.GetValue() Report.result( diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py index 2b82c3e596..291bb96627 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py +++ b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py @@ -93,11 +93,13 @@ class TestAutomation(TestAutomationBase): self._run_test(request, workspace, editor, test_module) @revert_physics_config + @fm.file_override('physxsystemconfiguration.setreg','C4044457_Material_RestitutionCombine.setreg_override', 'AutomatedTesting/Registry') def test_C4044457_Material_RestitutionCombine(self, request, workspace, editor, launcher_platform): from . import C4044457_Material_RestitutionCombine as test_module self._run_test(request, workspace, editor, test_module) @revert_physics_config + @fm.file_override('physxsystemconfiguration.setreg','C4044456_Material_FrictionCombine.setreg_override', 'AutomatedTesting/Registry') def test_C4044456_Material_FrictionCombine(self, request, workspace, editor, launcher_platform): from . import C4044456_Material_FrictionCombine as test_module self._run_test(request, workspace, editor, test_module) @@ -194,6 +196,7 @@ class TestAutomation(TestAutomationBase): self._run_test(request, workspace, editor, test_module) @revert_physics_config + @fm.file_override('physxsystemconfiguration.setreg','C18981526_Material_RestitutionCombinePriority.setreg_override', 'AutomatedTesting/Registry') def test_C18981526_Material_RestitutionCombinePriority(self, request, workspace, editor, launcher_platform): from . import C18981526_Material_RestitutionCombinePriority as test_module self._run_test(request, workspace, editor, test_module) @@ -229,6 +232,7 @@ class TestAutomation(TestAutomationBase): self._run_test(request, workspace, editor, test_module) @revert_physics_config + @fm.file_override('physxsystemconfiguration.setreg','C18977601_Material_FrictionCombinePriority.setreg_override', 'AutomatedTesting/Registry') def test_C18977601_Material_FrictionCombinePriority(self, request, workspace, editor, launcher_platform): from . import C18977601_Material_FrictionCombinePriority as test_module self._run_test(request, workspace, editor, test_module) @@ -250,6 +254,7 @@ class TestAutomation(TestAutomationBase): @pytest.mark.xfail( reason="This test needs new physics asset with multiple materials to be more stable.") @revert_physics_config + @fm.file_override('physxsystemconfiguration.setreg','C4044697_Material_PerfaceMaterialValidation.setreg_override', 'AutomatedTesting/Registry') def test_C4044697_Material_PerfaceMaterialValidation(self, request, workspace, editor, launcher_platform): from . import C4044697_Material_PerfaceMaterialValidation as test_module self._run_test(request, workspace, editor, test_module) @@ -282,6 +287,7 @@ class TestAutomation(TestAutomationBase): self._run_test(request, workspace, editor, test_module) @revert_physics_config + @fm.file_override('physxsystemconfiguration.setreg','C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.setreg_override', 'AutomatedTesting/Registry') def test_C15556261_PhysXMaterials_CharacterControllerMaterialAssignment(self, request, workspace, editor, launcher_platform): from . import C15556261_PhysXMaterials_CharacterControllerMaterialAssignment as test_module self._run_test(request, workspace, editor, test_module) @@ -326,6 +332,7 @@ class TestAutomation(TestAutomationBase): self._run_test(request, workspace, editor, test_module) @revert_physics_config + @fm.file_override('physxsystemconfiguration.setreg','C4044461_Material_Restitution.setreg_override', 'AutomatedTesting/Registry') def test_C4044461_Material_Restitution(self, request, workspace, editor, launcher_platform): from . import C4044461_Material_Restitution as test_module self._run_test(request, workspace, editor, test_module) diff --git a/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/C18977329_NvCloth_AddClothSimulationToMesh.ly b/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/C18977329_NvCloth_AddClothSimulationToMesh.ly index 1afbf787db..9a1b1fe59a 100644 --- a/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/C18977329_NvCloth_AddClothSimulationToMesh.ly +++ b/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/C18977329_NvCloth_AddClothSimulationToMesh.ly @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e15d484113e8151072b410924747a8ad304f6f12457fad577308c0491693ab34 -size 5472 +oid sha256:6517300fb1ce70c4696286e14715c547cfd175eabbb2042f7f2a456b15054224 +size 5253 diff --git a/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/filelist.xml b/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/filelist.xml index 9775a35c53..2cf4d55bf0 100644 --- a/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/filelist.xml +++ b/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/filelist.xml @@ -1,6 +1,6 @@ - + diff --git a/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/level.pak b/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/level.pak index 08a775b6c8..954bb1912f 100644 --- a/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/level.pak +++ b/AutomatedTesting/Levels/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh/level.pak @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:64de37c805b0be77cdb7a85b5406af58b7f845e7d97fec1721ac5d789bb641db -size 38856 +oid sha256:ce32a7cdf3ed37751385b3bb18f05206702978363f325d06727b5eb20d40b7eb +size 38563 diff --git a/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/C18977330_NvCloth_AddClothSimulationToActor.ly b/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/C18977330_NvCloth_AddClothSimulationToActor.ly index 385027c479..9ef8bc0525 100644 --- a/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/C18977330_NvCloth_AddClothSimulationToActor.ly +++ b/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/C18977330_NvCloth_AddClothSimulationToActor.ly @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b595323d4d51211463dea0338abb6ce2a4a0a8d41efb12ac3c9dccd1f972171 -size 5504 +oid sha256:89dbcec013cb819e52ec0f8fed0a9e417fd32eac8aeb67d3958266bb6089ec21 +size 5505 diff --git a/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/filelist.xml b/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/filelist.xml index 7ccc1d51eb..a7de99a91c 100644 --- a/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/filelist.xml +++ b/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/filelist.xml @@ -1,6 +1,6 @@ - + diff --git a/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/level.pak b/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/level.pak index 12ce03fa87..ad10c72b31 100644 --- a/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/level.pak +++ b/AutomatedTesting/Levels/NvCloth/C18977330_NvCloth_AddClothSimulationToActor/level.pak @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:617c455668fc41cb7fd69de690e4aa3c80f2cb36deaa371902b79de18fcd1cb2 -size 39233 +oid sha256:622c2624b04e07b704520f32c458b50d5a50de1ef116b7bc9c3c0ccb6f4a4ecc +size 3606 diff --git a/AutomatedTesting/Levels/Physics/C5340400_RigidBody_ManualMomentOfInertia/C5340400_RigidBody_ManualMomentOfInertia.ly b/AutomatedTesting/Levels/Physics/C5340400_RigidBody_ManualMomentOfInertia/C5340400_RigidBody_ManualMomentOfInertia.ly index a649728997..87166a9d8d 100644 --- a/AutomatedTesting/Levels/Physics/C5340400_RigidBody_ManualMomentOfInertia/C5340400_RigidBody_ManualMomentOfInertia.ly +++ b/AutomatedTesting/Levels/Physics/C5340400_RigidBody_ManualMomentOfInertia/C5340400_RigidBody_ManualMomentOfInertia.ly @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6e408095c15a388768b7f70b6049f33c894aab3e51f2d744bc1ae1d18668ee4 -size 9694 +oid sha256:824a51a375f19274d5698ff08af0fdc3dc18204505c73a943de748455d108b01 +size 6181 diff --git a/AutomatedTesting/Registry/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.setreg_override b/AutomatedTesting/Registry/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.setreg_override new file mode 100644 index 0000000000..a329434623 --- /dev/null +++ b/AutomatedTesting/Registry/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.setreg_override @@ -0,0 +1,115 @@ +{ + "Amazon": { + "Gems": { + "PhysX": { + "PhysXSystemConfiguration": { + "CollisionConfig": { + "Layers": { + "LayerNames": [ + "Default", + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + "TouchBend" + ] + }, + "Groups": { + "GroupPresets": [ + { + "Name": "All", + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}" + }, + "Name": "None", + "Group": { + "Mask": 0 + }, + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}" + }, + "Name": "All_NoTouchBend", + "Group": { + "Mask": 9223372036854775807 + }, + "ReadOnly": true + } + ] + } + }, + "MaterialLibrary": { + "assetId": { + "guid": "{70D4A444-AFD4-57C4-9885-63F25AC3C281}" + }, + "loadBehavior": "QueueLoad", + "assetHint": "levels/physics/c15556261_physxmaterials_charactercontrollermaterialassignment/library.physmaterial" + } + } + } + } + } +} \ No newline at end of file diff --git a/AutomatedTesting/Registry/C18977601_Material_FrictionCombinePriority.setreg_override b/AutomatedTesting/Registry/C18977601_Material_FrictionCombinePriority.setreg_override new file mode 100644 index 0000000000..44a91c67cb --- /dev/null +++ b/AutomatedTesting/Registry/C18977601_Material_FrictionCombinePriority.setreg_override @@ -0,0 +1,115 @@ +{ + "Amazon": { + "Gems": { + "PhysX": { + "PhysXSystemConfiguration": { + "CollisionConfig": { + "Layers": { + "LayerNames": [ + "Default", + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + "TouchBend" + ] + }, + "Groups": { + "GroupPresets": [ + { + "Name": "All", + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}" + }, + "Name": "None", + "Group": { + "Mask": 0 + }, + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}" + }, + "Name": "All_NoTouchBend", + "Group": { + "Mask": 9223372036854775807 + }, + "ReadOnly": true + } + ] + } + }, + "MaterialLibrary": { + "assetId": { + "guid": "{B8749DAB-15DA-5A61-B565-C853673604CD}" + }, + "loadBehavior": "QueueLoad", + "assetHint": "levels/physics/c18977601_material_frictioncombinepriority/friction_combine.physmaterial" + } + } + } + } + } +} \ No newline at end of file diff --git a/AutomatedTesting/Registry/C18981526_Material_RestitutionCombinePriority.setreg_override b/AutomatedTesting/Registry/C18981526_Material_RestitutionCombinePriority.setreg_override new file mode 100644 index 0000000000..8de10787f1 --- /dev/null +++ b/AutomatedTesting/Registry/C18981526_Material_RestitutionCombinePriority.setreg_override @@ -0,0 +1,115 @@ +{ + "Amazon": { + "Gems": { + "PhysX": { + "PhysXSystemConfiguration": { + "CollisionConfig": { + "Layers": { + "LayerNames": [ + "Default", + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + "TouchBend" + ] + }, + "Groups": { + "GroupPresets": [ + { + "Name": "All", + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}" + }, + "Name": "None", + "Group": { + "Mask": 0 + }, + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}" + }, + "Name": "All_NoTouchBend", + "Group": { + "Mask": 9223372036854775807 + }, + "ReadOnly": true + } + ] + } + }, + "MaterialLibrary": { + "assetId": { + "guid": "{AED48B18-0F3F-5E59-A8FF-30DB134B307B}" + }, + "loadBehavior": "QueueLoad", + "assetHint": "levels/physics/c18981526_material_restitutioncombinepriority/restitution_combine.physmaterial" + } + } + } + } + } +} \ No newline at end of file diff --git a/AutomatedTesting/Registry/C4044456_Material_FrictionCombine.setreg_override b/AutomatedTesting/Registry/C4044456_Material_FrictionCombine.setreg_override new file mode 100644 index 0000000000..83f7079e1f --- /dev/null +++ b/AutomatedTesting/Registry/C4044456_Material_FrictionCombine.setreg_override @@ -0,0 +1,115 @@ +{ + "Amazon": { + "Gems": { + "PhysX": { + "PhysXSystemConfiguration": { + "CollisionConfig": { + "Layers": { + "LayerNames": [ + "Default", + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + "TouchBend" + ] + }, + "Groups": { + "GroupPresets": [ + { + "Name": "All", + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}" + }, + "Name": "None", + "Group": { + "Mask": 0 + }, + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}" + }, + "Name": "All_NoTouchBend", + "Group": { + "Mask": 9223372036854775807 + }, + "ReadOnly": true + } + ] + } + }, + "MaterialLibrary": { + "assetId": { + "guid": "{8D2C4A29-E0FC-564F-82C9-24BBA30C5A90}" + }, + "loadBehavior": "QueueLoad", + "assetHint": "levels/physics/c4044456_material_frictioncombine/friction_combine.physmaterial" + } + } + } + } + } +} \ No newline at end of file diff --git a/AutomatedTesting/Registry/C4044457_Material_RestitutionCombine.setreg_override b/AutomatedTesting/Registry/C4044457_Material_RestitutionCombine.setreg_override new file mode 100644 index 0000000000..96836b6ae4 --- /dev/null +++ b/AutomatedTesting/Registry/C4044457_Material_RestitutionCombine.setreg_override @@ -0,0 +1,115 @@ +{ + "Amazon": { + "Gems": { + "PhysX": { + "PhysXSystemConfiguration": { + "CollisionConfig": { + "Layers": { + "LayerNames": [ + "Default", + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + "TouchBend" + ] + }, + "Groups": { + "GroupPresets": [ + { + "Name": "All", + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}" + }, + "Name": "None", + "Group": { + "Mask": 0 + }, + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}" + }, + "Name": "All_NoTouchBend", + "Group": { + "Mask": 9223372036854775807 + }, + "ReadOnly": true + } + ] + } + }, + "MaterialLibrary": { + "assetId": { + "guid": "{D5D6A6DE-E636-5638-B30D-6CE2FDC321F8}" + }, + "loadBehavior": "QueueLoad", + "assetHint": "levels/physics/c4044457_material_restitutioncombine/restitution_combine.physmaterial" + } + } + } + } + } +} \ No newline at end of file diff --git a/AutomatedTesting/Registry/C4044461_Material_Restitution.setreg_override b/AutomatedTesting/Registry/C4044461_Material_Restitution.setreg_override new file mode 100644 index 0000000000..21b285506b --- /dev/null +++ b/AutomatedTesting/Registry/C4044461_Material_Restitution.setreg_override @@ -0,0 +1,115 @@ +{ + "Amazon": { + "Gems": { + "PhysX": { + "PhysXSystemConfiguration": { + "CollisionConfig": { + "Layers": { + "LayerNames": [ + "Default", + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + "TouchBend" + ] + }, + "Groups": { + "GroupPresets": [ + { + "Name": "All", + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}" + }, + "Name": "None", + "Group": { + "Mask": 0 + }, + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}" + }, + "Name": "All_NoTouchBend", + "Group": { + "Mask": 9223372036854775807 + }, + "ReadOnly": true + } + ] + } + }, + "MaterialLibrary": { + "assetId": { + "guid": "{E4117B5B-8D9A-5C1D-BA1E-C36542A6588D}" + }, + "loadBehavior": "QueueLoad", + "assetHint": "levels/physics/c4044461_material_restitution/restitution.physmaterial" + } + } + } + } + } +} \ No newline at end of file diff --git a/AutomatedTesting/Registry/C4044697_Material_PerfaceMaterialValidation.setreg_override b/AutomatedTesting/Registry/C4044697_Material_PerfaceMaterialValidation.setreg_override new file mode 100644 index 0000000000..d585a4c468 --- /dev/null +++ b/AutomatedTesting/Registry/C4044697_Material_PerfaceMaterialValidation.setreg_override @@ -0,0 +1,115 @@ +{ + "Amazon": { + "Gems": { + "PhysX": { + "PhysXSystemConfiguration": { + "CollisionConfig": { + "Layers": { + "LayerNames": [ + "Default", + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + "TouchBend" + ] + }, + "Groups": { + "GroupPresets": [ + { + "Name": "All", + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}" + }, + "Name": "None", + "Group": { + "Mask": 0 + }, + "ReadOnly": true + }, + { + "Id": { + "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}" + }, + "Name": "All_NoTouchBend", + "Group": { + "Mask": 9223372036854775807 + }, + "ReadOnly": true + } + ] + } + }, + "MaterialLibrary": { + "assetId": { + "guid": "{2E85B457-ED19-5FE3-90B4-6EFFB4D0E682}" + }, + "loadBehavior": "QueueLoad", + "assetHint": "levels/physics/c4044697_material_perfacematerialvalidation/test_library.physmaterial" + } + } + } + } + } +} \ No newline at end of file diff --git a/AutomatedTesting/ScriptCanvas/C12712455_ScriptCanvas_ShapeCastVerification.scriptcanvas b/AutomatedTesting/ScriptCanvas/C12712455_ScriptCanvas_ShapeCastVerification.scriptcanvas index b24a477a2e..9b1357eebe 100644 --- a/AutomatedTesting/ScriptCanvas/C12712455_ScriptCanvas_ShapeCastVerification.scriptcanvas +++ b/AutomatedTesting/ScriptCanvas/C12712455_ScriptCanvas_ShapeCastVerification.scriptcanvas @@ -3,34 +3,34 @@ - + - + - + - + - + - + - + - + @@ -39,77 +39,23 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + @@ -127,7 +73,7 @@ - + @@ -142,7 +88,7 @@ - + @@ -170,7 +116,7 @@ - + @@ -208,7 +154,7 @@ - + @@ -253,46 +199,58 @@ - + + + + + + + + + + + + + - - + + - + - + - + - + - + - + - + @@ -307,7 +265,7 @@ - + @@ -335,7 +293,7 @@ - + @@ -350,7 +308,93 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -378,7 +422,7 @@ - + @@ -416,7 +460,7 @@ - + @@ -455,42 +499,64 @@ - + - - - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + @@ -498,21 +564,21 @@ - + - + - + - + @@ -521,23 +587,18 @@ - - - - - - + - + - + @@ -555,7 +616,7 @@ - + @@ -570,7 +631,7 @@ - + @@ -598,7 +659,7 @@ - + @@ -636,7 +697,215 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -713,21 +982,12 @@ - - - - - - - - - - + - + @@ -1321,7 +1581,7 @@ - + @@ -1386,285 +1646,36 @@ - + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - + @@ -1692,7 +1703,7 @@ - + @@ -1707,7 +1718,7 @@ - + @@ -1735,7 +1746,7 @@ - + @@ -1744,13 +1755,8 @@ - - - - - - + @@ -1761,13 +1767,13 @@ - + - + @@ -1778,7 +1784,7 @@ - + @@ -1787,89 +1793,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -1898,86 +1823,64 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + - + - + - + - + - - + + - + - + - + - + - + - + - + @@ -1986,14 +1889,9 @@ - - - - - - - + + @@ -2002,211 +1900,304 @@ - - + + - + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - + - - - - - - + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - + - + - + - + - + - + - + - + @@ -2216,28 +2207,28 @@ - + - + - + - + - + - + - + @@ -2247,28 +2238,28 @@ - + - + - + - + - + - + - + @@ -2278,28 +2269,28 @@ - + - + - + - + - + - + - + @@ -2309,28 +2300,28 @@ - + - + - + - + - + - + - + @@ -2340,28 +2331,28 @@ - + - + - + - + - + - + - + @@ -2371,28 +2362,28 @@ - + - + - + - + - + - + - + @@ -2402,28 +2393,28 @@ - + - + - + - + - + - + - + @@ -2433,28 +2424,28 @@ - + - + - + - + - + - + - + @@ -2470,7 +2461,7 @@ - + @@ -2478,20 +2469,22 @@ - + - - - + + + + - - - + + + + @@ -2502,17 +2495,15 @@ - - - - + + + - - - - + + + @@ -2520,7 +2511,7 @@ - + @@ -2528,27 +2519,21 @@ - + - + - - - - - - - + @@ -2557,25 +2542,10 @@ - - - - - - - - - - - - - - - - - - + + + @@ -2583,7 +2553,7 @@ - + @@ -2591,27 +2561,21 @@ - + - + - - - - - - - + @@ -2620,12 +2584,18 @@ + + + + + + - + @@ -2633,27 +2603,21 @@ - + - + - - - - - - - + @@ -2662,46 +2626,52 @@ + + + + + + - + - - - + + + + - - - + + + + - + - - - - + + + - - - - + + + @@ -2709,7 +2679,7 @@ - + @@ -2717,7 +2687,7 @@ - + @@ -2734,24 +2704,24 @@ - - - - - - + + + + + + - + @@ -2759,7 +2729,7 @@ - + @@ -2776,16 +2746,37 @@ + + + + + + - + + + + + + + + + + - - - + + + + + + + + + @@ -2793,41 +2784,41 @@ - + - - - + + + + - - - + + + + - + - - - - + + + - - - - + + + @@ -2838,20 +2829,20 @@ - - + + - + - + - - + + @@ -2868,7 +2859,7 @@ - + diff --git a/Code/Framework/AzCore/AzCore/Math/ColorSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/ColorSerializer.cpp index 3f7a3c3a5d..0d45a3fb6c 100644 --- a/Code/Framework/AzCore/AzCore/Math/ColorSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Math/ColorSerializer.cpp @@ -36,6 +36,12 @@ namespace AZ Color* color = reinterpret_cast(outputValue); AZ_Assert(color, "Output value for JsonColorSerializer can't be null."); + if (IsExplicitDefault(inputValue)) + { + *color = Color::CreateZero(); + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Color value set to default of zero."); + } + switch (inputValue.GetType()) { case rapidjson::kArrayType: @@ -43,10 +49,14 @@ namespace AZ case rapidjson::kObjectType: return LoadObject(*color, inputValue, context); - case rapidjson::kStringType: // fall through - case rapidjson::kNumberType: // fall through - case rapidjson::kNullType: // fall through - case rapidjson::kFalseType: // fall through + case rapidjson::kStringType: + [[fallthrough]]; + case rapidjson::kNumberType: + [[fallthrough]]; + case rapidjson::kNullType: + [[fallthrough]]; + case rapidjson::kFalseType: + [[fallthrough]]; case rapidjson::kTrueType: return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, "Unsupported type. Colors can only be read from arrays or objects."); @@ -91,6 +101,11 @@ namespace AZ } } + auto JsonColorSerializer::GetOperationsFlags() const -> OperationFlags + { + return OperationFlags::InitializeNewInstance; + } + JsonSerializationResult::Result JsonColorSerializer::LoadObject(Color& output, const rapidjson::Value& inputValue, JsonDeserializerContext& context) { diff --git a/Code/Framework/AzCore/AzCore/Math/ColorSerializer.h b/Code/Framework/AzCore/AzCore/Math/ColorSerializer.h index b7b948a25a..cd16506b28 100644 --- a/Code/Framework/AzCore/AzCore/Math/ColorSerializer.h +++ b/Code/Framework/AzCore/AzCore/Math/ColorSerializer.h @@ -28,6 +28,8 @@ namespace AZ JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override; + OperationFlags GetOperationsFlags() const override; + private: enum class LoadAlpha { diff --git a/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp index 0b7e3300cf..7f412f68e6 100644 --- a/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.cpp @@ -263,7 +263,7 @@ namespace AZ::JsonMathMatrixSerializerInternal template JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, - const rapidjson::Value& inputValue, JsonDeserializerContext& context) + const rapidjson::Value& inputValue, JsonDeserializerContext& context, bool isExplicitDefault) { namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. @@ -279,6 +279,12 @@ namespace AZ::JsonMathMatrixSerializerInternal MatrixType* matrix = reinterpret_cast(outputValue); AZ_Assert(matrix, "Output value for JsonMatrix%zux%zuSerializer can't be null.", RowCount, ColumnCount); + if (isExplicitDefault) + { + *matrix = MatrixType::CreateIdentity(); + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Matrix value set to identity matrix."); + } + switch (inputValue.GetType()) { case rapidjson::kArrayType: @@ -381,6 +387,16 @@ namespace AZ::JsonMathMatrixSerializerInternal namespace AZ { + // BaseJsonMatrixSerializer + + AZ_CLASS_ALLOCATOR_IMPL(BaseJsonMatrixSerializer, SystemAllocator, 0); + + auto BaseJsonMatrixSerializer::GetOperationsFlags() const -> OperationFlags + { + return OperationFlags::InitializeNewInstance; + } + + // Matrix3x3 AZ_CLASS_ALLOCATOR_IMPL(JsonMatrix3x3Serializer, SystemAllocator, 0); @@ -389,10 +405,7 @@ namespace AZ const rapidjson::Value& inputValue, JsonDeserializerContext& context) { return JsonMathMatrixSerializerInternal::Load( - outputValue, - outputValueTypeId, - inputValue, - context); + outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonMatrix3x3Serializer::Store(rapidjson::Value& outputValue, const void* inputValue, @@ -401,11 +414,7 @@ namespace AZ outputValue.SetObject(); return JsonMathMatrixSerializerInternal::StoreRotationAndScale( - outputValue, - inputValue, - defaultValue, - valueTypeId, - context); + outputValue, inputValue, defaultValue, valueTypeId, context); } @@ -417,10 +426,7 @@ namespace AZ const rapidjson::Value& inputValue, JsonDeserializerContext& context) { return JsonMathMatrixSerializerInternal::Load( - outputValue, - outputValueTypeId, - inputValue, - context); + outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonMatrix3x4Serializer::Store(rapidjson::Value& outputValue, const void* inputValue, @@ -428,19 +434,11 @@ namespace AZ { outputValue.SetObject(); - auto result = JsonMathMatrixSerializerInternal::StoreRotationAndScale( - outputValue, - inputValue, - defaultValue, - valueTypeId, - context); + auto result = + JsonMathMatrixSerializerInternal::StoreRotationAndScale(outputValue, inputValue, defaultValue, valueTypeId, context); - auto resultTranslation = JsonMathMatrixSerializerInternal::StoreTranslation( - outputValue, - inputValue, - defaultValue, - valueTypeId, - context); + auto resultTranslation = + JsonMathMatrixSerializerInternal::StoreTranslation(outputValue, inputValue, defaultValue, valueTypeId, context); result.GetResultCode().Combine(resultTranslation); return result; @@ -454,10 +452,7 @@ namespace AZ const rapidjson::Value& inputValue, JsonDeserializerContext& context) { return JsonMathMatrixSerializerInternal::Load( - outputValue, - outputValueTypeId, - inputValue, - context); + outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonMatrix4x4Serializer::Store(rapidjson::Value& outputValue, const void* inputValue, @@ -465,19 +460,11 @@ namespace AZ { outputValue.SetObject(); - auto result = JsonMathMatrixSerializerInternal::StoreRotationAndScale( - outputValue, - inputValue, - defaultValue, - valueTypeId, - context); - - auto resultTranslation = JsonMathMatrixSerializerInternal::StoreTranslation( - outputValue, - inputValue, - defaultValue, - valueTypeId, - context); + auto result = + JsonMathMatrixSerializerInternal::StoreRotationAndScale(outputValue, inputValue, defaultValue, valueTypeId, context); + + auto resultTranslation = + JsonMathMatrixSerializerInternal::StoreTranslation(outputValue, inputValue, defaultValue, valueTypeId, context); result.GetResultCode().Combine(resultTranslation); return result; diff --git a/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.h b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.h index 81c9635a79..773859a2c8 100644 --- a/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.h +++ b/Code/Framework/AzCore/AzCore/Math/MathMatrixSerializer.h @@ -16,11 +16,18 @@ namespace AZ { - class JsonMatrix3x3Serializer - : public BaseJsonSerializer + class BaseJsonMatrixSerializer : public BaseJsonSerializer { public: - AZ_RTTI(JsonMatrix3x3Serializer, "{8C76CD6A-8576-4604-A746-CF7A7F20F366}", BaseJsonSerializer); + AZ_RTTI(BaseJsonMatrixSerializer, "{18CA4637-C9B7-454B-9126-107E18A8C096}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + OperationFlags GetOperationsFlags() const override; + }; + + class JsonMatrix3x3Serializer : public BaseJsonMatrixSerializer + { + public: + AZ_RTTI(JsonMatrix3x3Serializer, "{8C76CD6A-8576-4604-A746-CF7A7F20F366}", BaseJsonMatrixSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -28,11 +35,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonMatrix3x4Serializer - : public BaseJsonSerializer + class JsonMatrix3x4Serializer : public BaseJsonMatrixSerializer { public: - AZ_RTTI(JsonMatrix3x4Serializer, "{E801333B-4AF1-4F43-976C-579670B02DC5}", BaseJsonSerializer); + AZ_RTTI(JsonMatrix3x4Serializer, "{E801333B-4AF1-4F43-976C-579670B02DC5}", BaseJsonMatrixSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -40,11 +46,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonMatrix4x4Serializer - : public BaseJsonSerializer + class JsonMatrix4x4Serializer : public BaseJsonMatrixSerializer { public: - AZ_RTTI(JsonMatrix4x4Serializer, "{46E888FC-248A-4910-9221-4E101A10AEA1}", BaseJsonSerializer); + AZ_RTTI(JsonMatrix4x4Serializer, "{46E888FC-248A-4910-9221-4E101A10AEA1}", BaseJsonMatrixSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; diff --git a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp index aa9686f709..7225f1713c 100644 --- a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.cpp @@ -124,7 +124,7 @@ namespace AZ template JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, - JsonDeserializerContext& context) + JsonDeserializerContext& context, bool isExplicitDefault) { namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. @@ -138,6 +138,12 @@ namespace AZ VectorType* vector = reinterpret_cast(outputValue); AZ_Assert(vector, "Output value for JsonVector%iSerializer can't be null.", ElementCount); + if (isExplicitDefault) + { + *vector = VectorType::CreateZero(); + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Math vector value set to default of zero."); + } + switch (inputValue.GetType()) { case rapidjson::kArrayType: @@ -145,10 +151,14 @@ namespace AZ case rapidjson::kObjectType: return LoadObject(*vector, inputValue, context); - case rapidjson::kStringType: // fall through - case rapidjson::kNumberType: // fall through - case rapidjson::kNullType: // fall through - case rapidjson::kFalseType: // fall through + case rapidjson::kStringType: + [[fallthrough]]; + case rapidjson::kNumberType: + [[fallthrough]]; + case rapidjson::kNullType: + [[fallthrough]]; + case rapidjson::kFalseType: + [[fallthrough]]; case rapidjson::kTrueType: return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, "Unsupported type. Math vectors can only be read from arrays or objects."); @@ -189,6 +199,16 @@ namespace AZ } } + + // BaseJsonVectorSerializer + + AZ_CLASS_ALLOCATOR_IMPL(BaseJsonVectorSerializer, SystemAllocator, 0); + + auto BaseJsonVectorSerializer::GetOperationsFlags() const -> OperationFlags + { + return OperationFlags::InitializeNewInstance; + } + // Vector2 @@ -197,7 +217,8 @@ namespace AZ JsonSerializationResult::Result JsonVector2Serializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) { - return JsonMathVectorSerializerInternal::Load(outputValue, outputValueTypeId, inputValue, context); + return JsonMathVectorSerializerInternal::Load( + outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonVector2Serializer::Store(rapidjson::Value& outputValue, const void* inputValue, @@ -214,7 +235,8 @@ namespace AZ JsonSerializationResult::Result JsonVector3Serializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) { - return JsonMathVectorSerializerInternal::Load(outputValue, outputValueTypeId, inputValue, context); + return JsonMathVectorSerializerInternal::Load( + outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonVector3Serializer::Store(rapidjson::Value& outputValue, const void* inputValue, @@ -231,7 +253,8 @@ namespace AZ JsonSerializationResult::Result JsonVector4Serializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) { - return JsonMathVectorSerializerInternal::Load(outputValue, outputValueTypeId, inputValue, context); + return JsonMathVectorSerializerInternal::Load( + outputValue, outputValueTypeId, inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonVector4Serializer::Store(rapidjson::Value& outputValue, const void* inputValue, @@ -252,7 +275,7 @@ namespace AZ // check for "yaw, pitch, roll" object if (inputValue.IsObject()) { - if (inputValue.GetObject().ObjectEmpty()) + if (IsExplicitDefault(inputValue)) { Quaternion* outQuaternion = reinterpret_cast(outputValue); *outQuaternion = Quaternion::CreateIdentity(); @@ -283,7 +306,7 @@ namespace AZ return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success, "Successfully read quaternion."); } - return JsonMathVectorSerializerInternal::Load(outputValue, outputValueTypeId, inputValue, context); + return JsonMathVectorSerializerInternal::Load(outputValue, outputValueTypeId, inputValue, context, false); } JsonSerializationResult::Result JsonQuaternionSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, diff --git a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h index 9c2606b932..0f81709c17 100644 --- a/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h +++ b/Code/Framework/AzCore/AzCore/Math/MathVectorSerializer.h @@ -16,11 +16,18 @@ namespace AZ { - class JsonVector2Serializer - : public BaseJsonSerializer + class BaseJsonVectorSerializer : public BaseJsonSerializer { public: - AZ_RTTI(JsonVector2Serializer, "{E1EAA209-9682-4120-B26B-3EDD9AD56D6F}", BaseJsonSerializer); + AZ_RTTI(BaseJsonVectorSerializer, "{C188D355-E6DF-4590-8B31-F40591F48A8E}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + OperationFlags GetOperationsFlags() const override; + }; + + class JsonVector2Serializer : public BaseJsonVectorSerializer + { + public: + AZ_RTTI(JsonVector2Serializer, "{E1EAA209-9682-4120-B26B-3EDD9AD56D6F}", BaseJsonVectorSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -28,11 +35,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonVector3Serializer - : public BaseJsonSerializer + class JsonVector3Serializer : public BaseJsonVectorSerializer { public: - AZ_RTTI(JsonVector3Serializer, "{BF82BBF3-3CD9-48DA-97CC-E4DF2EF01552}", BaseJsonSerializer); + AZ_RTTI(JsonVector3Serializer, "{BF82BBF3-3CD9-48DA-97CC-E4DF2EF01552}", BaseJsonVectorSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -40,11 +46,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonVector4Serializer - : public BaseJsonSerializer + class JsonVector4Serializer : public BaseJsonVectorSerializer { public: - AZ_RTTI(JsonVector4Serializer, "{05B45EA7-7102-4281-8AA0-2AC72D74AAFD}", BaseJsonSerializer); + AZ_RTTI(JsonVector4Serializer, "{05B45EA7-7102-4281-8AA0-2AC72D74AAFD}", BaseJsonVectorSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -52,11 +57,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonQuaternionSerializer - : public BaseJsonSerializer + class JsonQuaternionSerializer : public BaseJsonVectorSerializer { public: - AZ_RTTI(JsonQuaternionSerializer, "{18604375-3606-49AC-B366-0F6DF9149FF3}", BaseJsonSerializer); + AZ_RTTI(JsonQuaternionSerializer, "{18604375-3606-49AC-B366-0F6DF9149FF3}", BaseJsonVectorSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; diff --git a/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp index 36c40265af..b3c9ea3b7c 100644 --- a/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp @@ -33,6 +33,12 @@ namespace AZ AZ::Transform* transformInstance = reinterpret_cast(outputValue); AZ_Assert(transformInstance, "Output value for JsonTransformSerializer can't be null."); + if (IsExplicitDefault(inputValue)) + { + *transformInstance = AZ::Transform::CreateIdentity(); + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Transform value set to identity."); + } + JSR::ResultCode result(JSR::Tasks::ReadField); { @@ -72,7 +78,7 @@ namespace AZ return context.Report( result, - result.GetProcessing() != JSR::Processing::Halted ? "Succesfully loaded Transform information." + result.GetProcessing() != JSR::Processing::Halted ? "Successfully loaded Transform information." : "Failed to load Transform information."); } @@ -140,4 +146,9 @@ namespace AZ : "Failed to store Transform information."); } + auto JsonTransformSerializer::GetOperationsFlags() const -> OperationFlags + { + return OperationFlags::InitializeNewInstance; + } + } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Math/TransformSerializer.h b/Code/Framework/AzCore/AzCore/Math/TransformSerializer.h index e03c41e31d..ef277f831a 100644 --- a/Code/Framework/AzCore/AzCore/Math/TransformSerializer.h +++ b/Code/Framework/AzCore/AzCore/Math/TransformSerializer.h @@ -30,6 +30,8 @@ namespace AZ rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override; + OperationFlags GetOperationsFlags() const override; + private: // Note: These need to be defined as "const char[]" instead of "const char*" so that they can be implicitly converted // to a rapidjson::GenericStringRef<>. (This also lets rapidjson get the string length at compile time) diff --git a/Code/Framework/AzCore/AzCore/Math/UuidSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/UuidSerializer.cpp index 9da7b11805..458744d5b2 100644 --- a/Code/Framework/AzCore/AzCore/Math/UuidSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Math/UuidSerializer.cpp @@ -33,6 +33,11 @@ namespace AZ AZStd::regex_constants::icase | AZStd::regex_constants::optimize); } + auto JsonUuidSerializer::GetOperationsFlags() const -> OperationFlags + { + return OperationFlags::InitializeNewInstance; + } + JsonSerializationResult::Result JsonUuidSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) { @@ -53,13 +58,24 @@ namespace AZ Uuid* valAsUuid = reinterpret_cast(outputValue); + if (IsExplicitDefault(inputValue)) + { + *valAsUuid = AZ::Uuid::CreateNull(); + return MessageResult("Uuid value set to default of null.", JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed)); + } + switch (inputValue.GetType()) { - case rapidjson::kArrayType: // fallthrough - case rapidjson::kObjectType:// fallthrough - case rapidjson::kFalseType: // fallthrough - case rapidjson::kTrueType: // fallthrough - case rapidjson::kNumberType:// fallthrough + case rapidjson::kArrayType: + [[fallthrough]]; + case rapidjson::kObjectType: + [[fallthrough]]; + case rapidjson::kFalseType: + [[fallthrough]]; + case rapidjson::kTrueType: + [[fallthrough]]; + case rapidjson::kNumberType: + [[fallthrough]]; case rapidjson::kNullType: return MessageResult("Unsupported type. Uuids can only be read from strings.", JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported)); diff --git a/Code/Framework/AzCore/AzCore/Math/UuidSerializer.h b/Code/Framework/AzCore/AzCore/Math/UuidSerializer.h index 1c350a2fcd..43487dcc10 100644 --- a/Code/Framework/AzCore/AzCore/Math/UuidSerializer.h +++ b/Code/Framework/AzCore/AzCore/Math/UuidSerializer.h @@ -41,6 +41,8 @@ namespace AZ JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override; + OperationFlags GetOperationsFlags() const override; + //! Does the same as load, but doesn't report through the provided callback in the settings. Instead the final //! ResultCode and message are returned and it's up to the caller to report if need needed. MessageResult UnreportedLoad(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue); diff --git a/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl b/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl index 9bda5cdcce..ebe7d27a8e 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl +++ b/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl @@ -406,6 +406,7 @@ namespace AZ AZStd::vector eventParamsTypes{ AZStd::initializer_list{ CreateBehaviorEventParameter>()... } }; behaviorContext->Class>() + ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly) ->Attribute(AZ::Script::Attributes::EventHandlerCreationFunction, createHandlerHolder) ->Attribute(AZ::Script::Attributes::EventParameterTypes, eventParamsTypes) ->Method("HasHandlerConnected", &AZ::Event::HasHandlerConnected) @@ -413,6 +414,7 @@ namespace AZ behaviorContext->Class>() ->Method("Disconnect", &AZ::EventHandler::Disconnect) + ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly) ; } } diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.cpp index d5a1730364..2e53eb5697 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.cpp @@ -32,13 +32,24 @@ namespace AZ switch (inputValue.GetType()) { case rapidjson::kArrayType: - return LoadContainer(outputValue, outputValueTypeId, inputValue, context); + return LoadContainer(outputValue, outputValueTypeId, inputValue, false, context); - case rapidjson::kObjectType: // fall through - case rapidjson::kNullType: // fall through - case rapidjson::kStringType: // fall through - case rapidjson::kFalseType: // fall through - case rapidjson::kTrueType: // fall through + case rapidjson::kObjectType: + if (IsExplicitDefault(inputValue)) + { + // Because this serializer has only the operation flag "InitializeNewInstance" set, the only time this will be called with + // an explicit default is when a new instance has been created. + return LoadContainer(outputValue, outputValueTypeId, inputValue, true, context); + } + [[fallthrough]]; + case rapidjson::kNullType: + [[fallthrough]]; + case rapidjson::kStringType: + [[fallthrough]]; + case rapidjson::kFalseType: + [[fallthrough]]; + case rapidjson::kTrueType: + [[fallthrough]]; case rapidjson::kNumberType: return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, "Unsupported type. AZStd::array entries can only be read from an array."); @@ -129,7 +140,16 @@ namespace AZ } } - JsonSerializationResult::Result JsonArraySerializer::LoadContainer(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + auto JsonArraySerializer::GetOperationsFlags() const -> OperationFlags + { + return OperationFlags::InitializeNewInstance; + } + + JsonSerializationResult::Result JsonArraySerializer::LoadContainer( + void* outputValue, + const Uuid& outputValueTypeId, + const rapidjson::Value& inputValue, + bool isNewInstance, JsonDeserializerContext& context) { namespace JSR = JsonSerializationResult; // Used to remove name conflicts in AzCore in uber builds. @@ -154,14 +174,7 @@ namespace AZ "Unable to retrieve the correct container information for AZStd::array instance."); } - const size_t size = container->Size(outputValue); - if (inputValue.Size() < size) - { - return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, - "Not enough entries in JSON array to load an AZStd::array from."); - } - - ContinuationFlags flags = ContinuationFlags::None; + ContinuationFlags flags = isNewInstance ? ContinuationFlags::LoadAsNewInstance : ContinuationFlags::None; Uuid elementTypeId = Uuid::CreateNull(); auto typeEnumCallback = [&elementTypeId, &flags](const Uuid&, const SerializeContext::ClassElement* genericClassElement) { @@ -175,13 +188,23 @@ namespace AZ }; container->EnumTypes(typeEnumCallback); + const size_t size = container->Size(outputValue); + if (!isNewInstance && inputValue.Size() < size) + { + return context.Report( + JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, "Not enough entries in JSON array to load an AZStd::array from."); + } + + rapidjson::Value explicitDefaultValue = GetExplicitDefault(); + JSR::ResultCode retVal(JSR::Tasks::ReadField); for (size_t i = 0; i < size; ++i) { ScopedContextPath subPath(context, i); void* element = container->GetElementByIndex(outputValue, nullptr, i); - JSR::ResultCode result = ContinueLoading(element, elementTypeId, inputValue[aznumeric_caster(i)], context, flags); + JSR::ResultCode result = ContinueLoading( + element, elementTypeId, isNewInstance ? explicitDefaultValue : inputValue[aznumeric_caster(i)], context, flags); if (result.GetProcessing() == JSR::Processing::Halted) { return context.Report(result, "Failed to load data to element in AZStd::array."); @@ -189,15 +212,19 @@ namespace AZ retVal.Combine(result); } - if (container->Size(outputValue) == inputValue.Size()) + if (isNewInstance) + { + return context.Report(retVal, "Filled new instance of AZStd::array with defaults."); + } + else if (container->Size(outputValue) == inputValue.Size()) { return context.Report(retVal, "Successfully read entries into AZStd::array."); } else { retVal.Combine(JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::Skipped)); - return context.Report(retVal, - "Successfully read available entries into AZStd::array, but there were still values left in the JSON array."); + return context.Report( + retVal, "Successfully read available entries into AZStd::array, but there were still values left in the JSON array."); } } } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.h index 11edc87139..a6d8dd37e3 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ArraySerializer.h @@ -30,8 +30,14 @@ namespace AZ JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override; + OperationFlags GetOperationsFlags() const override; + protected: - JsonSerializationResult::Result LoadContainer(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + JsonSerializationResult::Result LoadContainer( + void* outputValue, + const Uuid& outputValueTypeId, + const rapidjson::Value& inputValue, + bool isNewInstance, JsonDeserializerContext& context); }; } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp index 9a426a1e59..666fa0f96a 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.cpp @@ -216,9 +216,10 @@ namespace AZ JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueLoading( void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context, ContinuationFlags flags) { + bool loadAsNewInstance = (flags & ContinuationFlags::LoadAsNewInstance) == ContinuationFlags::LoadAsNewInstance; return (flags & ContinuationFlags::ResolvePointer) == ContinuationFlags::ResolvePointer ? JsonDeserializer::LoadToPointer(object, typeId, value, context) - : JsonDeserializer::Load(object, typeId, value, context); + : JsonDeserializer::Load(object, typeId, value, loadAsNewInstance, context); } JsonSerializationResult::ResultCode BaseJsonSerializer::ContinueStoring( diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h index 06c5eda6de..99b63bf4de 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BaseJsonSerializer.h @@ -163,15 +163,20 @@ namespace AZ enum class ContinuationFlags { - None = 0, //! No extra flags. - ResolvePointer = 1 << 0, //! The pointer passed in contains a pointer. The (de)serializer will attempt to resolve to an instance. - ReplaceDefault = 1 << 1 //! The default value provided for storing will be replaced with a newly created one. + None = 0, //! No extra flags. + ResolvePointer = 1 << 0, //! The pointer passed in contains a pointer. The (de)serializer will attempt to resolve to an instance. + ReplaceDefault = 1 << 1, //! The default value provided for storing will be replaced with a newly created one. + LoadAsNewInstance = 1 << 2 //! Treats the value as if it's a newly created instance. This may trigger serializers marked with + //! OperationFlags::InitializeNewInstance. Used for instance by pointers or new instances added to + //! an array. }; enum class OperationFlags { - None = 0, //! No flags that control how the custom json serializer is used. - ManualDefault = 1 << 0 //! Even if an (explicit) default is found the custom json serializer will still be called. + None = 0, //! No flags that control how the custom json serializer is used. + ManualDefault = 1 << 0, //! Even if an (explicit) default is found the custom json serializer will still be called. + InitializeNewInstance = 1 << 1 //! If set, the custom json serializer will be called with an explicit default if a new + //! instance of its target type is created. }; virtual ~BaseJsonSerializer() = default; diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BasicContainerSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/BasicContainerSerializer.cpp index 400a3b7949..d61366413f 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BasicContainerSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BasicContainerSerializer.cpp @@ -34,11 +34,16 @@ namespace AZ case rapidjson::kArrayType: return LoadContainer(outputValue, outputValueTypeId, inputValue, context); - case rapidjson::kObjectType: // fall through - case rapidjson::kNullType: // fall through - case rapidjson::kStringType: // fall through - case rapidjson::kFalseType: // fall through - case rapidjson::kTrueType: // fall through + case rapidjson::kObjectType: + [[fallthrough]]; + case rapidjson::kNullType: + [[fallthrough]]; + case rapidjson::kStringType: + [[fallthrough]]; + case rapidjson::kFalseType: + [[fallthrough]]; + case rapidjson::kTrueType: + [[fallthrough]]; case rapidjson::kNumberType: return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, "Unsupported type. Basic containers can only be read from an array."); @@ -123,6 +128,10 @@ namespace AZ { if (retVal.HasDoneWork()) { + // If at least one value was written, even if it has all defaults, then the array has + // a value written to it and is therefore not in a default state anymore. + retVal.Combine(JSR::ResultCode(JSR::Tasks::WriteValue, JSR::Outcomes::Success)); + outputValue = AZStd::move(array); return context.Report(retVal, "Content written to basic container."); } @@ -165,6 +174,7 @@ namespace AZ ContinuationFlags flags = classElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ? ContinuationFlags::ResolvePointer : ContinuationFlags::None; + flags |= ContinuationFlags::LoadAsNewInstance; const size_t capacity = container->IsFixedCapacity() ? container->Capacity(outputValue) : std::numeric_limits::max(); @@ -243,6 +253,11 @@ namespace AZ } size_t addedCount = container->Size(outputValue) - containerSize; + if (addedCount > 0) + { + // Values were added which means the container is no longer in its default state of being empty. + retVal.Combine(JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::Success)); + } AZStd::string_view message = addedCount >= arraySize ? "Successfully read basic container.": addedCount == 0 ? "Unable to read data for basic container." : diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.cpp index d37e512ac2..3a9b5323b0 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.cpp @@ -82,12 +82,18 @@ namespace AZ bool* valAsBool = reinterpret_cast(outputValue); + if (IsExplicitDefault(inputValue)) + { + *valAsBool = {}; + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Boolean value set to default of 'false'."); + } + switch (inputValue.GetType()) { case rapidjson::kArrayType: - // fallthrough + [[fallthrough]]; case rapidjson::kObjectType: - // fallthrough + [[fallthrough]]; case rapidjson::kNullType: return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, "Unsupported type. Booleans can't be read from arrays, objects or null."); @@ -96,7 +102,7 @@ namespace AZ return SerializerInternal::TextToValue(valAsBool, inputValue.GetString(), inputValue.GetStringLength(), context); case rapidjson::kFalseType: - // fallthrough + [[fallthrough]]; case rapidjson::kTrueType: *valAsBool = inputValue.GetBool(); return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success, "Successfully read boolean."); @@ -145,4 +151,9 @@ namespace AZ return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "Default boolean used."); } + + auto JsonBoolSerializer::GetOperationsFlags() const -> OperationFlags + { + return OperationFlags::InitializeNewInstance; + } } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.h index ac288c73ed..f000a03317 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/BoolSerializer.h @@ -27,5 +27,6 @@ namespace AZ JsonDeserializerContext& context) override; JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override; + OperationFlags GetOperationsFlags() const override; }; } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.cpp index 9140be7fcd..0921587041 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.cpp @@ -62,19 +62,26 @@ namespace AZ } template - static JsonSerializationResult::Result Load(T* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context) + static JsonSerializationResult::Result Load( + T* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context, bool isExplicitDefault) { namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. static_assert(AZStd::is_floating_point::value, "Expected T to be a floating point type"); AZ_Assert(outputValue, "Expected a valid pointer to load from json value."); + if (isExplicitDefault) + { + *outputValue = {}; + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Floating point value set to default of 0.0."); + } + switch (inputValue.GetType()) { case rapidjson::kArrayType: - // fallthrough + [[fallthrough]]; case rapidjson::kObjectType: - // fallthrough + [[fallthrough]]; case rapidjson::kNullType: return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, "Unsupported type. Floating point values can't be read from arrays, objects or null."); @@ -83,7 +90,7 @@ namespace AZ return TextToValue(outputValue, inputValue.GetString(), context); case rapidjson::kFalseType: - // fallthrough + [[fallthrough]]; case rapidjson::kTrueType: *outputValue = inputValue.GetBool() ? 1.0f : 0.0f; return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success, @@ -144,7 +151,8 @@ namespace AZ "Unable to deserialize double to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - return SerializerFloatingPointInternal::Load(reinterpret_cast(outputValue), inputValue, context); + return SerializerFloatingPointInternal::Load( + reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonDoubleSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, @@ -156,6 +164,11 @@ namespace AZ return SerializerFloatingPointInternal::Store(outputValue, inputValue, defaultValue, context); } + auto JsonDoubleSerializer::GetOperationsFlags() const -> OperationFlags + { + return OperationFlags::InitializeNewInstance; + } + JsonSerializationResult::Result JsonFloatSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) { @@ -163,7 +176,8 @@ namespace AZ "Unable to deserialize float to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - return SerializerFloatingPointInternal::Load(reinterpret_cast(outputValue), inputValue, context); + return SerializerFloatingPointInternal::Load( + reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonFloatSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, @@ -174,4 +188,9 @@ namespace AZ AZ_UNUSED(valueTypeId); return SerializerFloatingPointInternal::Store(outputValue, inputValue, defaultValue, context); } + + auto JsonFloatSerializer::GetOperationsFlags() const -> OperationFlags + { + return OperationFlags::InitializeNewInstance; + } } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.h index 81e631d9ab..a8c37316f0 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/DoubleSerializer.h @@ -28,6 +28,7 @@ namespace AZ JsonDeserializerContext& context) override; JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override; + OperationFlags GetOperationsFlags() const override; }; class JsonFloatSerializer @@ -40,5 +41,6 @@ namespace AZ JsonDeserializerContext& context) override; JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override; + OperationFlags GetOperationsFlags() const override; }; } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.cpp index cc365da4f7..a6b1118ac1 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.cpp @@ -25,6 +25,8 @@ namespace AZ { + AZ_CLASS_ALLOCATOR_IMPL(BaseJsonIntegerSerializer, SystemAllocator, 0); + AZ_CLASS_ALLOCATOR_IMPL(JsonCharSerializer, SystemAllocator, 0); AZ_CLASS_ALLOCATOR_IMPL(JsonShortSerializer, SystemAllocator, 0); AZ_CLASS_ALLOCATOR_IMPL(JsonIntSerializer, SystemAllocator, 0); @@ -56,19 +58,25 @@ namespace AZ template static JsonSerializationResult::Result LoadInt(T* outputValue, const rapidjson::Value& inputValue, - JsonDeserializerContext& context) + JsonDeserializerContext& context, bool isDefaultValue) { namespace JSR = JsonSerializationResult; // Used remove name conflicts in AzCore in uber builds. static_assert(AZStd::is_integral(), "Expected T to be a signed or unsigned type"); AZ_Assert(outputValue, "Expected a valid pointer to load from json value."); + if (isDefaultValue) + { + *outputValue = {}; + return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, "Integer value set to default of zero."); + } + switch (inputValue.GetType()) { case rapidjson::kArrayType: - // fallthrough + [[fallthrough]]; case rapidjson::kObjectType: - // fallthrough + [[fallthrough]]; case rapidjson::kNullType: return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, "Unsupported type. Integers can't be read from arrays, objects or null."); @@ -77,7 +85,7 @@ namespace AZ return TextToValue(outputValue, inputValue.GetString(), context); case rapidjson::kFalseType: - // fallthrough + [[fallthrough]]; case rapidjson::kTrueType: *outputValue = inputValue.GetBool() ? 1 : 0; return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success, @@ -125,6 +133,11 @@ namespace AZ } } // namespace SerializerInternal + auto BaseJsonIntegerSerializer::GetOperationsFlags() const -> OperationFlags + { + return OperationFlags::InitializeNewInstance; + } + JsonSerializationResult::Result JsonCharSerializer::Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) { @@ -132,7 +145,7 @@ namespace AZ "Unable to deserialize char to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context); + return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonCharSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, @@ -151,7 +164,7 @@ namespace AZ "Unable to deserialize short to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context); + return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonShortSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, @@ -170,7 +183,7 @@ namespace AZ "Unable to deserialize int to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context); + return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonIntSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, @@ -189,7 +202,7 @@ namespace AZ "Unable to deserialize long to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context); + return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonLongSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, @@ -208,7 +221,7 @@ namespace AZ "Unable to deserialize long long to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context); + return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonLongLongSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, @@ -227,7 +240,8 @@ namespace AZ "Unable to deserialize unsigned char to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context); + return SerializerInternal::LoadInt( + reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonUnsignedCharSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, @@ -246,7 +260,8 @@ namespace AZ "Unable to deserialize unsigned short to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context); + return SerializerInternal::LoadInt( + reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonUnsignedShortSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, @@ -265,7 +280,8 @@ namespace AZ "Unable to deserialize unsigned int to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context); + return SerializerInternal::LoadInt( + reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonUnsignedIntSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, @@ -284,7 +300,8 @@ namespace AZ "Unable to deserialize unsigned long to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context); + return SerializerInternal::LoadInt( + reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonUnsignedLongSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, @@ -303,7 +320,8 @@ namespace AZ "Unable to deserialize unsigned long long to json because the provided type is %s", outputValueTypeId.ToString().c_str()); AZ_UNUSED(outputValueTypeId); - return SerializerInternal::LoadInt(reinterpret_cast(outputValue), inputValue, context); + return SerializerInternal::LoadInt( + reinterpret_cast(outputValue), inputValue, context, IsExplicitDefault(inputValue)); } JsonSerializationResult::Result JsonUnsignedLongLongSerializer::Store(rapidjson::Value& outputValue, const void* inputValue, diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.h index 9f522619ae..31d5a4164a 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/IntSerializer.h @@ -18,11 +18,18 @@ namespace AZ { - class JsonCharSerializer - : public BaseJsonSerializer + class BaseJsonIntegerSerializer : public BaseJsonSerializer { public: - AZ_RTTI(JsonCharSerializer, "{CA2A4AAC-3068-40B2-94F8-A537FBA8236E}", BaseJsonSerializer); + AZ_RTTI(BaseJsonIntegerSerializer, "{FD060F54-D3B5-4D5B-B64A-AFE371CD6F20}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + OperationFlags GetOperationsFlags() const override; + }; + + class JsonCharSerializer : public BaseJsonIntegerSerializer + { + public: + AZ_RTTI(JsonCharSerializer, "{CA2A4AAC-3068-40B2-94F8-A537FBA8236E}", BaseJsonIntegerSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -30,11 +37,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonShortSerializer - : public BaseJsonSerializer + class JsonShortSerializer : public BaseJsonIntegerSerializer { public: - AZ_RTTI(JsonShortSerializer, "{3D6789BD-231B-4E5D-B81D-609E71A2BCB5}", BaseJsonSerializer); + AZ_RTTI(JsonShortSerializer, "{3D6789BD-231B-4E5D-B81D-609E71A2BCB5}", BaseJsonIntegerSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -42,11 +48,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonIntSerializer - : public BaseJsonSerializer + class JsonIntSerializer : public BaseJsonIntegerSerializer { public: - AZ_RTTI(JsonIntSerializer, "{29E26946-0F1F-44B0-A098-1171B7B0C8FA}", BaseJsonSerializer); + AZ_RTTI(JsonIntSerializer, "{29E26946-0F1F-44B0-A098-1171B7B0C8FA}", BaseJsonIntegerSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -54,11 +59,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonLongSerializer - : public BaseJsonSerializer + class JsonLongSerializer : public BaseJsonIntegerSerializer { public: - AZ_RTTI(JsonLongSerializer, "{0EB432D0-A0C8-43B2-9D65-A73A4D6DFE3E}", BaseJsonSerializer); + AZ_RTTI(JsonLongSerializer, "{0EB432D0-A0C8-43B2-9D65-A73A4D6DFE3E}", BaseJsonIntegerSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -66,11 +70,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonLongLongSerializer - : public BaseJsonSerializer + class JsonLongLongSerializer : public BaseJsonIntegerSerializer { public: - AZ_RTTI(JsonLongLongSerializer, "{5E7967DE-A4DC-40E1-81A1-2896A054BB8A}", BaseJsonSerializer); + AZ_RTTI(JsonLongLongSerializer, "{5E7967DE-A4DC-40E1-81A1-2896A054BB8A}", BaseJsonIntegerSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -78,11 +81,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonUnsignedCharSerializer - : public BaseJsonSerializer + class JsonUnsignedCharSerializer : public BaseJsonIntegerSerializer { public: - AZ_RTTI(JsonUnsignedCharSerializer, "{1E6D606F-8490-4736-AAFF-91046FDEA2BB}", BaseJsonSerializer); + AZ_RTTI(JsonUnsignedCharSerializer, "{1E6D606F-8490-4736-AAFF-91046FDEA2BB}", BaseJsonIntegerSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -90,11 +92,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonUnsignedShortSerializer - : public BaseJsonSerializer + class JsonUnsignedShortSerializer : public BaseJsonIntegerSerializer { public: - AZ_RTTI(JsonUnsignedShortSerializer, "{3C92D2CC-CB13-4A40-B779-47562EE36451}", BaseJsonSerializer); + AZ_RTTI(JsonUnsignedShortSerializer, "{3C92D2CC-CB13-4A40-B779-47562EE36451}", BaseJsonIntegerSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -102,11 +103,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonUnsignedIntSerializer - : public BaseJsonSerializer + class JsonUnsignedIntSerializer : public BaseJsonIntegerSerializer { public: - AZ_RTTI(JsonUnsignedIntSerializer, "{70C0714A-690D-4F30-8986-ABC9DEFE9D62}", BaseJsonSerializer); + AZ_RTTI(JsonUnsignedIntSerializer, "{70C0714A-690D-4F30-8986-ABC9DEFE9D62}", BaseJsonIntegerSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -114,11 +114,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonUnsignedLongSerializer - : public BaseJsonSerializer + class JsonUnsignedLongSerializer : public BaseJsonIntegerSerializer { public: - AZ_RTTI(JsonUnsignedLongSerializer, "{28E5499F-6AF4-4778-AE14-66BA40B56247}", BaseJsonSerializer); + AZ_RTTI(JsonUnsignedLongSerializer, "{28E5499F-6AF4-4778-AE14-66BA40B56247}", BaseJsonIntegerSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; @@ -126,11 +125,10 @@ namespace AZ const Uuid& valueTypeId, JsonSerializerContext& context) override; }; - class JsonUnsignedLongLongSerializer - : public BaseJsonSerializer + class JsonUnsignedLongLongSerializer : public BaseJsonIntegerSerializer { public: - AZ_RTTI(JsonUnsignedLongLongSerializer, "{AB048BB3-C280-4166-9E2E-54CE2C3413CA}", BaseJsonSerializer); + AZ_RTTI(JsonUnsignedLongLongSerializer, "{AB048BB3-C280-4166-9E2E-54CE2C3413CA}", BaseJsonIntegerSerializer); AZ_CLASS_ALLOCATOR_DECL; JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp index 9c4641741e..a0a2ea6c37 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp @@ -19,25 +19,30 @@ #include #include #include +#include #include namespace AZ { JsonSerializationResult::ResultCode JsonDeserializer::DeserializerDefaultCheck(BaseJsonSerializer* serializer, void* object, - const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context) + const Uuid& typeId,const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context) { using namespace AZ::JsonSerializationResult; bool isExplicitDefault = IsExplicitDefault(value); bool manuallyDefaults = (serializer->GetOperationsFlags() & BaseJsonSerializer::OperationFlags::ManualDefault) == BaseJsonSerializer::OperationFlags::ManualDefault; - return !isExplicitDefault || (isExplicitDefault && manuallyDefaults) + bool initializeNewInstance = (serializer->GetOperationsFlags() & BaseJsonSerializer::OperationFlags::InitializeNewInstance) == + BaseJsonSerializer::OperationFlags::InitializeNewInstance; + + return + !isExplicitDefault || (isExplicitDefault && manuallyDefaults) || (isExplicitDefault && isNewInstance && initializeNewInstance) ? serializer->Load(object, typeId, value, context) : context.Report(Tasks::ReadField, Outcomes::DefaultsUsed, "Value has an explicit default."); } - JsonSerializationResult::ResultCode JsonDeserializer::Load(void* object, const Uuid& typeId, const rapidjson::Value& value, - JsonDeserializerContext& context) + JsonSerializationResult::ResultCode JsonDeserializer::Load( + void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context) { using namespace AZ::JsonSerializationResult; @@ -50,7 +55,7 @@ namespace AZ BaseJsonSerializer* serializer = context.GetRegistrationContext()->GetSerializerForType(typeId); if (serializer) { - return DeserializerDefaultCheck(serializer, object, typeId, value, context); + return DeserializerDefaultCheck(serializer, object, typeId, value, isNewInstance, context); } const SerializeContext::ClassData* classData = context.GetSerializeContext()->FindClassData(typeId); @@ -72,7 +77,7 @@ namespace AZ serializer = context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId()); if (serializer) { - return DeserializerDefaultCheck(serializer, object, typeId, value, context); + return DeserializerDefaultCheck(serializer, object, typeId, value, isNewInstance, context); } } @@ -133,7 +138,7 @@ namespace AZ const SerializeContext::ClassData* resolvedClassData = context.GetSerializeContext()->FindClassData(resolvedTypeId); if (resolvedClassData) { - status = JsonDeserializer::Load(*objectPtr, resolvedTypeId, value, context); + status = JsonDeserializer::Load(*objectPtr, resolvedTypeId, value, true, context); *objectPtr = resolvedClassData->m_azRtti->Cast(*objectPtr, typeId); @@ -174,7 +179,7 @@ namespace AZ } else { - return Load(object, classElement.m_typeId, value, context); + return Load(object, classElement.m_typeId, value, false, context); } } @@ -591,7 +596,9 @@ namespace AZ } else { - status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, "Serialization information for target type not found."); + using ReporterString = AZStd::fixed_string<1024>; + status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, + ReporterString::format("Serialization information for target type %s not found.", loadedTypeId.m_typeId.ToString().c_str())); return ResolvePointerResult::FullyProcessed; } objectType = loadedTypeId.m_typeId; diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h index 5954082ee0..1d16b49e39 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.h @@ -58,8 +58,8 @@ namespace AZ JsonDeserializer(const JsonDeserializer& rhs) = delete; JsonDeserializer(JsonDeserializer&& rhs) = delete; - static JsonSerializationResult::ResultCode Load(void* object, const Uuid& typeId, const rapidjson::Value& value, - JsonDeserializerContext& context); + static JsonSerializationResult::ResultCode Load( + void* object, const Uuid& typeId, const rapidjson::Value& value, bool isNewInstance, JsonDeserializerContext& context); static JsonSerializationResult::ResultCode LoadToPointer(void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context); @@ -120,6 +120,7 @@ namespace AZ void* object, const Uuid& typeId, const rapidjson::Value& value, + bool isNewInstance, JsonDeserializerContext& context); }; } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.cpp index de9aa70362..db1172d245 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonMerger.cpp @@ -607,10 +607,12 @@ namespace AZ } else if (source.Size() > target.Size()) { - rapidjson::SizeType sourceCount = source.Size(); - for (rapidjson::SizeType i = count; i < sourceCount; ++i) + // Loop backwards through the removals so that each removal has a valid index when processing in order. + for (rapidjson::SizeType i = source.Size(); i > count; --i) { - ScopedStackedString entryName(element, i); + // (We use "i - 1" here instead of in the loop to ensure we don't wrap around our unsigned numbers in the case + // where count is 0.) + ScopedStackedString entryName(element, i - 1); patch.PushBack(CreatePatchInternal_Remove(allocator, element), allocator); resultCode.Combine(settings.m_reporting("Removed member from array in JSON Patch.", ResultCode(Tasks::CreatePatch, Outcomes::Success), element)); diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp index 0629f1c32e..6fabf51237 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.cpp @@ -249,7 +249,7 @@ namespace AZ { StackedString path(StackedString::Format::JsonPointer); JsonDeserializerContext context(settings); - result = JsonDeserializer::Load(object, objectType, root, context); + result = JsonDeserializer::Load(object, objectType, root, false, context); } return result; } diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp index 437a648e1e..4dc3c44834 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp @@ -190,6 +190,12 @@ namespace AZ } size_t addedCount = container->Size(outputValue) - containerSize; + if (addedCount > 0) + { + // If at least one entry was added then the map is no longer in it's default state so + // mark is with success so the result can at best be partial defaults. + retVal.Combine(JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::Success)); + } AZStd::string_view message = addedCount >= maximumSize ? "Successfully read associative container." : addedCount == 0 ? "Unable to read data for the associative container." : @@ -215,10 +221,10 @@ namespace AZ // Load key void* keyAddress = pairContainer->GetElementByIndex(address, pairElement, 0); AZ_Assert(keyAddress, "Element reserved for associative container, but unable to retrieve address of the key."); - ContinuationFlags keyLoadFlags = ContinuationFlags::None; + ContinuationFlags keyLoadFlags = ContinuationFlags::LoadAsNewInstance; if (keyElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER) { - keyLoadFlags = ContinuationFlags::ResolvePointer; + keyLoadFlags |= ContinuationFlags::ResolvePointer; *reinterpret_cast(keyAddress) = nullptr; } JSR::ResultCode keyResult = ContinueLoading(keyAddress, keyElement->m_typeId, key, context, keyLoadFlags); @@ -231,10 +237,10 @@ namespace AZ // Load value void* valueAddress = pairContainer->GetElementByIndex(address, pairElement, 1); AZ_Assert(valueAddress, "Element reserved for associative container, but unable to retrieve address of the value."); - ContinuationFlags valueLoadFlags = ContinuationFlags::None; + ContinuationFlags valueLoadFlags = ContinuationFlags::LoadAsNewInstance; if (valueElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER) { - valueLoadFlags = ContinuationFlags::ResolvePointer; + valueLoadFlags |= ContinuationFlags::ResolvePointer; *reinterpret_cast(valueAddress) = nullptr; } JSR::ResultCode valueResult = ContinueLoading(valueAddress, valueElement->m_typeId, value, context, valueLoadFlags); diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.cpp index 5b43cec817..e8a6f549a7 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.cpp @@ -34,13 +34,24 @@ namespace AZ switch (inputValue.GetType()) { case rapidjson::kArrayType: - return LoadContainer(outputValue, outputValueTypeId, inputValue, context); + return LoadContainer(outputValue, outputValueTypeId, inputValue, false, context); - case rapidjson::kObjectType: // fall through - case rapidjson::kNullType: // fall through - case rapidjson::kStringType: // fall through - case rapidjson::kFalseType: // fall through - case rapidjson::kTrueType: // fall through + case rapidjson::kObjectType: + if (IsExplicitDefault(inputValue)) + { + // Because this serializer has only the operation flag "InitializeNewInstance" set, the only time this will be called with + // an explicit default is when a new instance has been created. + return LoadContainer(outputValue, outputValueTypeId, inputValue, true, context); + } + [[fallthrough]]; + case rapidjson::kNullType: + [[fallthrough]]; + case rapidjson::kStringType: + [[fallthrough]]; + case rapidjson::kFalseType: + [[fallthrough]]; + case rapidjson::kTrueType: + [[fallthrough]]; case rapidjson::kNumberType: return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, "Unsupported type. AZStd::pair or AZStd::tuple can only be read from an array."); @@ -127,8 +138,13 @@ namespace AZ } } + auto JsonTupleSerializer::GetOperationsFlags() const -> OperationFlags + { + return OperationFlags::InitializeNewInstance; + } + JsonSerializationResult::Result JsonTupleSerializer::LoadContainer(void* outputValue, const Uuid& outputValueTypeId, - const rapidjson::Value& inputValue, JsonDeserializerContext& context) + const rapidjson::Value& inputValue, bool isNewInstance, JsonDeserializerContext& context) { namespace JSR = JsonSerializationResult; // Used to remove name conflicts in AzCore in uber builds. @@ -154,13 +170,6 @@ namespace AZ }; container->EnumTypes(typeCountCallback); - rapidjson::SizeType arraySize = inputValue.Size(); - if (arraySize < typeCount) - { - return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, - "Not enough entries in array to load an AZStd::pair or AZStd::tuple from."); - } - AZStd::vector classElements; classElements.reserve(typeCount); auto typeEnumCallback = [&classElements](const Uuid&, const SerializeContext::ClassElement* genericClassElement) @@ -171,46 +180,80 @@ namespace AZ container->EnumTypes(typeEnumCallback); JSR::ResultCode retVal(JSR::Tasks::ReadField); - rapidjson::SizeType arrayIndex = 0; - size_t numElementsWritten = 0; - for (size_t i = 0; i < typeCount; ++i) + if (isNewInstance) { - ScopedContextPath subPath(context, i); - - void* elementAddress = container->GetElementByIndex(outputValue, nullptr, i); - AZ_Assert(elementAddress, "Address of AZStd::pair or AZStd::tuple element %zu could not be retrieved.", i); - - ContinuationFlags flags = classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER - ? ContinuationFlags::ResolvePointer - : ContinuationFlags::None; + rapidjson::Value explicitDefaultValue = GetExplicitDefault(); - while (arrayIndex < inputValue.Size()) + for (size_t i = 0; i < typeCount; ++i) { - JSR::ResultCode result = ContinueLoading(elementAddress, classElements[i]->m_typeId, inputValue[arrayIndex], context, flags); + ScopedContextPath subPath(context, i); + + void* elementAddress = container->GetElementByIndex(outputValue, nullptr, i); + AZ_Assert(elementAddress, "Address of AZStd::pair or AZStd::tuple element %zu could not be retrieved.", i); + + ContinuationFlags flags = ContinuationFlags::LoadAsNewInstance; + flags |= + (classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ? ContinuationFlags::ResolvePointer + : ContinuationFlags::None); + JSR::ResultCode result = ContinueLoading(elementAddress, classElements[i]->m_typeId, explicitDefaultValue, context, flags); retVal.Combine(result); - arrayIndex++; if (result.GetProcessing() == JSR::Processing::Halted) { return context.Report(retVal, "Failed to read element for AZStd::pair or AZStd::tuple."); } - else if (result.GetProcessing() != JSR::Processing::Altered) - { - numElementsWritten++; - break; - } } - } - if (numElementsWritten < typeCount) - { - AZStd::string_view message = numElementsWritten == 0 ? - "Unable to read data for AZStd::pair or AZStd::tuple." : - "Partially read data for AZStd::pair or AZStd::tuple."; - return context.Report(retVal, message); + return context.Report(retVal, "Initialized AZStd::pair or AZStd::tuple to defaults."); } else { - return context.Report(retVal, "Successfully read AZStd::pair or AZStd::tuple."); + if (inputValue.Size() < typeCount) + { + return context.Report( + JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, + "Not enough entries in array to load an AZStd::pair or AZStd::tuple from."); + } + + rapidjson::SizeType arrayIndex = 0; + size_t numElementsWritten = 0; + for (size_t i = 0; i < typeCount; ++i) + { + ScopedContextPath subPath(context, i); + + void* elementAddress = container->GetElementByIndex(outputValue, nullptr, i); + AZ_Assert(elementAddress, "Address of AZStd::pair or AZStd::tuple element %zu could not be retrieved.", i); + + ContinuationFlags flags = + (classElements[i]->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER ? ContinuationFlags::ResolvePointer + : ContinuationFlags::None); + while (arrayIndex < inputValue.Size()) + { + JSR::ResultCode result = + ContinueLoading(elementAddress, classElements[i]->m_typeId, inputValue[arrayIndex], context, flags); + retVal.Combine(result); + arrayIndex++; + if (result.GetProcessing() == JSR::Processing::Halted) + { + return context.Report(retVal, "Failed to read element for AZStd::pair or AZStd::tuple."); + } + else if (result.GetProcessing() != JSR::Processing::Altered) + { + numElementsWritten++; + break; + } + } + } + + if (numElementsWritten < typeCount) + { + AZStd::string_view message = numElementsWritten == 0 ? "Unable to read data for AZStd::pair or AZStd::tuple." + : "Partially read data for AZStd::pair or AZStd::tuple."; + return context.Report(retVal, message); + } + else + { + return context.Report(retVal, "Successfully read AZStd::pair or AZStd::tuple."); + } } } } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.h index a105272811..70a506eb81 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/TupleSerializer.h @@ -23,13 +23,20 @@ namespace AZ public: AZ_RTTI(JsonTupleSerializer, "{1AA0ADC1-395A-4223-8A73-304ACDEE7793}", BaseJsonSerializer); AZ_CLASS_ALLOCATOR_DECL; + JsonSerializationResult::Result Load(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, JsonDeserializerContext& context) override; JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override; + OperationFlags GetOperationsFlags() const override; + private: - JsonSerializationResult::Result LoadContainer(void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + JsonSerializationResult::Result LoadContainer( + void* outputValue, + const Uuid& outputValueTypeId, + const rapidjson::Value& inputValue, + bool isNewInstance, JsonDeserializerContext& context); }; } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp index 2d2acd9d44..172a3697e4 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp @@ -816,7 +816,11 @@ namespace AZ::SettingsRegistryMergeUtils } } - void MergeSettingsToRegistry_CommandLine(SettingsRegistryInterface& registry, const AZ::CommandLine& commandLine, bool executeCommands) + // This function intentionally copies `commandLine`. It looks like it only uses it as a const reference, but the + // code in the loop makes calls that mutates the `commandLine` instance, invalidating the iterators. Making a copy + // ensures that the iterators remain valid. + // NOLINTNEXTLINE(performance-unnecessary-value-param) + void MergeSettingsToRegistry_CommandLine(SettingsRegistryInterface& registry, AZ::CommandLine commandLine, bool executeCommands) { // Iterate over all the command line options in order to parse the --regset and --regremove // arguments in the order they were supplied @@ -831,7 +835,7 @@ namespace AZ::SettingsRegistryMergeUtils continue; } } - if (commandArgument.m_option == "regremove") + else if (commandArgument.m_option == "regremove") { if (!registry.Remove(commandArgument.m_value)) { diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h index b482530d24..dbeb1bfe24 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h @@ -15,11 +15,7 @@ #include #include #include - -namespace AZ -{ - class CommandLine; -} +#include namespace AZ::IO { @@ -217,7 +213,7 @@ namespace AZ::SettingsRegistryMergeUtils //! example: --regdump /My/Array/With/Objects //! --regdumpall Dumps the entire settings registry to output. //! Note that this function is only called in development builds and is compiled out in release builds. - void MergeSettingsToRegistry_CommandLine(SettingsRegistryInterface& registry, const AZ::CommandLine& commandLine, bool executeCommands); + void MergeSettingsToRegistry_CommandLine(SettingsRegistryInterface& registry, AZ::CommandLine commandLine, bool executeCommands); //! Stores the command line settings into the Setting Registry //! The arguments can be used later anywhere the command line is needed diff --git a/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp b/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp index 3e4ddac3af..47dba62ec8 100644 --- a/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp @@ -168,6 +168,10 @@ namespace JsonSerializationTests { features.EnableJsonType(rapidjson::kObjectType); features.m_typeToInject = rapidjson::kNullType; + // Assets are not fully registered with the Serialize Context for historical reasons. Due to the missing + // information the Json Serializer Conformity Tests can't run the subsection of tests that explicitly + // require the missing information. + features.m_enableNewInstanceTests = false; } bool AreEqual(const Asset& lhs, const Asset& rhs) override diff --git a/Code/Framework/AzCore/Tests/Name/NameJsonSerializerTests.cpp b/Code/Framework/AzCore/Tests/Name/NameJsonSerializerTests.cpp index 4fa816cd4d..cb26937824 100644 --- a/Code/Framework/AzCore/Tests/Name/NameJsonSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Name/NameJsonSerializerTests.cpp @@ -32,6 +32,11 @@ namespace JsonSerializationTests AZ::NameDictionary::Destroy(); } + void Reflect(AZStd::unique_ptr& context) + { + AZ::Name::Reflect(context.get()); + } + void Reflect(AZStd::unique_ptr& context) { AZ::Name::Reflect(context.get()); diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/ArraySerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/ArraySerializerTests.cpp index da66bdd0b5..f696a9d270 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/ArraySerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/ArraySerializerTests.cpp @@ -126,9 +126,9 @@ namespace JsonSerializationTests { auto array = AZStd::shared_ptr(new Array(), Deleter); (*array)[0] = nullptr; - (*array)[1] = aznew MultipleInheritence(); + (*array)[1] = nullptr; (*array)[2] = nullptr; - (*array)[3] = aznew MultipleInheritence(); + (*array)[3] = nullptr; return array; } @@ -154,6 +154,7 @@ namespace JsonSerializationTests null, null, { + "$type": "MultipleInheritence", "base_var": 242.0, "var1" : 142 } @@ -246,56 +247,21 @@ namespace JsonSerializationTests ])"; } - AZStd::string_view GetJsonFor_Store_SerializeFullySetInstance() override - { - // This is a unique situation because the $type is determined separate from other values, so all - // member values can be changed, but since the default type matches the stored type the $type - // will only be written if default values are explicitly kept. - return R"( - [ - { - "$type": "MultipleInheritence", - "base_var": 1142.0, - "base2_var1": 1242.0, - "base2_var2": 1342.0, - "base2_var3": 1442.0, - "var1" : 1542, - "var2" : 1642.0 - }, - { - "base_var": 2142.0, - "base2_var1": 2242.0, - "base2_var2": 2342.0, - "base2_var3": 2442.0, - "var1" : 2542, - "var2" : 2642.0 - }, - { - "$type": "MultipleInheritence", - "base_var": 3142.0, - "base2_var1": 3242.0, - "base2_var2": 3342.0, - "base2_var3": 3442.0, - "var1" : 3542, - "var2" : 3642.0 - }, - { - "base_var": 4142.0, - "base2_var1": 4242.0, - "base2_var2": 4342.0, - "base2_var3": 4442.0, - "var1" : 4542, - "var2" : 4642.0 - } - ])"; - } - void Reflect(AZStd::unique_ptr& context) override { Base::Reflect(context); MultipleInheritence::Reflect(context, true); } + void ConfigureFeatures(JsonSerializerConformityTestDescriptorFeatures& features) override + { + Base::ConfigureFeatures(features); + // These tests don't work with pointers because there'll be a random value in the pointer + // which the Json Serialization will try to delete. The POD version of these tests already cover + // these cases. + features.m_enableNewInstanceTests = false; + } + bool AreEqual(const Array& lhs, const Array& rhs) override { size_t size = lhs.size(); @@ -311,6 +277,11 @@ namespace JsonSerializationTests return rhs[i] == nullptr; } + if (rhs[i] == nullptr) + { + return false; + } + if (!static_cast(lhs[i])->Equals(*static_cast(rhs[i]), true)) { return false; diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/BasicContainerSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/BasicContainerSerializerTests.cpp index 88e888743e..508658e2a5 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/BasicContainerSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/BasicContainerSerializerTests.cpp @@ -54,6 +54,11 @@ namespace JsonSerializationTests return AZStd::make_shared(Container{ 188, 288, 388 }); } + AZStd::shared_ptr CreateSingleArrayDefaultInstance() override + { + return AZStd::make_shared(Container{ 0 }); + } + AZStd::string_view GetJsonForFullySetInstance() override { return "[188, 288, 388]"; @@ -120,6 +125,13 @@ namespace JsonSerializationTests &SimplePointerTestDescription::Delete); } + AZStd::shared_ptr CreateSingleArrayDefaultInstance() override + { + int* value = reinterpret_cast(azmalloc(sizeof(int), alignof(int))); + *value = 0; + return AZStd::shared_ptr(new Container{ value }, &SimplePointerTestDescription::Delete); + } + AZStd::string_view GetJsonForFullySetInstance() override { return "[188, 288, 388]"; @@ -180,6 +192,13 @@ namespace JsonSerializationTests return instance; } + AZStd::shared_ptr CreateSingleArrayDefaultInstance() override + { + auto instance = AZStd::make_shared(); + *instance = { SimpleClass{} }; + return instance; + } + AZStd::string_view GetJsonForFullySetInstance() override { return R"([ @@ -301,7 +320,7 @@ namespace JsonSerializationTests ResultCode result = m_serializer->Store(*m_jsonDocument, &instance, &instance, azrtti_typeid(&instance), *m_jsonSerializationContext); EXPECT_EQ(Processing::Completed, result.GetProcessing()); - EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome()); + EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome()); Expect_DocStrEq("[{}]"); } @@ -315,7 +334,7 @@ namespace JsonSerializationTests ResultCode result = m_serializer->Store(*m_jsonDocument, &instance, nullptr, azrtti_typeid(&instance), *m_jsonSerializationContext); EXPECT_EQ(Processing::Completed, result.GetProcessing()); - EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome()); + EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome()); Expect_DocStrEq("[{},{}]"); } @@ -330,7 +349,6 @@ namespace JsonSerializationTests ResultCode result = m_serializer->Store(*m_jsonDocument, &instance, nullptr, azrtti_typeid(&instance), *m_jsonSerializationContext); EXPECT_EQ(Processing::Completed, result.GetProcessing()); EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome()); - EXPECT_NE(Outcomes::DefaultsUsed, result.GetOutcome()); Expect_DocStrEq(R"([{"$type": "SimpleInheritence"},{"$type": "SimpleInheritence"}])"); } diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/BoolSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/BoolSerializerTests.cpp index cf9d76e79d..cd6fcef5c5 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/BoolSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/BoolSerializerTests.cpp @@ -63,6 +63,18 @@ namespace JsonSerializationTests : public BaseJsonSerializerFixture { public: + struct BoolPointerWrapper + { + AZ_TYPE_INFO(BoolPointerWrapper, "{2E67C069-BB0F-4F00-A704-E964F5FE5ED2}"); + + bool* m_value{ nullptr }; + + ~BoolPointerWrapper() + { + azfree(m_value); + } + }; + void SetUp() override { BaseJsonSerializerFixture::SetUp(); @@ -75,6 +87,12 @@ namespace JsonSerializationTests BaseJsonSerializerFixture::TearDown(); } + void RegisterAdditional(AZStd::unique_ptr& serializeContext) override + { + serializeContext->Class() + ->Field("Value", &BoolPointerWrapper::m_value); + } + void Load(rapidjson::Value& testVal, bool expectedBool, AZ::JsonSerializationResult::Outcomes expectedOutcome) { using namespace AZ::JsonSerializationResult; diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/DoubleSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/DoubleSerializerTests.cpp index d19c38fcdc..1556318199 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/DoubleSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/DoubleSerializerTests.cpp @@ -32,7 +32,7 @@ namespace JsonSerializationTests AZStd::shared_ptr CreateDefaultInstance() override { - return AZStd::make_shared(-2.0f); + return AZStd::make_shared(0.0f); } AZStd::shared_ptr CreateFullySetInstance() override @@ -71,6 +71,20 @@ namespace JsonSerializationTests : public BaseJsonSerializerFixture { public: + struct DoublePointerWrapper + { + AZ_TYPE_INFO(DoublePointerWrapper, "{C2FD9E0B-2641-4D24-A3D9-A29FD1A21A81}"); + + double* m_double{ nullptr }; + float* m_float{ nullptr }; + + ~DoublePointerWrapper() + { + azfree(m_float); + azfree(m_double); + } + }; + void SetUp() override { BaseJsonSerializerFixture::SetUp(); @@ -85,6 +99,13 @@ namespace JsonSerializationTests BaseJsonSerializerFixture::TearDown(); } + void RegisterAdditional(AZStd::unique_ptr& serializeContext) override + { + serializeContext->Class() + ->Field("Double", &DoublePointerWrapper::m_double) + ->Field("Float", &DoublePointerWrapper::m_float); + } + void TestSerializers(rapidjson::Value& testVal, double expectedValue, AZ::JsonSerializationResult::Outcomes expectedOutcome) { using namespace AZ::JsonSerializationResult; diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializerConformityTests.h b/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializerConformityTests.h index c0f470378c..4931c203cf 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializerConformityTests.h +++ b/Code/Framework/AzCore/Tests/Serialization/Json/JsonSerializerConformityTests.h @@ -62,6 +62,14 @@ namespace JsonSerializationTests //! can be used to manually create these documents. If that is also not an option the tests can be //! disabled by setting this flag to false. bool m_supportsInjection{ true }; + //! Enables the check that tries to determine if variables are initialized and if not whether they have the + //! OperationFlags::ManualDefault set. This applies for instance to integers, which won't be initialized if + //! constructed a new instance is created for pointers. + bool m_enableInitializationTest{ true }; + //! Enable the test that creates a new instance of the provided test type through the factory that's found in + //! the Serialize Context. This test is automatically disabled for classes that don't have a factory or + //! have a null factory as well as for classes that have mandatory fields. + bool m_enableNewInstanceTests{ true }; private: // There's no way to retrieve the number of types from RapidJSON so they're hard-coded here. @@ -87,6 +95,7 @@ namespace JsonSerializationTests { public: using Type = T; + virtual ~JsonSerializerConformityTestDescriptor() = default; virtual AZStd::shared_ptr CreateSerializer() = 0; @@ -104,13 +113,21 @@ namespace JsonSerializationTests virtual AZStd::shared_ptr CreatePartialDefaultInstance() { return nullptr; } //! Create an instance where all values are set to non-default values. virtual AZStd::shared_ptr CreateFullySetInstance() = 0; + //! Create an instance of the target array type with a single value that has all defaults. + //! If the target type doesn't support arrays or requires more than one entry this can be ignored and + //! tests using this value will be skipped. + virtual AZStd::shared_ptr CreateSingleArrayDefaultInstance() { return nullptr; } //! Get the json that represents the default instance. //! If the target type doesn't support partial specialization this can be ignored and //! tests for partial support will be skipped. - virtual AZStd::string_view GetJsonForPartialDefaultInstance() { return ""; } + virtual AZStd::string_view GetJsonForPartialDefaultInstance() { return ""; } //! Get the json that represents the instance with all values set. virtual AZStd::string_view GetJsonForFullySetInstance() = 0; + //! Get the json that represents an array with a single value that has only defaults. + //! If the target type doesn't support arrays or requires more than one entry this can be ignored and + //! tests using this value will be skipped. + virtual AZStd::string_view GetJsonForSingleArrayDefaultInstance() { return "[{}]"; } //! Get the json where additional values are added to the json file. //! If this function is not overloaded, but features.m_supportsInjection is enabled then //! the Json Serializer Conformity Tests will inject extra values in the json for a fully. @@ -138,12 +155,15 @@ namespace JsonSerializationTests virtual AZStd::string_view GetJsonFor_Load_DeserializeUnreflectedType() { return this->GetJsonForFullySetInstance(); } virtual AZStd::string_view GetJsonFor_Load_DeserializeFullySetInstance() { return this->GetJsonForFullySetInstance(); } virtual AZStd::string_view GetJsonFor_Load_DeserializePartialInstance() { return this->GetJsonForPartialDefaultInstance(); } + virtual AZStd::string_view GetJsonFor_Load_DeserializeArrayWithDefaultValue() { return this->GetJsonForSingleArrayDefaultInstance(); } + virtual AZStd::string_view GetJsonFor_Load_DeserializeFullInstanceOnTopOfPartialDefaulted() { return this->GetJsonForFullySetInstance(); } virtual AZStd::string_view GetJsonFor_Load_HaltedThroughCallback() { return this->GetJsonForFullySetInstance(); } virtual AZStd::string_view GetJsonFor_Store_SerializeWithDefaultsKept() { return this->GetJsonForFullySetInstance(); } virtual AZStd::string_view GetJsonFor_Store_SerializeFullySetInstance() { return this->GetJsonForFullySetInstance(); } virtual AZStd::string_view GetJsonFor_Store_SerializeWithoutDefault() { return this->GetJsonForFullySetInstance(); } virtual AZStd::string_view GetJsonFor_Store_SerializeWithoutDefaultAndDefaultsKept() { return this->GetJsonForFullySetInstance(); } virtual AZStd::string_view GetJsonFor_Store_SerializePartialInstance() { return this->GetJsonForPartialDefaultInstance(); } + virtual AZStd::string_view GetJsonFor_Store_SerializeArrayWithSingleDefaultValue() { return this->GetJsonForSingleArrayDefaultInstance(); } }; template @@ -154,6 +174,21 @@ namespace JsonSerializationTests using Description = T; using Type = typename T::Type; + struct PointerWrapper + { + AZ_TYPE_INFO(PointerWrapper, "{32FA6645-074A-458A-B79C-B173D0BD4B42}"); + AZ_CLASS_ALLOCATOR(PointerWrapper, AZ::SystemAllocator, 0); + + Type* m_value{ nullptr }; + + ~PointerWrapper() + { + // Using free because not all types can safely use delete. Since this just to clear the memory to satisfy the memory + // leak test, this is fine. + azfree(m_value); + } + }; + void SetUp() override { using namespace AZ::JsonSerializationResult; @@ -165,6 +200,7 @@ namespace JsonSerializationTests descriptor->ConfigureFeatures(this->m_features); descriptor->Reflect(this->m_serializeContext); descriptor->Reflect(this->m_jsonRegistrationContext); + this->m_serializeContext->template Class()->Field("Value", &PointerWrapper::m_value); this->m_deserializationSettings->m_reporting = &Internal::VerifyCallback; this->m_serializationSettings->m_reporting = &Internal::VerifyCallback; @@ -185,6 +221,7 @@ namespace JsonSerializationTests this->m_jsonRegistrationContext->DisableRemoveReflection(); this->m_serializeContext->EnableRemoveReflection(); + this->m_serializeContext->template Class()->Field("Value", &PointerWrapper::m_value); descriptor->Reflect(this->m_serializeContext); this->m_serializeContext->DisableRemoveReflection(); @@ -487,6 +524,41 @@ namespace JsonSerializationTests } } + TYPED_TEST_P(JsonSerializerConformityTests, Load_DeserializeArrayWithDefaultValue_SucceedsAndReportPartialDefaults) + { + using namespace AZ::JsonSerializationResult; + + if (this->m_features.SupportsJsonType(rapidjson::kArrayType)) + { + this->m_jsonDocument->Parse(this->m_description.GetJsonFor_Load_DeserializeArrayWithDefaultValue().data()); + ASSERT_FALSE(this->m_jsonDocument->HasParseError()); + + auto serializer = this->m_description.CreateSerializer(); + auto instance = this->m_description.CreateDefaultInstance(); + + this->m_jsonDeserializationContext->PushPath(DefaultPath); + + ResultCode result = + serializer->Load(instance.get(), azrtti_typeid(*instance), *this->m_jsonDocument, *this->m_jsonDeserializationContext); + + if (this->m_features.m_fixedSizeArray) + { + EXPECT_EQ(Outcomes::Unsupported, result.GetOutcome()); + EXPECT_EQ(Processing::Altered, result.GetProcessing()); + } + else + { + EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome()); + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + + auto compare = this->m_description.CreateSingleArrayDefaultInstance(); + ASSERT_NE(nullptr, compare) + << "Conformity tests for variably sized arrays require an implementation of CreateSingleArrayDefaultInstance"; + EXPECT_TRUE(this->m_description.AreEqual(*compare, *instance)); + } + } + } + TYPED_TEST_P(JsonSerializerConformityTests, Load_InterruptClearingTarget_ContainerIsNotCleared) { using namespace AZ::JsonSerializationResult; @@ -548,7 +620,6 @@ namespace JsonSerializationTests this->m_jsonDocument->Parse(json.data()); ASSERT_FALSE(this->m_jsonDocument->HasParseError()); - auto serializer = this->m_description.CreateSerializer(); auto instance = this->m_description.CreateDefaultConstructedInstance(); auto compare = this->m_description.CreateFullySetInstance(); @@ -622,6 +693,94 @@ namespace JsonSerializationTests } } + TYPED_TEST_P(JsonSerializerConformityTests, Load_DeserializeFullInstanceOnTopOfPartialDefaulted_SucceedsAndObjectMatchesParialInstance) + { + using namespace AZ::JsonSerializationResult; + + if (this->m_features.m_supportsPartialInitialization) + { + AZStd::string_view json = this->m_description.GetJsonFor_Load_DeserializeFullInstanceOnTopOfPartialDefaulted(); + // If tests for partial initialization are enabled than json for the partial initialization is needed. + ASSERT_FALSE(json.empty()); + this->m_jsonDocument->Parse(json.data()); + ASSERT_FALSE(this->m_jsonDocument->HasParseError()); + + auto serializer = this->m_description.CreateSerializer(); + auto instance = this->m_description.CreatePartialDefaultInstance(); + auto compare = this->m_description.CreateFullySetInstance(); + ASSERT_NE(nullptr, compare); + + // Clear containers which should effectively turn them into default containers. + this->m_deserializationSettings->m_clearContainers = true; + this->ResetJsonContexts(); + this->m_jsonDeserializationContext->PushPath(DefaultPath); + + ResultCode result = + serializer->Load(instance.get(), azrtti_typeid(*instance), *this->m_jsonDocument, *this->m_jsonDeserializationContext); + + EXPECT_EQ(Outcomes::Success, result.GetOutcome()); + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + EXPECT_TRUE(this->m_description.AreEqual(*instance, *compare)); + } + } + + TYPED_TEST_P(JsonSerializerConformityTests, Load_DefaultToPointer_SucceedsAndValueIsInitialized) + { + using namespace AZ::JsonSerializationResult; + + if (this->m_features.m_enableNewInstanceTests && this->m_features.m_mandatoryFields.empty()) + { + AZ::SerializeContext* serializeContext = this->m_jsonDeserializationContext->GetSerializeContext(); + const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(azrtti_typeid()); + ASSERT_NE(nullptr, classData); + // Skip this test if the target type doesn't have a factor to create a new instance with or if the factor explicit + // prohibits construction. + if (classData->m_factory && classData->m_factory != AZ::Internal::NullFactory::GetInstance()) + { + typename JsonSerializerConformityTests::PointerWrapper instance; + auto compare = this->m_description.CreateDefaultInstance(); + + this->m_jsonDocument->Parse(R"({ "Value": {}})"); + ASSERT_FALSE(this->m_jsonDocument->HasParseError()); + + AZ::JsonDeserializerSettings settings; + settings.m_serializeContext = serializeContext; + settings.m_registrationContext = this->m_jsonDeserializationContext->GetRegistrationContext(); + ResultCode result = AZ::JsonSerialization::Load(instance, *this->m_jsonDocument, settings); + + EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome()); + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + ASSERT_NE(nullptr, instance.m_value); + EXPECT_TRUE(this->m_description.AreEqual(*instance.m_value, *compare)); + } + } + } + + TYPED_TEST_P(JsonSerializerConformityTests, Load_InitializeNewInstance_SucceedsAndValueIsInitialized) + { + using namespace AZ; + using namespace AZ::JsonSerializationResult; + + if (this->m_features.m_enableNewInstanceTests && this->m_features.m_mandatoryFields.empty()) + { + auto serializer = this->m_description.CreateSerializer(); + if ((serializer->GetOperationsFlags() & BaseJsonSerializer::OperationFlags::InitializeNewInstance) == + BaseJsonSerializer::OperationFlags::InitializeNewInstance) + { + typename TypeParam::Type instance; + auto compare = this->m_description.CreateDefaultInstance(); + this->m_jsonDocument->SetObject(); + + ResultCode result = + serializer->Load(&instance, azrtti_typeid(instance), *this->m_jsonDocument, *this->m_jsonDeserializationContext); + + EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome()); + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + EXPECT_TRUE(this->m_description.AreEqual(instance, *compare)); + } + } + } + TYPED_TEST_P(JsonSerializerConformityTests, Load_HaltedThroughCallback_LoadFailsAndHaltReported) { using namespace AZ::JsonSerializationResult; @@ -909,6 +1068,28 @@ namespace JsonSerializationTests } } + TYPED_TEST_P(JsonSerializerConformityTests, Store_SerializeArrayWithSingleDefaultValue_StoredSuccessfullyAndJsonMatches) + { + using namespace AZ::JsonSerializationResult; + + if (this->m_features.SupportsJsonType(rapidjson::kArrayType) && !this->m_features.m_fixedSizeArray) + { + this->m_jsonSerializationContext->PushPath(DefaultPath); + + auto serializer = this->m_description.CreateSerializer(); + auto instance = this->m_description.CreateSingleArrayDefaultInstance(); + ASSERT_NE(nullptr, instance) + << "Conformity tests for variably sized arrays require an implementation of CreateSingleArrayDefaultInstance"; + + ResultCode result = serializer->Store( + *this->m_jsonDocument, instance.get(), instance.get(), azrtti_typeid(*instance), *this->m_jsonSerializationContext); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome()); + this->Expect_DocStrEq(this->m_description.GetJsonFor_Store_SerializeArrayWithSingleDefaultValue()); + } + } + TYPED_TEST_P(JsonSerializerConformityTests, Store_HaltedThroughCallback_StoreFailsAndHaltReported) { using namespace AZ::JsonSerializationResult; @@ -1017,7 +1198,29 @@ namespace JsonSerializationTests } } - TYPED_TEST_P(JsonSerializerConformityTests, GetOperationsFlags_ManualDefaultSetIfNeeded_ManualDefaultOperationSetIfMandatoryFieldsAreDeclared) + TYPED_TEST_P(JsonSerializerConformityTests, GetOperationFlags_RequiresExplicitInit_ObjectsThatDoNotConstructHaveExplicitInitOption) + { + using namespace AZ; + using namespace AZ::JsonSerializationResult; + + if (this->m_features.m_enableInitializationTest) + { + auto instance = this->m_description.CreateDefaultInstance(); + typename TypeParam::Type compare; + if (!this->m_description.AreEqual(*instance, compare)) + { + auto serializer = this->m_description.CreateSerializer(); + BaseJsonSerializer::OperationFlags flags = serializer->GetOperationsFlags(); + bool hasManualDefaultSet = + (flags & BaseJsonSerializer::OperationFlags::ManualDefault) == BaseJsonSerializer::OperationFlags::ManualDefault || + (flags & BaseJsonSerializer::OperationFlags::InitializeNewInstance) == + BaseJsonSerializer::OperationFlags::InitializeNewInstance; + EXPECT_TRUE(hasManualDefaultSet); + } + } + } + + TYPED_TEST_P(JsonSerializerConformityTests, GetOperationFlags_ManualDefaultSetIfNeeded_ManualDefaultOperationSetIfMandatoryFieldsAreDeclared) { if (this->m_features.SupportsJsonType(rapidjson::kObjectType)) { @@ -1048,10 +1251,14 @@ namespace JsonSerializationTests Load_DeserializeEmptyArray_SucceedsAndObjectMatchesDefaults, Load_DeserializeEmptyArrayWithClearEnabled_SucceedsAndObjectMatchesDefaults, Load_DeserializeEmptyArrayWithClearedTarget_SucceedsAndObjectMatchesDefaults, + Load_DeserializeArrayWithDefaultValue_SucceedsAndReportPartialDefaults, Load_InterruptClearingTarget_ContainerIsNotCleared, Load_DeserializeFullySetInstance_SucceedsAndObjectMatchesFullySetInstance, Load_DeserializeFullySetInstanceThroughMainLoad_SucceedsAndObjectMatchesFullySetInstance, Load_DeserializePartialInstance_SucceedsAndObjectMatchesParialInstance, + Load_DeserializeFullInstanceOnTopOfPartialDefaulted_SucceedsAndObjectMatchesParialInstance, + Load_DefaultToPointer_SucceedsAndValueIsInitialized, + Load_InitializeNewInstance_SucceedsAndValueIsInitialized, Load_DeserializeWithMissingMandatoryField_LoadFailedAndUnsupportedReported, Load_InsertAdditionalData_SucceedsAndObjectMatchesFullySetInstance, Load_HaltedThroughCallback_LoadFailsAndHaltReported, @@ -1066,13 +1273,15 @@ namespace JsonSerializationTests Store_SerializeWithoutDefaultAndDefaultsKept_StoredSuccessfullyAndJsonMatches, Store_SerializePartialInstance_StoredSuccessfullyAndJsonMatches, Store_SerializeEmptyArray_StoredSuccessfullyAndJsonMatches, + Store_SerializeArrayWithSingleDefaultValue_StoredSuccessfullyAndJsonMatches, Store_HaltedThroughCallback_StoreFailsAndHaltReported, StoreLoad_RoundTripWithPartialDefault_IdenticalInstances, StoreLoad_RoundTripWithFullSet_IdenticalInstances, StoreLoad_RoundTripWithDefaultsKept_IdenticalInstances, - GetOperationsFlags_ManualDefaultSetIfNeeded_ManualDefaultOperationSetIfMandatoryFieldsAreDeclared); + GetOperationFlags_RequiresExplicitInit_ObjectsThatDoNotConstructHaveExplicitInitOption, + GetOperationFlags_ManualDefaultSetIfNeeded_ManualDefaultOperationSetIfMandatoryFieldsAreDeclared); } // namespace JsonSerializationTests namespace AZ diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp index 5dec394351..7ec5ca3b9a 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp @@ -35,6 +35,11 @@ namespace JsonSerializationTests return AZStd::make_shared(); } + AZStd::string_view GetJsonForSingleArrayDefaultInstance() override + { + return R"({ "{}": {} })"; + } + void ConfigureFeatures(JsonSerializerConformityTestDescriptorFeatures& features) override { features.EnableJsonType(rapidjson::kArrayType); @@ -61,6 +66,13 @@ namespace JsonSerializationTests public: using Map = T; + AZStd::shared_ptr CreateSingleArrayDefaultInstance() override + { + auto instance = AZStd::make_shared(); + instance->emplace(AZStd::make_pair(0, 0.0)); + return instance; + } + AZStd::shared_ptr CreateFullySetInstance() override { auto instance = AZStd::make_shared(); @@ -100,6 +112,13 @@ namespace JsonSerializationTests public: using Map = T; + AZStd::shared_ptr CreateSingleArrayDefaultInstance() override + { + auto instance = AZStd::make_shared(); + instance->emplace(AZStd::make_pair(AZStd::string(), 0.0)); + return instance; + } + AZStd::shared_ptr CreateFullySetInstance() override { auto instance = AZStd::make_shared(); @@ -163,6 +182,14 @@ namespace JsonSerializationTests return instance; } + AZStd::shared_ptr CreateSingleArrayDefaultInstance() override + { + auto instance = AZStd::shared_ptr(new Map{}, &Delete); + instance->emplace(AZStd::make_pair(aznew SimpleClass(), aznew SimpleClass())); + return instance; + } + + AZStd::string_view GetJsonForPartialDefaultInstance() override { if constexpr (IsMultiMap) @@ -237,13 +264,23 @@ namespace JsonSerializationTests return false; } - auto compare = [](typename Map::const_reference lhs, typename Map::const_reference rhs) -> bool + // Naive compare to avoid having to split up the test because comparing for ordered and unordered maps would need to be + // different. + for (auto&& [key, value] : lhs) { - return - lhs.first->Equals(*rhs.first, true) && - lhs.second->Equals(*rhs.second, true); - }; - return AZStd::equal(lhs.begin(), lhs.end(), rhs.begin(), compare); + for (auto&& [keyCompare, valueCompare] : rhs) + { + if (key->Equals(*keyCompare, true)) + { + if (!value->Equals(*valueCompare, true)) + { + return false; + } + break; + } + } + } + return true; } }; @@ -393,6 +430,29 @@ namespace JsonSerializationTests { using namespace AZ::JsonSerializationResult; + m_jsonDocument->Parse(R"( + { + "{}": {} + })"); + ASSERT_FALSE(m_jsonDocument->HasParseError()); + + TestStringMap values; + ResultCode result = m_unorderedMapSerializer.Load(&values, azrtti_typeid(&values), *m_jsonDocument, *m_jsonDeserializationContext); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome()); + + EXPECT_EQ(1, values.size()); + + auto defaultKey = values.find(TestString()); + EXPECT_NE(values.end(), defaultKey); + EXPECT_STRCASEEQ(TestString().m_value.c_str(), defaultKey->second.m_value.c_str()); + } + + TEST_F(JsonMapSerializerTests, Load_DefaultForStringKeyAndAdditionalValue_LoadedBackWithDefaults) + { + using namespace AZ::JsonSerializationResult; + m_jsonDocument->Parse(R"( { "{}": {}, @@ -563,13 +623,13 @@ namespace JsonSerializationTests EXPECT_EQ(Outcomes::Catastrophic, result.GetOutcome()); } - TEST_F(JsonMapSerializerTests, Load_DefaultValueInMultiMap_DefaultUsed) + TEST_F(JsonMapSerializerTests, Load_DefaultObjectInMultiMap_DefaultUsed) { using namespace AZ::JsonSerializationResult; m_jsonDocument->Parse(R"( { - "Hello": {} + "World": {} })"); ASSERT_FALSE(m_jsonDocument->HasParseError()); @@ -580,18 +640,41 @@ namespace JsonSerializationTests EXPECT_EQ(Processing::Completed, result.GetProcessing()); EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome()); + ASSERT_FALSE(values.empty()); + EXPECT_STREQ("World", values.begin()->first.m_value.c_str()); + EXPECT_STREQ(TestString().m_value.c_str(), values.begin()->second.m_value.c_str()); + } + + TEST_F(JsonMapSerializerTests, Load_FullDefaultObjectInMultiMap_DefaultUsed) + { + using namespace AZ::JsonSerializationResult; + + m_jsonDocument->Parse(R"( + { + "{}": {} + })"); + ASSERT_FALSE(m_jsonDocument->HasParseError()); + + TestStringMultiMap values; + ResultCode result = + m_unorderedMultiMapSerializer.Load(&values, azrtti_typeid(&values), *m_jsonDocument, *m_jsonDeserializationContext); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome()); + ASSERT_FALSE(values.empty()); EXPECT_STREQ("Hello", values.begin()->first.m_value.c_str()); + EXPECT_STREQ("Hello", values.begin()->second.m_value.c_str()); EXPECT_STREQ(TestString().m_value.c_str(), values.begin()->second.m_value.c_str()); } - TEST_F(JsonMapSerializerTests, Load_DefaultArrayValueInMultiMap_DefaultUsed) + TEST_F(JsonMapSerializerTests, Load_DefaultObjectValueInMultiMap_DefaultUsed) { using namespace AZ::JsonSerializationResult; m_jsonDocument->Parse(R"( { - "Hello": [{}] + "World": [{}] })"); ASSERT_FALSE(m_jsonDocument->HasParseError()); @@ -603,7 +686,8 @@ namespace JsonSerializationTests EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome()); ASSERT_FALSE(values.empty()); - EXPECT_STREQ("Hello", values.begin()->first.m_value.c_str()); + EXPECT_STREQ("World", values.begin()->first.m_value.c_str()); + EXPECT_STREQ("Hello", values.begin()->second.m_value.c_str()); EXPECT_STREQ(TestString().m_value.c_str(), values.begin()->second.m_value.c_str()); } @@ -636,7 +720,7 @@ namespace JsonSerializationTests azrtti_typeid(&values), *m_jsonSerializationContext); EXPECT_EQ(Processing::Completed, result.GetProcessing()); - EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome()); + EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome()); Expect_DocStrEq(R"( { "{}": {} @@ -654,7 +738,25 @@ namespace JsonSerializationTests azrtti_typeid(&values), *m_jsonSerializationContext); EXPECT_EQ(Processing::Completed, result.GetProcessing()); - EXPECT_EQ(Outcomes::DefaultsUsed, result.GetOutcome()); + EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome()); + Expect_DocStrEq(R"( + { + "{}": {} + })"); + } + + TEST_F(JsonMapSerializerTests, Store_SingleAllDefaulValue_InitializedWithDefaults) + { + using namespace AZ::JsonSerializationResult; + + SimpleClassMap values; + values.emplace(SimpleClass(), SimpleClass()); + + ResultCode result = + m_unorderedMapSerializer.Store(*m_jsonDocument, &values, nullptr, azrtti_typeid(&values), *m_jsonSerializationContext); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + EXPECT_EQ(Outcomes::PartialDefaults, result.GetOutcome()); Expect_DocStrEq(R"( { "{}": {} diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_Patching.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_Patching.cpp index 0906eb45f8..1f6c6142e8 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_Patching.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_Patching.cpp @@ -303,6 +303,29 @@ namespace JsonSerializationTests R"( { "foo": [ "bar", "baz" ] })"); } + TEST_F(JsonPatchingSerializationTests, ApplyPatch_UseJsonPatchRemoveArrayMembersInCorrectOrder_ReportsSuccess) + { + CheckApplyPatch( + R"( { "foo": [ "bar", "qux", "baz" ] })", + R"( [ + { "op": "remove", "path": "/foo/2" }, + { "op": "remove", "path": "/foo/1" } + ])", + R"( { "foo": [ "bar" ] })"); + } + + TEST_F(JsonPatchingSerializationTests, ApplyPatch_UseJsonPatchRemoveArrayMembersInWrongOrder_ReportsError) + { + using namespace AZ::JsonSerializationResult; + CheckApplyPatchOutcome( + R"( { "foo": [ "bar", "qux", "baz" ] })", + R"( [ + { "op": "remove", "path": "/foo/1" }, + { "op": "remove", "path": "/foo/2" } + ])", + Outcomes::Invalid, Processing::Halted); + } + TEST_F(JsonPatchingSerializationTests, ApplyPatch_UseJsonPatchRemoveOperationInvalidParent_ReportError) { using namespace AZ::JsonSerializationResult; @@ -949,6 +972,27 @@ namespace JsonSerializationTests ); } + TEST_F(JsonPatchingSerializationTests, CreatePatch_UseJsonPatchRemoveLastArrayEntries_MultipleOperationsInCorrectOrder) + { + CheckCreatePatch( + R"( [ "foo", "hello", "bar" ])", R"( [ "foo" ])", + R"( [ + { "op": "remove", "path": "/2" }, + { "op": "remove", "path": "/1" } + ])"); + } + + TEST_F(JsonPatchingSerializationTests, CreatePatch_UseJsonPatchRemoveAllArrayEntries_MultipleOperationsInCorrectOrder) + { + CheckCreatePatch( + R"( [ "foo", "hello", "bar" ])", R"( [])", + R"( [ + { "op": "remove", "path": "/2" }, + { "op": "remove", "path": "/1" }, + { "op": "remove", "path": "/0" } + ])"); + } + TEST_F(JsonPatchingSerializationTests, CreatePatch_UseJsonPatchRemoveObjectFromArrayInMiddle_OperationToUpdateMember) { CheckCreatePatch( diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/TupleSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/TupleSerializerTests.cpp index eceaaae5f1..77a88fda6c 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/TupleSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/TupleSerializerTests.cpp @@ -48,12 +48,12 @@ namespace JsonSerializationTests AZStd::shared_ptr CreateDefaultInstance() override { - return AZStd::make_shared(142, 242.0); + return AZStd::make_shared(0, 0.0); } AZStd::shared_ptr CreatePartialDefaultInstance() override { - return AZStd::make_shared(142, 288.0); + return AZStd::make_shared(0, 288.0); } AZStd::shared_ptr CreateFullySetInstance() override @@ -102,12 +102,12 @@ namespace JsonSerializationTests AZStd::shared_ptr CreateDefaultInstance() override { - return AZStd::make_shared(142, 242.0, 342.0f); + return AZStd::make_shared(0, 0.0, 0.0f); } AZStd::shared_ptr CreatePartialDefaultInstance() override { - return AZStd::make_shared(142, 288.0, 342.0f); + return AZStd::make_shared(0, 288.0, 0.0f); } AZStd::shared_ptr CreateFullySetInstance() override @@ -345,6 +345,7 @@ namespace JsonSerializationTests { TupleSerializerTestsInternal::ConfigureFeatures(features); features.m_supportsPartialInitialization = true; + features.m_enableNewInstanceTests = false; } void Reflect(AZStd::unique_ptr& context) override @@ -447,14 +448,14 @@ namespace JsonSerializationTests { return AZStd::make_shared( AZStd::vector(), - AZStd::make_pair(442, "")); + AZStd::make_pair(0, "")); } AZStd::shared_ptr CreatePartialDefaultInstance() override { return AZStd::make_shared( AZStd::vector(), - AZStd::make_pair(442, "hello")); + AZStd::make_pair(0, "hello")); } AZStd::shared_ptr CreateFullySetInstance() override diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/UnorderedSetSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/UnorderedSetSerializerTests.cpp index 6e9cd0f3d6..fb7b683d2e 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/UnorderedSetSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/UnorderedSetSerializerTests.cpp @@ -36,6 +36,11 @@ namespace JsonSerializationTests return AZStd::make_shared(); } + AZStd::shared_ptr CreateSingleArrayDefaultInstance() override + { + return AZStd::make_shared(Set{ 0 }); + } + AZStd::shared_ptr CreateFullySetInstance() override { return AZStd::make_shared(Set{42, -88, 342}); @@ -80,6 +85,11 @@ namespace JsonSerializationTests return AZStd::make_shared(); } + AZStd::shared_ptr CreateSingleArrayDefaultInstance() override + { + return AZStd::make_shared(MultiSet{ 0 }); + } + AZStd::shared_ptr CreateFullySetInstance() override { return AZStd::make_shared(MultiSet{ 42, -88, 42, 342 }); diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsEvents.h b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsEvents.h index a3a34dc1df..e0a89e14ac 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsEvents.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsEvents.h @@ -48,7 +48,8 @@ namespace AzPhysics using OnPresimulateEvent = AZ::Event; //! Event triggers at the end of the SystemInterface::Simulate call. - using OnPostsimulateEvent = AZ::Event<>; + //! Parameter is the total time that the physics system will run for during the Simulate call. + using OnPostsimulateEvent = AZ::Event; //! Event trigger when a Scene is added to the simulation. //! When triggered will send the handle to the new Scene. diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Material.cpp b/Code/Framework/AzFramework/AzFramework/Physics/Material.cpp index d84d2739d0..82c5c5d071 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Material.cpp +++ b/Code/Framework/AzFramework/AzFramework/Physics/Material.cpp @@ -402,7 +402,7 @@ namespace Physics ->Attribute(AZ_CRC_CE("EditButton"), "") ->Attribute(AZ_CRC_CE("EditDescription"), "Open in Asset Editor") ->Attribute(AZ::Edit::Attributes::DefaultAsset, &MaterialSelection::GetMaterialLibraryId) - ->DataElement(AZ::Edit::UIHandlers::Default, &MaterialSelection::m_materialIdsAssignedToSlots, "", "") + ->DataElement(AZ::Edit::UIHandlers::Default, &MaterialSelection::m_materialIdsAssignedToSlots, "Slots", "") ->ElementAttribute(Attributes::MaterialLibraryAssetId, &MaterialSelection::GetMaterialLibraryId) ->Attribute(AZ::Edit::Attributes::IndexedChildNameLabelOverride, &MaterialSelection::GetMaterialSlotLabel) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/PhysicsSystem.cpp b/Code/Framework/AzFramework/AzFramework/Physics/PhysicsSystem.cpp index 289b5a940b..aa17b7ec83 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/PhysicsSystem.cpp +++ b/Code/Framework/AzFramework/AzFramework/Physics/PhysicsSystem.cpp @@ -43,7 +43,7 @@ namespace AzPhysics const AZ::BehaviorAzEventDescription postsimulateEventDescription = { "Postsimulate event", - {} // Parameters + {"Tick time"} // Parameters }; behaviorContext->Class("System Interface") diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityTransformBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityTransformBus.h index 3fd9b24e7d..b250abe410 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityTransformBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityTransformBus.h @@ -1,47 +1,36 @@ /* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ #pragma once +#include + namespace AzToolsFramework { using EntityIdList = AZStd::vector; - /*! - * Bus for notifications about entity transform changes from the editor viewport - */ - class EditorTransformChangeNotifications - : public AZ::EBusTraits + //! Notifications about entity transform changes from the editor. + class EditorTransformChangeNotifications : public AZ::EBusTraits { public: - virtual ~EditorTransformChangeNotifications() = default; - - /*! - * Notification that the specified entities are about to have their transforms changed due to user interaction in the editor viewport - * - * \param entityIds Entities about to be changed - */ - virtual void OnEntityTransformChanging(const AzToolsFramework::EntityIdList& /*entityIds*/) {}; - - /*! - * Notification that the specified entities had their transforms changed due to user interaction in the editor viewport - * - * \param entityIds Entities changed - */ - virtual void OnEntityTransformChanged(const AzToolsFramework::EntityIdList& /*entityIds*/) {}; + //! A notification that these entities had their transforms changed due to a user interaction in the editor. + //! @param entityIds Entities that had their transform changed. + virtual void OnEntityTransformChanged([[maybe_unused]] const AzToolsFramework::EntityIdList& entityIds) + { + } + + protected: + ~EditorTransformChangeNotifications() = default; }; using EditorTransformChangeNotificationBus = AZ::EBus; - } // namespace AzToolsFramework - diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp index bcbe98c3a7..a911888028 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -944,7 +945,7 @@ namespace AzToolsFramework return AZ::Success(); } - AZ::u32 TransformComponent::ParentChanged() + AZ::u32 TransformComponent::ParentChangedInspector() { AZ::u32 refreshLevel = AZ::Edit::PropertyRefreshLevels::None; @@ -974,12 +975,23 @@ namespace AzToolsFramework return refreshLevel; } - AZ::u32 TransformComponent::TransformChanged() + AZ::u32 TransformComponent::TransformChangedInspector() + { + if (TransformChanged()) + { + AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( + &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged, + EntityIdList{ GetEntityId() }); + } + + return AZ::Edit::PropertyRefreshLevels::None; + } + + bool TransformComponent::TransformChanged() { if (!m_suppressTransformChangedEvent) { - auto parent = GetParentTransformComponent(); - if (parent) + if (auto parent = GetParentTransformComponent()) { OnTransformChanged(parent->GetLocalTM(), parent->GetWorldTM()); } @@ -987,13 +999,15 @@ namespace AzToolsFramework { OnTransformChanged(AZ::Transform::Identity(), AZ::Transform::Identity()); } + + return true; } - return AZ::Edit::PropertyRefreshLevels::None; + return false; } // This is called when our transform changes static state. - AZ::u32 TransformComponent::StaticChanged() + AZ::u32 TransformComponent::StaticChangedInspector() { AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( &AzToolsFramework::ToolsApplicationEvents::Bus::Events::InvalidatePropertyDisplay, @@ -1175,10 +1189,10 @@ namespace AzToolsFramework Attribute(AZ::Edit::Attributes::AutoExpand, true)-> DataElement(AZ::Edit::UIHandlers::Default, &TransformComponent::m_parentEntityId, "Parent entity", "")-> Attribute(AZ::Edit::Attributes::ChangeValidate, &TransformComponent::ValidatePotentialParent)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &TransformComponent::ParentChanged)-> + Attribute(AZ::Edit::Attributes::ChangeNotify, &TransformComponent::ParentChangedInspector)-> Attribute(AZ::Edit::Attributes::SliceFlags, AZ::Edit::SliceFlags::DontGatherReference | AZ::Edit::SliceFlags::NotPushableOnSliceRoot)-> DataElement(AZ::Edit::UIHandlers::Default, &TransformComponent::m_editorTransform, "Values", "")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &TransformComponent::TransformChanged)-> + Attribute(AZ::Edit::Attributes::ChangeNotify, &TransformComponent::TransformChangedInspector)-> Attribute(AZ::Edit::Attributes::AutoExpand, true)-> DataElement(AZ::Edit::UIHandlers::Button, &TransformComponent::m_addNonUniformScaleButton, "", "")-> Attribute(AZ::Edit::Attributes::ButtonText, "Add non-uniform scale")-> @@ -1189,7 +1203,7 @@ namespace AzToolsFramework EnumAttribute(AZ::TransformConfig::ParentActivationTransformMode::MaintainOriginalRelativeTransform, "Original relative transform")-> EnumAttribute(AZ::TransformConfig::ParentActivationTransformMode::MaintainCurrentWorldTransform, "Current world transform")-> DataElement(AZ::Edit::UIHandlers::Default, &TransformComponent::m_isStatic ,"Static", "Static entities are highly optimized and cannot be moved during runtime.")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &TransformComponent::StaticChanged)-> + Attribute(AZ::Edit::Attributes::ChangeNotify, &TransformComponent::StaticChangedInspector)-> DataElement(AZ::Edit::UIHandlers::Default, &TransformComponent::m_cachedWorldTransformParent, "Cached Parent Entity", "")-> Attribute(AZ::Edit::Attributes::SliceFlags, AZ::Edit::SliceFlags::DontGatherReference | AZ::Edit::SliceFlags::NotPushable)-> Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Hide)-> diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h index 80db5e10fb..30608b9680 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h @@ -182,9 +182,12 @@ namespace AzToolsFramework static void Reflect(AZ::ReflectContext* context); AZ::Outcome ValidatePotentialParent(void* newValue, const AZ::Uuid& valueType); - AZ::u32 ParentChanged(); - AZ::u32 TransformChanged(); - AZ::u32 StaticChanged(); + + AZ::u32 TransformChangedInspector(); + AZ::u32 ParentChangedInspector(); + AZ::u32 StaticChangedInspector(); + + bool TransformChanged(); AZ::Transform GetLocalTranslationTM() const; AZ::Transform GetLocalRotationTM() const; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp index 1a3bc0e5a3..84a58b1f79 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp @@ -165,11 +165,13 @@ namespace UnitTest void EditorEntityComponentChangeDetector::OnEntityTransformChanged( const AzToolsFramework::EntityIdList& entityIds) { + m_entityIds = entityIds; + for (const AZ::EntityId& entityId : entityIds) { if (const auto* entity = GetEntityById(entityId)) { - if (AZ::Component * transformComponent = entity->FindComponent()) + if (AZ::Component* transformComponent = entity->FindComponent()) { OnEntityComponentPropertyChanged(transformComponent->GetId()); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h index 276982d46d..6c146b3ac3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h @@ -239,6 +239,7 @@ namespace UnitTest bool PropertyDisplayInvalidated() const { return m_propertyDisplayInvalidated; } AZStd::vector m_componentIds; + AzToolsFramework::EntityIdList m_entityIds; private: // PropertyEditorEntityChangeNotificationBus ... diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 54934c13c7..7edc6c3a05 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -1024,7 +1024,6 @@ namespace AzToolsFramework static void RefreshUiAfterChange(const EntityIdList& entitiyIds) { EditorTransformChangeNotificationBus::Broadcast(&EditorTransformChangeNotifications::OnEntityTransformChanged, entitiyIds); - ToolsApplicationNotificationBus::Broadcast(&ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay, Refresh_Values); } @@ -1097,7 +1096,7 @@ namespace AzToolsFramework auto entityBoxSelectData = AZStd::make_shared(); m_boxSelect.InstallLeftMouseDown( - [this, entityBoxSelectData](const ViewportInteraction::MouseInteractionEvent& /*mouseInteraction*/) + [this, entityBoxSelectData]([[maybe_unused]] const ViewportInteraction::MouseInteractionEvent& mouseInteraction) { // begin selection undo/redo command entityBoxSelectData->m_boxSelectSelectionCommand = @@ -1295,8 +1294,12 @@ namespace AzToolsFramework }); translationManipulators->InstallLinearManipulatorMouseUpCallback( - [this]([[maybe_unused]] const LinearManipulator::Action& action) mutable + [this, manipulatorEntityIds]([[maybe_unused]] const LinearManipulator::Action& action) mutable { + AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( + &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged, + manipulatorEntityIds->m_entityIds); + EndRecordManipulatorCommand(); }); @@ -1325,8 +1328,12 @@ namespace AzToolsFramework }); translationManipulators->InstallPlanarManipulatorMouseUpCallback( - [this, manipulatorEntityIds](const PlanarManipulator::Action& /*action*/) + [this, manipulatorEntityIds]([[maybe_unused]] const PlanarManipulator::Action& action) { + AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( + &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged, + manipulatorEntityIds->m_entityIds); + EndRecordManipulatorCommand(); }); @@ -1354,8 +1361,12 @@ namespace AzToolsFramework }); translationManipulators->InstallSurfaceManipulatorMouseUpCallback( - [this, manipulatorEntityIds](const SurfaceManipulator::Action& /*action*/) + [this, manipulatorEntityIds]([[maybe_unused]] const SurfaceManipulator::Action& action) { + AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( + &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged, + manipulatorEntityIds->m_entityIds); + EndRecordManipulatorCommand(); }); @@ -1392,7 +1403,7 @@ namespace AzToolsFramework AZStd::shared_ptr sharedRotationState = AZStd::make_shared(); rotationManipulators->InstallLeftMouseDownCallback( - [this, sharedRotationState](const AngularManipulator::Action& /*action*/) mutable -> void + [this, sharedRotationState]([[maybe_unused]] const AngularManipulator::Action& action) mutable -> void { sharedRotationState->m_savedOrientation = AZ::Quaternion::CreateIdentity(); sharedRotationState->m_referenceFrameAtMouseDown = m_referenceFrame; @@ -1518,8 +1529,12 @@ namespace AzToolsFramework }); rotationManipulators->InstallLeftMouseUpCallback( - [this](const AngularManipulator::Action& /*action*/) + [this, sharedRotationState]([[maybe_unused]] const AngularManipulator::Action& action) { + AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( + &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged, + sharedRotationState->m_entityIds); + EndRecordManipulatorCommand(); }); @@ -1565,6 +1580,10 @@ namespace AzToolsFramework auto uniformLeftMouseUpCallback = [this, manipulatorEntityIds]([[maybe_unused]] const LinearManipulator::Action& action) { + AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( + &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged, + manipulatorEntityIds->m_entityIds); + m_entityIdManipulators.m_manipulators->SetLocalTransform(RecalculateAverageManipulatorTransform( m_entityIdManipulators.m_lookups, m_pivotOverrideFrame, m_pivotMode, m_referenceFrame)); }; @@ -2402,7 +2421,7 @@ namespace AzToolsFramework AddAction( m_actions, { QKeySequence(Qt::Key_U) }, - /*ID_VIEWPORTUI_VISIBLE=*/50040, "Toggle ViewportUI", "Hide/Unhide Viewport UI", + /*ID_VIEWPORTUI_VISIBLE=*/50040, "Toggle Viewport UI", "Hide/Show Viewport UI", [this]() { SetAllViewportUiVisible(!m_viewportUiVisible); @@ -3642,17 +3661,17 @@ namespace AzToolsFramework RegenerateManipulators(); } - void EditorTransformComponentSelection::OnEntityVisibilityChanged(const bool /*visibility*/) + void EditorTransformComponentSelection::OnEntityVisibilityChanged([[maybe_unused]] const bool visibility) { m_selectedEntityIdsAndManipulatorsDirty = true; } - void EditorTransformComponentSelection::OnEntityLockChanged(const bool /*locked*/) + void EditorTransformComponentSelection::OnEntityLockChanged([[maybe_unused]] const bool locked) { m_selectedEntityIdsAndManipulatorsDirty = true; } - void EditorTransformComponentSelection::EnteredComponentMode(const AZStd::vector& /*componentModeTypes*/) + void EditorTransformComponentSelection::EnteredComponentMode([[maybe_unused]] const AZStd::vector& componentModeTypes) { SetAllViewportUiVisible(false); @@ -3661,7 +3680,7 @@ namespace AzToolsFramework ToolsApplicationNotificationBus::Handler::BusDisconnect(); } - void EditorTransformComponentSelection::LeftComponentMode(const AZStd::vector& /*componentModeTypes*/) + void EditorTransformComponentSelection::LeftComponentMode([[maybe_unused]] const AZStd::vector& componentModeTypes) { SetAllViewportUiVisible(true); diff --git a/Code/Framework/AzToolsFramework/CMakeLists.txt b/Code/Framework/AzToolsFramework/CMakeLists.txt index 53dba8eb48..661cb43302 100644 --- a/Code/Framework/AzToolsFramework/CMakeLists.txt +++ b/Code/Framework/AzToolsFramework/CMakeLists.txt @@ -85,6 +85,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) AZ::AzManipulatorTestFramework.Static AZ::AzTest AZ::AzQtComponents + RUNTIME_DEPENDENCIES + 3rdParty::Qt::Test ) ly_add_googletest( NAME AZ::AzToolsFramework.Tests diff --git a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp index 9a34efa6f5..ab421b53b3 100644 --- a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp @@ -425,6 +425,43 @@ namespace UnitTest EXPECT_TRUE(finalEntityTransform.IsClose(finalTransformWorld, 0.01f)); } + TEST_F(EditorTransformComponentSelectionManipulatorTestFixture, TranslatingEntityWithLinearManipulatorNotifiesOnEntityTransformChanged) + { + EditorEntityComponentChangeDetector editorEntityChangeDetector(m_entity1); + + // the initial starting position of the entity (in front and to the left of the camera) + const auto initialTransformWorld = AZ::Transform::CreateTranslation(AZ::Vector3(-10.0f, 10.0f, 0.0f)); + // where the entity should end up (in front and to the right of the camera) + const auto finalTransformWorld = AZ::Transform::CreateTranslation(AZ::Vector3(10.0f, 10.0f, 0.0f)); + + // calculate the position in screen space of the initial position of the entity + const auto initialPositionScreen = AzFramework::WorldToScreen(initialTransformWorld.GetTranslation(), m_cameraState); + // calculate the position in screen space of the final position of the entity + const auto finalPositionScreen = AzFramework::WorldToScreen(finalTransformWorld.GetTranslation(), m_cameraState); + + // move the entity to its starting position + AzToolsFramework::SetWorldTransform(m_entity1, initialTransformWorld); + // select the entity (this will cause the manipulators to appear in EditorTransformComponentSelection) + AzToolsFramework::SelectEntity(m_entity1); + + // create an offset along the linear manipulator pointing along the x-axis (perpendicular to the camera view) + const auto mouseOffsetOnManipulator = AzFramework::ScreenVector(10, 0); + // store the mouse down position on the manipulator + const auto mouseDownPosition = initialPositionScreen + mouseOffsetOnManipulator; + // final position in screen space of the mouse + const auto mouseMovePosition = finalPositionScreen + mouseOffsetOnManipulator; + + m_actionDispatcher->CameraState(m_cameraState) + ->MousePosition(mouseDownPosition) + ->MouseLButtonDown() + ->MousePosition(mouseMovePosition) + ->MouseLButtonUp(); + + // verify a EditorTransformChangeNotificationBus::OnEntityTransformChanged occurred + using ::testing::UnorderedElementsAreArray; + EXPECT_THAT(editorEntityChangeDetector.m_entityIds, UnorderedElementsAreArray(m_entityIds)); + } + // simple widget to listen for a mouse wheel event and then forward it on to the ViewportSelectionRequestBus class WheelEventWidget : public QWidget { diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp index 8e4c2eaad7..1901560b00 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/SpawnableCreateBenchmarks.cpp @@ -29,15 +29,20 @@ namespace Benchmark {}, m_pathString)); + auto& prefabDom = m_prefabSystemComponent->FindTemplateDom(instance->GetTemplateId()); for (auto _ : state) { - state.PauseTiming(); - - AzFramework::Spawnable spawnable; - AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(spawnable, prefabDom); - - state.ResumeTiming(); + // Create a vector to store spawnables so that they don't get destroyed immediately after construction. + AZStd::vector> spawnables; + spawnables.reserve(numSpawnables); + + for (int spwanableCounter = 0; spwanableCounter < numSpawnables; ++spwanableCounter) + { + AZStd::unique_ptr spawnable = AZStd::make_unique(); + AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(*spawnable, prefabDom); + spawnables.push_back(AZStd::move(spawnable)); + } } state.SetComplexityN(numSpawnables); @@ -50,3 +55,4 @@ namespace Benchmark } #endif + diff --git a/Code/Framework/Tests/CMakeLists.txt b/Code/Framework/Tests/CMakeLists.txt index 491f6d8e14..7cb243d69b 100644 --- a/Code/Framework/Tests/CMakeLists.txt +++ b/Code/Framework/Tests/CMakeLists.txt @@ -9,7 +9,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) +if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) @@ -27,40 +27,42 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) AZ::AzFramework ) - ly_add_target( - NAME ProcessLaunchTest EXECUTABLE - NAMESPACE AZ - FILES_CMAKE - process_launch_test_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - . - BUILD_DEPENDENCIES - PRIVATE - AZ::AzCore - AZ::AzFramework - ) + if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_add_target( + NAME ProcessLaunchTest EXECUTABLE + NAMESPACE AZ + FILES_CMAKE + process_launch_test_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + . + BUILD_DEPENDENCIES + PRIVATE + AZ::AzCore + AZ::AzFramework + ) - ly_add_target( - NAME Framework.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} - NAMESPACE AZ - FILES_CMAKE - frameworktests_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - . - ${pal_dir} - BUILD_DEPENDENCIES - PRIVATE - AZ::AzTest - AZ::AzToolsFramework - AZ::AzTestShared - AZ::AzFrameworkTestShared - RUNTIME_DEPENDENCIES - AZ::ProcessLaunchTest - ) - ly_add_googletest( - NAME AZ::Framework.Tests - ) + ly_add_target( + NAME Framework.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} + NAMESPACE AZ + FILES_CMAKE + frameworktests_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + . + ${pal_dir} + BUILD_DEPENDENCIES + PRIVATE + AZ::AzTest + AZ::AzToolsFramework + AZ::AzTestShared + AZ::AzFrameworkTestShared + RUNTIME_DEPENDENCIES + AZ::ProcessLaunchTest + ) + ly_add_googletest( + NAME AZ::Framework.Tests + ) + endif() endif() diff --git a/Code/Framework/Tests/Mocks/MockSpawnableEntitiesInterface.h b/Code/Framework/Tests/Mocks/MockSpawnableEntitiesInterface.h new file mode 100644 index 0000000000..51063a49be --- /dev/null +++ b/Code/Framework/Tests/Mocks/MockSpawnableEntitiesInterface.h @@ -0,0 +1,84 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ +#pragma once + +#include +#include +#include +#include + +namespace AzFramework +{ + class MockSpawnableEntitiesInterface; + using NiceSpawnableEntitiesInterfaceMock = ::testing::NiceMock; + + class MockSpawnableEntitiesInterface : public SpawnableEntitiesDefinition + { + public: + AZ_RTTI(MockSpawnableEntitiesInterface, "{2A20FF73-C445-4F32-ABB9-5CF0A5778404}", SpawnableEntitiesDefinition); + + MockSpawnableEntitiesInterface() + { + AZ::Interface::Register(this); + } + + virtual ~MockSpawnableEntitiesInterface() + { + AZ::Interface::Unregister(this); + } + + MOCK_METHOD2(SpawnAllEntities, void(EntitySpawnTicket& ticket, SpawnAllEntitiesOptionalArgs optionalArgs)); + + MOCK_METHOD3( + SpawnEntities, + void(EntitySpawnTicket& ticket, AZStd::vector entityIndices, SpawnEntitiesOptionalArgs optionalArgs)); + + MOCK_METHOD2(DespawnAllEntities, void(EntitySpawnTicket& ticket, DespawnAllEntitiesOptionalArgs optionalArgs)); + + MOCK_METHOD3( + ReloadSpawnable, + void(EntitySpawnTicket& ticket, AZ::Data::Asset spawnable, ReloadSpawnableOptionalArgs optionalArgs)); + + MOCK_METHOD3( + ListEntities, void(EntitySpawnTicket& ticket, ListEntitiesCallback listCallback, ListEntitiesOptionalArgs optionalArgs)); + + MOCK_METHOD3( + ListIndicesAndEntities, + void(EntitySpawnTicket& ticket, ListIndicesEntitiesCallback listCallback, ListEntitiesOptionalArgs optionalArgs)); + + MOCK_METHOD3( + ClaimEntities, + void(EntitySpawnTicket& ticket, ClaimEntitiesCallback listCallback, ClaimEntitiesOptionalArgs optionalArgs)); + + MOCK_METHOD3(Barrier, void(EntitySpawnTicket& ticket, BarrierCallback completionCallback, BarrierOptionalArgs optionalArgs)); + + MOCK_METHOD1(CreateTicket, AZStd::pair(AZ::Data::Asset&& spawnable)); + MOCK_METHOD1(DestroyTicket, void(void* ticket)); + + /** Installs some default result values for the above functions. + * Note that you can always override these in scope of your test by adding additional ON_CALL / EXPECT_CALL + * statements in the body of your test or after calling this function, and yours will take precedence. + **/ + static void InstallDefaultReturns(NiceSpawnableEntitiesInterfaceMock& target) + { + using namespace ::testing; + + // The ID and pointer are completely arbitrary, they just need to both be non-zero to look like a valid ticket. + constexpr EntitySpawnTicket::Id ticketId(1); + static int ticketPayload = 0; + ON_CALL(target, CreateTicket(_)).WillByDefault( + Return(AZStd::make_pair(ticketId, &ticketPayload))); + } + + }; + +} // namespace AzFramework diff --git a/Code/Framework/Tests/framework_shared_tests_files.cmake b/Code/Framework/Tests/framework_shared_tests_files.cmake index 57345ee630..8cf1a2e3fd 100644 --- a/Code/Framework/Tests/framework_shared_tests_files.cmake +++ b/Code/Framework/Tests/framework_shared_tests_files.cmake @@ -10,6 +10,7 @@ # set(FILES + Mocks/MockSpawnableEntitiesInterface.h Utils/Utils.h Utils/Utils.cpp ) diff --git a/Code/LauncherUnified/launcher_generator.cmake b/Code/LauncherUnified/launcher_generator.cmake index 5fa0f7a0e3..2180aff7d8 100644 --- a/Code/LauncherUnified/launcher_generator.cmake +++ b/Code/LauncherUnified/launcher_generator.cmake @@ -26,7 +26,7 @@ foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJEC message(FATAL_ERROR "The specified project path of ${project_real_path} does not contain a project.json file") else() # Add the project_name to global LY_PROJECTS_TARGET_NAME property - file(READ "${project_real_path}/project.json" project_json) + ly_file_read("${project_real_path}/project.json" project_json) string(JSON project_name ERROR_VARIABLE json_error GET ${project_json} "project_name") if(json_error) message(FATAL_ERROR "There is an error reading the \"project_name\" key from the '${project_real_path}/project.json' file: ${json_error}") diff --git a/Code/Sandbox/Editor/CMakeLists.txt b/Code/Sandbox/Editor/CMakeLists.txt index e1fce97067..51620c6e37 100644 --- a/Code/Sandbox/Editor/CMakeLists.txt +++ b/Code/Sandbox/Editor/CMakeLists.txt @@ -104,7 +104,6 @@ ly_add_target( 3rdParty::Qt::Gui 3rdParty::Qt::Widgets 3rdParty::Qt::Concurrent - 3rdParty::Qt::WebEngineWidgets 3rdParty::tiff 3rdParty::squish-ccr 3rdParty::zlib diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index 4169bf93a8..792f817362 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -4005,17 +4005,10 @@ void CCryEditApp::SetEditorWindowTitle(QString sTitleStr, QString sPreTitleStr, { if (MainWindow::instance() || m_pConsoleDialog) { - QString platform = ""; - -#ifdef WIN64 - platform = "[x64]"; -#else - platform = "[x86]"; -#endif //WIN64 if (sTitleStr.isEmpty()) { - sTitleStr = QObject::tr("Open 3D Engine Editor Beta %1 - Build %2").arg(platform).arg(LY_BUILD); + sTitleStr = QObject::tr("O3DE Editor [Developer Preview]"); } if (!sPreTitleStr.isEmpty()) diff --git a/Code/Sandbox/Editor/EditorPreferencesPageAWS.cpp b/Code/Sandbox/Editor/EditorPreferencesPageAWS.cpp index edaf813cd8..4ad4e70be4 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageAWS.cpp +++ b/Code/Sandbox/Editor/EditorPreferencesPageAWS.cpp @@ -47,8 +47,6 @@ CEditorPreferencesPage_AWS::CEditorPreferencesPage_AWS() { m_settingsRegistry = AZStd::make_unique(); InitializeSettings(); - - // TODO Update with AWS svg. m_icon = QIcon(":/res/AWS_preferences_icon.svg"); } diff --git a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp index a7420b79a4..d62ca741ce 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp +++ b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp @@ -28,8 +28,6 @@ #define EDITORPREFS_EVENTVALTOGGLE "operation" #define UNDOSLICESAVE_VALON "UndoSliceSaveValueOn" #define UNDOSLICESAVE_VALOFF "UndoSliceSaveValueOff" -#define EDITORUI10_ENABLED "EditorUI10On" -#define EDITORUI10_DISABLED "EditorUI10Off" void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) { @@ -45,8 +43,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->Field("StylusMode", &GeneralSettings::m_stylusMode) ->Field("ShowNews", &GeneralSettings::m_bShowNews) ->Field("EnableSceneInspector", &GeneralSettings::m_enableSceneInspector) - ->Field("RestoreViewportCamera", &GeneralSettings::m_restoreViewportCamera) - ->Field("PrefabSystem", &GeneralSettings::m_enablePrefabSystem); + ->Field("RestoreViewportCamera", &GeneralSettings::m_restoreViewportCamera); serialize.Class() ->Version(2) @@ -94,8 +91,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->EnumAttribute(AzQtComponents::ToolBar::ToolBarIconSize::IconLarge, "Large") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_stylusMode, "Stylus Mode", "Stylus Mode for tablets and other pointing devices") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_restoreViewportCamera, EditorPreferencesGeneralRestoreViewportCameraSettingName, "Keep the original editor viewport transform when exiting game mode.") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enableSceneInspector, "Enable Scene Inspector (EXPERIMENTAL)", "Enable the option to inspect the internal data loaded from scene files like .fbx. This is an experimental feature. Restart the Scene Settings if the option is not visible under the Help menu.") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enablePrefabSystem, "Enable Prefab System (EXPERIMENTAL)", "Enable this option to preview Open 3D Engine's new prefab system. Enabling this setting removes slice support for level entities; you will need to restart the Editor for the change to take effect."); + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enableSceneInspector, "Enable Scene Inspector (EXPERIMENTAL)", "Enable the option to inspect the internal data loaded from scene files like .fbx. This is an experimental feature. Restart the Scene Settings if the option is not visible under the Help menu."); editContext->Class("Messaging", "") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Messaging::m_showDashboard, "Show Welcome to Open 3D Engine at startup", "Show Welcome to Open 3D Engine at startup") @@ -159,8 +155,6 @@ void CEditorPreferencesPage_General::OnApply() gSettings.restoreViewportCamera = m_generalSettings.m_restoreViewportCamera; gSettings.enableSceneInspector = m_generalSettings.m_enableSceneInspector; - gSettings.prefabSystem = m_generalSettings.m_enablePrefabSystem; - if (static_cast(m_generalSettings.m_toolbarIconSize) != gSettings.gui.nToolbarIconSize) { gSettings.gui.nToolbarIconSize = static_cast(m_generalSettings.m_toolbarIconSize); @@ -178,16 +172,6 @@ void CEditorPreferencesPage_General::OnApply() //slices gSettings.sliceSettings.dynamicByDefault = m_sliceSettings.m_slicesDynamicByDefault; - - // if the user enabled/disabled the prefab context - notify them that a restart - // is required in order to see the effect of the change - if (gSettings.prefabSystem != m_generalSettings.m_enablePrefabSystemInitialValue) - { - QMessageBox::warning( - AzToolsFramework::GetActiveWindow(), QObject::tr("Restart required"), - QObject::tr("Restart the Editor in order for the Prefab/Slice system changes to take effect.") - ); - } } void CEditorPreferencesPage_General::InitializeSettings() @@ -202,8 +186,6 @@ void CEditorPreferencesPage_General::InitializeSettings() m_generalSettings.m_stylusMode = gSettings.stylusMode; m_generalSettings.m_restoreViewportCamera = gSettings.restoreViewportCamera; m_generalSettings.m_enableSceneInspector = gSettings.enableSceneInspector; - m_generalSettings.m_enablePrefabSystem = gSettings.prefabSystem; - m_generalSettings.m_enablePrefabSystemInitialValue = gSettings.prefabSystem; m_generalSettings.m_toolbarIconSize = static_cast(gSettings.gui.nToolbarIconSize); diff --git a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.h b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.h index 31776e9c10..6e7eeebd43 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.h +++ b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.h @@ -58,10 +58,6 @@ private: bool m_restoreViewportCamera; bool m_bShowNews; bool m_enableSceneInspector; - bool m_enablePrefabSystem; - - // Only used to tell if the user has changed this value since it requires a restart - bool m_enablePrefabSystemInitialValue; }; struct Messaging diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 3b04fc70f8..82d74d5d00 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -154,11 +154,23 @@ SandboxIntegrationManager::SandboxIntegrationManager() { // Required to receive events from the Cry Engine undo system GetIEditor()->GetUndoManager()->AddListener(this); + + // Only create the PrefabIntegrationManager if prefabs are enabled + bool prefabSystemEnabled = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult( + prefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); + if (prefabSystemEnabled) + { + m_prefabIntegrationManager = aznew AzToolsFramework::Prefab::PrefabIntegrationManager(); + } } SandboxIntegrationManager::~SandboxIntegrationManager() { GetIEditor()->GetUndoManager()->RemoveListener(this); + + delete m_prefabIntegrationManager; + m_prefabIntegrationManager = nullptr; } void SandboxIntegrationManager::Setup() @@ -187,11 +199,16 @@ void SandboxIntegrationManager::Setup() AZ_Assert((m_editorEntityUiInterface != nullptr), "SandboxIntegrationManager requires a EditorEntityUiInterface instance to be present on Setup()."); - m_prefabIntegrationInterface = AZ::Interface::Get(); - - AZ_Assert( - (m_prefabIntegrationInterface != nullptr), - "SandboxIntegrationManager requires a PrefabIntegrationInterface instance to be present on Setup()."); + bool prefabSystemEnabled = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult( + prefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); + if (prefabSystemEnabled) + { + m_prefabIntegrationInterface = AZ::Interface::Get(); + AZ_Assert( + (m_prefabIntegrationInterface != nullptr), + "SandboxIntegrationManager requires a PrefabIntegrationInterface instance to be present on Setup()."); + } m_editorEntityAPI = AZ::Interface::Get(); AZ_Assert(m_editorEntityAPI, "SandboxIntegrationManager requires an EditorEntityAPI instance to be present on Setup()."); diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h index 5cb03cc99f..b734d4d361 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h @@ -305,7 +305,7 @@ private: bool m_debugDisplayBusImplementationActive = false; - AzToolsFramework::Prefab::PrefabIntegrationManager m_prefabIntegrationManager; + AzToolsFramework::Prefab::PrefabIntegrationManager* m_prefabIntegrationManager = nullptr; AzToolsFramework::EditorEntityUiInterface* m_editorEntityUiInterface = nullptr; AzToolsFramework::Prefab::PrefabIntegrationInterface* m_prefabIntegrationInterface = nullptr; diff --git a/Code/Tools/AssetBundler/tests/DummyProject/project.json b/Code/Tools/AssetBundler/tests/DummyProject/project.json index 0fa6ec7011..84edbe781b 100644 --- a/Code/Tools/AssetBundler/tests/DummyProject/project.json +++ b/Code/Tools/AssetBundler/tests/DummyProject/project.json @@ -10,5 +10,6 @@ "version_number" : 1, "version_name" : "1.0.0.0", "orientation" : "landscape" - } + }, + "engine" : "o3de" } diff --git a/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp b/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp index 69e60f6733..74562f5af1 100644 --- a/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp +++ b/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp @@ -63,7 +63,7 @@ namespace AssetProcessor } - AZ::IO::Path fullPath = AZ::IO::Path(scanFolder.m_scanFolder, AZ::IO::PosixPathSeparator) / source.m_sourceName; + AZ::IO::Path fullPath = AZ::IO::Path(scanFolder.m_scanFolder) / source.m_sourceName; // It's common for Open 3D Engine game projects and scan folders to be in a subfolder // of the engine install. To improve readability of the source files, strip out @@ -74,7 +74,7 @@ namespace AssetProcessor } if (m_assetRootSet) { - AzFramework::StringFunc::Replace(fullPath.Native(), m_assetRoot.absolutePath().toUtf8(), ""); + fullPath = fullPath.LexicallyProximate(m_assetRoot.absolutePath().toUtf8().constData()); } if (fullPath.empty()) @@ -88,11 +88,12 @@ namespace AssetProcessor QModelIndex newIndicesStart; AssetTreeItem* parentItem = m_root.get(); - AZ::IO::Path currentFullFolderPath; - const AZ::IO::PathView filename = fullPath.Filename(); - const AZ::IO::PathView fullPathWithoutFilename = fullPath.RemoveFilename(); + // Use posix path separator for each child item + AZ::IO::Path currentFullFolderPath(AZ::IO::PosixPathSeparator); + const AZ::IO::FixedMaxPath filename = fullPath.Filename(); + fullPath.RemoveFilename(); AZStd::fixed_string currentPath; - for (auto pathIt = fullPathWithoutFilename.begin(); pathIt != fullPathWithoutFilename.end(); ++pathIt) + for (auto pathIt = fullPath.begin(); pathIt != fullPath.end(); ++pathIt) { currentPath = pathIt->FixedMaxPathString(); currentFullFolderPath /= currentPath; diff --git a/Code/Tools/AssetProcessor/native/utilities/BuilderManager.cpp b/Code/Tools/AssetProcessor/native/utilities/BuilderManager.cpp index 68ed75ebfb..d59569660b 100644 --- a/Code/Tools/AssetProcessor/native/utilities/BuilderManager.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/BuilderManager.cpp @@ -12,6 +12,7 @@ #include "BuilderManager.h" #include +#include #include #include @@ -186,10 +187,9 @@ namespace AssetProcessor QDir projectCacheRoot; AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot); - QString gameName = AssetUtilities::ComputeProjectName(); - QString projectPath = AssetUtilities::ComputeProjectPath(); - QDir engineRoot; - AssetUtilities::ComputeEngineRoot(engineRoot); + AZ::SettingsRegistryInterface::FixedValueString projectName = AZ::Utils::GetProjectName(); + AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath(); + AZ::IO::FixedMaxPathString enginePath = AZ::Utils::GetEnginePath(); int portNumber = 0; ApplicationServerBus::BroadcastResult(portNumber, &ApplicationServerBus::Events::GetServerListeningPort); @@ -197,14 +197,14 @@ namespace AssetProcessor AZStd::string params; #if !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS params = AZStd::string::format( - R"(-task=%s -id="%s" -project-name="%s" -project-cache-path="%s" -project-path="%s" -engine-path="%s" -port %d)", task, - builderGuid.c_str(), gameName.toUtf8().constData(), projectCacheRoot.absolutePath().toUtf8().constData(), - projectPath.toUtf8().constData(), engineRoot.absolutePath().toUtf8().constData(), portNumber); + R"(-task=%s -id="%s" -project-name="%s" -project-cache-path="%s" -project-path="%s" -engine-path="%s" -port %d)", + task, builderGuid.c_str(), projectName.c_str(), projectCacheRoot.absolutePath().toUtf8().constData(), + projectPath.c_str(), enginePath.c_str(), portNumber); #else params = AZStd::string::format( R"(-task=%s -id="%s" -project-name="\"%s\"" -project-cache-path="\"%s\"" -project-path="\"%s\"" -engine-path="\"%s\"" -port %d)", - task, builderGuid.c_str(), gameName.toUtf8().constData(), projectCacheRoot.absolutePath().toUtf8().constData(), - projectPath.toUtf8().constData(), engineRoot.absolutePath().toUtf8().constData(), portNumber); + task, builderGuid.c_str(), projectName.c_str(), projectCacheRoot.absolutePath().toUtf8().constData(), + projectPath.c_str(), enginePath.c_str(), portNumber); #endif // !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS if (moduleFilePath && moduleFilePath[0]) diff --git a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp index c8ed3954ac..0e3a4ba95d 100644 --- a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp @@ -77,6 +77,7 @@ namespace O3DE::ProjectManager return ProjectManagerScreen::CreateProject; } + // Called when pressing "Create New Project" void CreateProjectCtrl::NotifyCurrentScreen() { ScreenWidget* currentScreen = reinterpret_cast(m_stack->currentWidget()); @@ -84,6 +85,11 @@ namespace O3DE::ProjectManager { currentScreen->NotifyCurrentScreen(); } + + // Gather the gems from the project template. When we will have multiple project templates, we need to re-gather them + // on changing the template and let the user know that any further changes on top of the template will be lost. + QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath(); + m_gemCatalogScreen->ReinitForProject(projectTemplatePath + "/Template", /*isNewProject=*/true); } void CreateProjectCtrl::HandleBackButton() @@ -151,9 +157,6 @@ namespace O3DE::ProjectManager { m_stack->setCurrentIndex(m_stack->currentIndex() + 1); - QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath(); - m_gemCatalogScreen->ReinitForProject(projectTemplatePath + "/Template", /*isNewProject=*/true); - Update(); } else diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index 65f73accd1..409c51315d 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -89,17 +89,18 @@ namespace O3DE::ProjectManager return ProjectManagerScreen::UpdateProject; } + // Called when pressing "Edit Project Settings..." void UpdateProjectCtrl::NotifyCurrentScreen() { m_stack->setCurrentIndex(ScreenOrder::Settings); Update(); + + // Gather the available gems that will be shown in the gem catalog. + m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/false); } void UpdateProjectCtrl::HandleGemsButton() { - // The next page is the gem catalog. Gather the available gems that will be shown in the gem catalog. - m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/false); - m_stack->setCurrentWidget(m_gemCatalogScreen); Update(); } diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/FbxImportRequestHandler.cpp b/Code/Tools/SceneAPI/FbxSceneBuilder/FbxImportRequestHandler.cpp index a8b059304d..4ab4dd4d62 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/FbxImportRequestHandler.cpp +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/FbxImportRequestHandler.cpp @@ -77,6 +77,7 @@ namespace AZ { AZStd::string extension; StringFunc::Path::GetExtension(path.c_str(), extension); + AZStd::to_lower(extension.begin(), extension.end()); if (!m_settings.m_supportedFileTypeExtensions.contains(extension)) { diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp index d72cdde8e7..25b58ab544 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp @@ -151,7 +151,7 @@ namespace AZ SerializeContext* serializeContext = azrtti_cast(context); if (serializeContext) { - serializeContext->Class()->Version(4); // [LYN-3971] Bone pruning crash fix in AssImp SDK + serializeContext->Class()->Version(5); // [LYN-4226] Invert PostRotation matrix in animation chains } } diff --git a/Code/Tools/SerializeContextTools/SliceConverter.cpp b/Code/Tools/SerializeContextTools/SliceConverter.cpp index e7dc49d5b3..70412e23bc 100644 --- a/Code/Tools/SerializeContextTools/SliceConverter.cpp +++ b/Code/Tools/SerializeContextTools/SliceConverter.cpp @@ -385,24 +385,36 @@ namespace AZ return false; } - // Now, convert the nested slice to a prefab. - bool nestedSliceResult = ConvertSliceFile(serializeContext, assetPath, isDryRun); - if (!nestedSliceResult) - { - AZ_Warning("Convert-Slice", nestedSliceResult, " Nested slice '%s' could not be converted.", assetPath.c_str()); - return false; - } + // Check to see if we've already converted this slice at a higher level of slice nesting, or if this is our first + // occurrence and we need to convert it now. - // Find the prefab template we created for the newly-created nested prefab. - // To get the template, we need to take our absolute slice path and turn it into a project-relative prefab path. + // First, take our absolute slice path and turn it into a project-relative prefab path. AZ::IO::Path nestedPrefabPath = assetPath; nestedPrefabPath.ReplaceExtension("prefab"); auto prefabLoaderInterface = AZ::Interface::Get(); nestedPrefabPath = prefabLoaderInterface->GenerateRelativePath(nestedPrefabPath); + // Now, see if we already have a template ID in memory for it. AzToolsFramework::Prefab::TemplateId nestedTemplateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(nestedPrefabPath); + + // If we don't have a template ID yet, convert the nested slice to a prefab and get the template ID. + if (nestedTemplateId == AzToolsFramework::Prefab::InvalidTemplateId) + { + bool nestedSliceResult = ConvertSliceFile(serializeContext, assetPath, isDryRun); + if (!nestedSliceResult) + { + AZ_Warning("Convert-Slice", nestedSliceResult, " Nested slice '%s' could not be converted.", assetPath.c_str()); + return false; + } + + nestedTemplateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(nestedPrefabPath); + AZ_Assert(nestedTemplateId != AzToolsFramework::Prefab::InvalidTemplateId, + "Template ID for %s is invalid", nestedPrefabPath.c_str()); + } + + // Get the nested prefab template. AzToolsFramework::Prefab::TemplateReference nestedTemplate = prefabSystemComponentInterface->FindTemplate(nestedTemplateId); diff --git a/Gems/AWSCore/Code/CMakeLists.txt b/Gems/AWSCore/Code/CMakeLists.txt index d6cd57355f..4ade4b5e54 100644 --- a/Gems/AWSCore/Code/CMakeLists.txt +++ b/Gems/AWSCore/Code/CMakeLists.txt @@ -74,7 +74,7 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) ) ly_add_target( - NAME AWSCore.Editor MODULE + NAME AWSCore.Editor GEM_MODULE NAMESPACE Gem FILES_CMAKE awscore_editor_shared_files.cmake @@ -89,6 +89,8 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) Gem::AWSCore ) + # This target is not a real gem module + # It is not meant to be loaded by the ModuleManager in C++ ly_add_target( NAME AWSCore.ResourceMappingTool MODULE NAMESPACE Gem diff --git a/Gems/AWSCore/Code/Include/Private/Editor/Attribution/AWSAttributionServiceApi.h b/Gems/AWSCore/Code/Include/Private/Editor/Attribution/AWSAttributionServiceApi.h index d14e51589c..cee3574f4d 100644 --- a/Gems/AWSCore/Code/Include/Private/Editor/Attribution/AWSAttributionServiceApi.h +++ b/Gems/AWSCore/Code/Include/Private/Editor/Attribution/AWSAttributionServiceApi.h @@ -43,7 +43,7 @@ namespace AWSCore bool UseAWSCredentials() { - return false; + return true; } //! Request body for the service API request. diff --git a/Gems/AWSCore/Code/Source/Credential/AWSCVarCredentialHandler.cpp b/Gems/AWSCore/Code/Source/Credential/AWSCVarCredentialHandler.cpp index f4315c41c2..30a810eb23 100644 --- a/Gems/AWSCore/Code/Source/Credential/AWSCVarCredentialHandler.cpp +++ b/Gems/AWSCore/Code/Source/Credential/AWSCVarCredentialHandler.cpp @@ -18,7 +18,6 @@ namespace AWSCore { AZ_CVAR(AZ::CVarFixedString, cl_awsAccessKey, "", nullptr, AZ::ConsoleFunctorFlags::Null, "Override AWS access key"); AZ_CVAR(AZ::CVarFixedString, cl_awsSecretKey, "", nullptr, AZ::ConsoleFunctorFlags::Null, "Override AWS secret key"); - AZ_CVAR(AZ::CVarFixedString, cl_awsSessionToken, "", nullptr, AZ::ConsoleFunctorFlags::Null, "Override AWS session token"); static constexpr char AWSCVARCREDENTIALHANDLER_ALLOC_TAG[] = "AWSCVarCredentialHandler"; @@ -43,13 +42,12 @@ namespace AWSCore { auto accessKey = static_cast(cl_awsAccessKey); auto secretKey = static_cast(cl_awsSecretKey); - auto sessionToken = static_cast(cl_awsSessionToken); - // Session token is not always required + if (!accessKey.empty() && !secretKey.empty()) { AZStd::lock_guard credentialsLock{m_credentialMutex}; m_cvarCredentialsProvider = Aws::MakeShared( - AWSCVARCREDENTIALHANDLER_ALLOC_TAG, accessKey.c_str(), secretKey.c_str(), sessionToken.c_str()); + AWSCVARCREDENTIALHANDLER_ALLOC_TAG, accessKey.c_str(), secretKey.c_str()); return m_cvarCredentialsProvider; } return nullptr; diff --git a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionManager.cpp b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionManager.cpp index e7a6828903..6edb606a10 100644 --- a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionManager.cpp +++ b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionManager.cpp @@ -25,20 +25,24 @@ #include #include +#include +#include + namespace AWSCore { - static constexpr const char* EngineVersionJsonKey = "O3DEVersion"; + constexpr const char* EngineVersionJsonKey = "O3DEVersion"; constexpr char EditorAWSPreferencesFileName[] = "editor_aws_preferences.setreg"; constexpr char AWSAttributionSettingsPrefixKey[] = "/Amazon/AWS/Preferences"; constexpr char AWSAttributionEnabledKey[] = "/Amazon/AWS/Preferences/AWSAttributionEnabled"; constexpr char AWSAttributionDelaySecondsKey[] = "/Amazon/AWS/Preferences/AWSAttributionDelaySeconds"; constexpr char AWSAttributionLastTimeStampKey[] = "/Amazon/AWS/Preferences/AWSAttributionLastTimeStamp"; - constexpr char AWSAttributionApiId[] = "xbzx78kvbk"; + constexpr char AWSAttributionApiId[] = "2zxvvmv8d7"; constexpr char AWSAttributionChinaApiId[] = ""; constexpr char AWSAttributionApiStage[] = "prod"; + const int AWSAttributionDefaultDelayInDays = 7; AWSAttributionManager::AWSAttributionManager() { @@ -58,12 +62,11 @@ namespace AWSCore { if (ShouldGenerateMetric()) { - // 1. Gather metadata and assemble metric + // Gather metadata and assemble metric AttributionMetric metric; UpdateMetric(metric); - // 2. Identify region and chose attribution endpoint - // 3. Post metric + // Post metric SubmitMetric(metric); } } @@ -104,8 +107,7 @@ namespace AWSCore AZ::u64 delayInSeconds = 0; if (!m_settingsRegistry->Get(delayInSeconds, AWSAttributionDelaySecondsKey)) { - AZ_Warning("AWSAttributionManager", false, "AWSAttribution delay key not found. Defaulting to delay to day"); - delayInSeconds = 86400; + delayInSeconds = 86400 * AWSAttributionDefaultDelayInDays; m_settingsRegistry->Set(AWSAttributionDelaySecondsKey, delayInSeconds); } @@ -243,7 +245,8 @@ namespace AWSCore metric.SetO3DEVersion(engineVersion); AZStd::string platform = this->GetPlatform(); - metric.SetPlatform(platform, ""); + QString productName = QSysInfo::prettyProductName(); + metric.SetPlatform(platform, productName.toStdString().c_str()); AZStd::vector gemNames; GetActiveAWSGems(gemNames); @@ -256,17 +259,21 @@ namespace AWSCore void AWSAttributionManager::SubmitMetric(AttributionMetric& metric) { AWSCore::ServiceAPI::AWSAttributionRequestJob::Config* config = ServiceAPI::AWSAttributionRequestJob::GetDefaultConfig(); + // Identify region and chose attribution endpoint SetApiEndpointAndRegion(config); ServiceAPI::AWSAttributionRequestJob* requestJob = ServiceAPI::AWSAttributionRequestJob::Create( - [this](ServiceAPI::AWSAttributionRequestJob* successJob) + [this]([[maybe_unused]] ServiceAPI::AWSAttributionRequestJob* successJob) { - AZ_UNUSED(successJob); - UpdateLastSend(); AZ_Printf("AWSAttributionManager", "AWSAttribution metric submit success"); - }, {}, config); + }, + [this]([[maybe_unused]] ServiceAPI::AWSAttributionRequestJob* failJob) + { + AZ_Error("AWSAttributionManager", false, "Metrics send error: %s", failJob->error.message.c_str()); + }, + config); requestJob->parameters.metric = metric; requestJob->Start(); diff --git a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionMetric.cpp b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionMetric.cpp index 6ad322995e..683482b8f6 100644 --- a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionMetric.cpp +++ b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionMetric.cpp @@ -19,14 +19,16 @@ namespace AWSCore { + constexpr char AWSAttributionMetricDefaultO3DEVersion[] = "1.1"; + AttributionMetric::AttributionMetric(const AZStd::string& timestamp) - : m_version("1.1") + : m_version(AWSAttributionMetricDefaultO3DEVersion) , m_timestamp(timestamp) { } AttributionMetric::AttributionMetric() - : m_version("1.1") + : m_version(AWSAttributionMetricDefaultO3DEVersion) { m_timestamp = AttributionMetric::GenerateTimeStamp(); } diff --git a/Gems/AWSCore/Code/Tests/Editor/Attribution/AWSCoreAttributionManagerTest.cpp b/Gems/AWSCore/Code/Tests/Editor/Attribution/AWSCoreAttributionManagerTest.cpp index 298c250086..be6a0a5ae8 100644 --- a/Gems/AWSCore/Code/Tests/Editor/Attribution/AWSCoreAttributionManagerTest.cpp +++ b/Gems/AWSCore/Code/Tests/Editor/Attribution/AWSCoreAttributionManagerTest.cpp @@ -32,6 +32,8 @@ #include #include +#include +#include using namespace AWSCore; @@ -405,6 +407,7 @@ namespace AWSAttributionUnitTest AZStd::string serializedMetricValue = metric.SerializeToJson(); ASSERT_TRUE(serializedMetricValue.find("\"o3de_version\":\"1.0.0.0\"") != AZStd::string::npos); ASSERT_TRUE(serializedMetricValue.find(AZ::GetPlatformName(AZ::g_currentPlatform)) != AZStd::string::npos); + ASSERT_TRUE(serializedMetricValue.find(QSysInfo::prettyProductName().toStdString().c_str()) != AZStd::string::npos); ASSERT_TRUE(serializedMetricValue.find("AWSCore.Editor") != AZStd::string::npos); ASSERT_TRUE(serializedMetricValue.find("AWSClientAuth") != AZStd::string::npos); diff --git a/Gems/Atom/Asset/Shader/Code/CMakeLists.txt b/Gems/Atom/Asset/Shader/Code/CMakeLists.txt index dd8afec534..8bc032537d 100644 --- a/Gems/Atom/Asset/Shader/Code/CMakeLists.txt +++ b/Gems/Atom/Asset/Shader/Code/CMakeLists.txt @@ -102,6 +102,11 @@ ly_add_target( 3rdParty::azslc ) +# The Atom_Asset_Shader is a required gem for Builders in order to process the assets that come WITHOUT +# the Atom_Feature_Common required gem +ly_enable_gems(GEMS Atom_Asset_Shader VARIANTS Builders + TARGETS AssetBuilder AssetProcessor AssetProcessorBatch) + ################################################################################ # Tests ################################################################################ diff --git a/Gems/Atom/Bootstrap/Code/CMakeLists.txt b/Gems/Atom/Bootstrap/Code/CMakeLists.txt index 5e5a8c96d9..e2147f0bf3 100644 --- a/Gems/Atom/Bootstrap/Code/CMakeLists.txt +++ b/Gems/Atom/Bootstrap/Code/CMakeLists.txt @@ -37,3 +37,20 @@ ly_add_target( Legacy::CryCommon Gem::Atom_RPI.Public ) + +# Atom_Bootstrap is only used in Launchers +ly_create_alias(NAME Atom_Bootstrap.Clients NAMESPACE Gem TARGETS Gem::Atom_Bootstrap) +ly_create_alias(NAME Atom_Bootstrap.Servers NAMESPACE Gem TARGETS Gem::Atom_Bootstrap) + +# The Atom_Bootstrap gem is responsible for making the NativeWindow handle in the launcher applications +# Loop over each Project name to allow the ${ProjectName}.GameLauncher and ${ProjectName}.ServerLauncher +# target to add the gem the Clients and Servers variant +get_property(LY_PROJECTS_TARGET_NAME GLOBAL PROPERTY LY_PROJECTS_TARGET_NAME) +foreach(project_name IN LISTS LY_PROJECTS_TARGET_NAME) + # Add gem as a dependency of the Clients Launcher + ly_enable_gems(PROJECT_NAME ${project_name} GEMS Atom_Bootstrap VARIANTS Clients TARGETS ${project_name}.GameLauncher) + # Add gem as a dependency of the Servers Launcher + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) + ly_enable_gems(PROJECT_NAME ${project_name} GEMS Atom_Bootstrap VARIANTS Servers TARGETS ${project_name}.ServerLauncher) + endif() +endforeach() diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua index 20d3ee47ae..b90f962f6c 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua @@ -25,8 +25,6 @@ AlphaSource_Packed = 0 AlphaSource_Split = 1 AlphaSource_None = 2 -ForwardPassIndex = 1 - function ConfigureAlphaBlending(shaderItem) shaderItem:GetRenderStatesOverride():SetDepthEnabled(true) shaderItem:GetRenderStatesOverride():SetDepthWriteMask(DepthWriteMask_Zero) @@ -58,15 +56,17 @@ end function Process(context) local opacityMode = context:GetMaterialPropertyValue_enum("opacity.mode") + local forwardPassEDS = context:GetShaderByTag("ForwardPass_EDS") + if(opacityMode == OpacityMode_Blended) then - ConfigureAlphaBlending(context:GetShader(ForwardPassIndex)) - context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent") + ConfigureAlphaBlending(forwardPassEDS) + forwardPassEDS:SetDrawListTagOverride("transparent") elseif(opacityMode == OpacityMode_TintedTransparent) then - ConfigureDualSourceBlending(context:GetShader(ForwardPassIndex)) - context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent") + ConfigureDualSourceBlending(forwardPassEDS) + forwardPassEDS:SetDrawListTagOverride("transparent") else - ResetAlphaBlending(context:GetShader(ForwardPassIndex)) - context:GetShader(ForwardPassIndex):SetDrawListTagOverride("") -- reset to default draw list + ResetAlphaBlending(forwardPassEDS) + forwardPassEDS:SetDrawListTagOverride("") -- reset to default draw list end end diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua index 771726aea7..c42f16c179 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua @@ -49,7 +49,6 @@ function ProcessEditor(context) context:SetMaterialPropertyVisibility("parallax.factor", visibility) context:SetMaterialPropertyVisibility("parallax.offset", visibility) context:SetMaterialPropertyVisibility("parallax.showClipping", visibility) - context:SetMaterialPropertyVisibility("parallax.invert", visibility) context:SetMaterialPropertyVisibility("parallax.algorithm", visibility) context:SetMaterialPropertyVisibility("parallax.quality", visibility) context:SetMaterialPropertyVisibility("parallax.pdo", visibility) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua index b245fde3df..71e5ac7027 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua @@ -74,7 +74,9 @@ function Process(context) shadowMapWithPS:SetEnabled(opacityMode == OpacityMode_Cutout) forwardPass:SetEnabled(opacityMode == OpacityMode_Cutout) - TrySetShaderEnabled(lowEndForwardEDS, (opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent)) + -- Only enable lowEndForwardEDS in Opaque mode, Transparent mode will be handled by forwardPassEDS. The transparent pass uses the "transparent" draw tag + -- for both standard and low end pipelines, so this keeps both shaders from rendering to the transparent draw list. + TrySetShaderEnabled(lowEndForwardEDS, opacityMode == OpacityMode_Opaque) TrySetShaderEnabled(lowEndForward, opacityMode == OpacityMode_Cutout) end diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli index b28f0f1708..26f3c44fb1 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli @@ -15,9 +15,6 @@ #include #include -// The order should match m_pointShadowTransforms in PointLightFeatureProcessor.h/.cpp -static const float3 PointLightShadowCubemapDirections[6] = {float3(-1,0,0), float3(1,0,0), float3(0,-1,0), float3(0,1,0), float3(0,0,-1), float3(0,0,1)}; - int GetPointLightShadowCubemapFace(const float3 targetPos, const float3 lightPos) { const float3 toPoint = targetPos - lightPos; @@ -83,12 +80,13 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD { const int shadowCubemapFace = GetPointLightShadowCubemapFace(surface.position, light.m_position); const int shadowIndex = UnpackPointLightShadowIndex(light, shadowCubemapFace); - + const float3 lightDir = normalize(light.m_position - surface.position); + litRatio *= ProjectedShadow::GetVisibility( shadowIndex, light.m_position, surface.position, - PointLightShadowCubemapDirections[shadowCubemapFace], + lightDir, surface.normal); // Use backShadowRatio to carry thickness from shadow map for thick mode diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli index e4cb87802a..b8e5c485aa 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli @@ -226,7 +226,7 @@ float ProjectedShadow::GetVisibilityEsm() } const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize; - const Texture2DArray expShadowmap = PassSrg::m_projectedExponentialShadowmap; + const Texture2DArray shadowmap = PassSrg::m_projectedExponentialShadowmap; if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin && m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin) @@ -243,10 +243,12 @@ float ProjectedShadow::GetVisibilityEsm() const float depth = PerspectiveDepthToLinear( m_shadowPosition.z, coefficients); - const float expDepthInShadowmap = expShadowmap.Sample( + const float occluder = shadowmap.Sample( PassSrg::LinearSampler, float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r; - const float ratio = exp(-EsmExponentialShift * depth) * expDepthInShadowmap; + + const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder); + const float ratio = exp(exponent); // pow() mitigates light bleeding to shadows from near shadow casters. return saturate( pow(ratio, 8) ); } @@ -265,7 +267,7 @@ float ProjectedShadow::GetVisibilityEsmPcf() } const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize; - const Texture2DArray expShadowmap = PassSrg::m_projectedExponentialShadowmap; + const Texture2DArray shadowmap = PassSrg::m_projectedExponentialShadowmap; if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin && m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin) @@ -282,10 +284,12 @@ float ProjectedShadow::GetVisibilityEsmPcf() const float depth = PerspectiveDepthToLinear( m_shadowPosition.z, coefficients); - const float expDepthInShadowmap = expShadowmap.Sample( + const float occluder = shadowmap.Sample( PassSrg::LinearSampler, float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r; - float ratio = exp(-EsmExponentialShift * depth) * expDepthInShadowmap; + + const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder); + float ratio = exp(exponent); static const float pcfFallbackThreshold = 1.04; if (ratio > pcfFallbackThreshold) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/Shadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/Shadow.azsli index d267a74b36..138ea38562 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/Shadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/Shadow.azsli @@ -79,9 +79,9 @@ float4 Shadow::GetJitterUnitVectorDepthDiffBase( return float4(0., 0., 0., 0.); } const float3 v_M = v_M0 / v_M0_length; - const float cosTheta = dot(normalVector, v_M); + const float cosTheta = saturate(dot(normalVector, v_M)); const float sinTheta = sqrt(1 - cosTheta * cosTheta); - if (sinTheta == 0.) + if (sinTheta < 0.001) { return float4(0., 0., 0., 0.); } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli index 7a51d4c629..37b021e148 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli @@ -92,6 +92,8 @@ partial ShaderResourceGroup ViewSrg uint m_filteringSampleCount; float2 m_unprojectConstants; float m_bias; + float m_esmExponent; + float3 m_padding; }; StructuredBuffer m_projectedShadows; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.azsl index bea63c6b0b..5012f85c54 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/DepthExponentiation.azsl @@ -56,7 +56,6 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID) return; // Early return if filter is disabled. } - float depth = 0.; switch (o_shadowmapLightType) { case ShadowmapLightType::Directional: @@ -68,9 +67,15 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID) // and it often causes light bleeding with ESM. // So this converts it to "depth" to emphasize the difference // within the frustum. - depth = (depthInClip - distanceMin) / (1. - distanceMin); - } + const float depth = (depthInClip - distanceMin) / (1. - distanceMin); + + // Todo: Expose Esm exponent slider for directional lights + // This would remove the exp calculation below, collapsing it into a subtraction in DirectionalLightShadow.azsli + // ATOM-15775 + const float outValue = exp(EsmExponentialShift * depth); + PassSrg::m_outputShadowmap[dispatchId].r = outValue; break; + } case ShadowmapLightType::Spot: { const float3 coefficients = float3( @@ -84,12 +89,9 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID) // and it often causes light bleeding with ESM. // So this converts it to a linear depth to emphasize the // difference like a orthogonal depth. - depth = PerspectiveDepthToLinear(depthInClip, coefficients); - } + PassSrg::m_outputShadowmap[dispatchId].r = PerspectiveDepthToLinear(depthInClip, coefficients); break; + } } - - const float outValue = exp(EsmExponentialShift * depth); - PassSrg::m_outputShadowmap[dispatchId].r = outValue; } diff --git a/Gems/Atom/Feature/Common/Code/CMakeLists.txt b/Gems/Atom/Feature/Common/Code/CMakeLists.txt index 6f087edefe..da092c3f8a 100644 --- a/Gems/Atom/Feature/Common/Code/CMakeLists.txt +++ b/Gems/Atom/Feature/Common/Code/CMakeLists.txt @@ -76,6 +76,8 @@ ly_add_target( FILES_CMAKE atom_feature_common_shared_files.cmake ../Assets/atom_feature_common_asset_files.cmake + PLATFORM_INCLUDE_FILES + ${pal_source_dir}/runtime_dependencies_clients.cmake INCLUDE_DIRECTORIES PRIVATE Source @@ -99,6 +101,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) NAMESPACE Gem FILES_CMAKE atom_feature_common_editor_files.cmake + PLATFORM_INCLUDE_FILES + ${pal_source_dir}/runtime_dependencies_tools.cmake INCLUDE_DIRECTORIES PRIVATE . @@ -130,12 +134,16 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) NAMESPACE Gem FILES_CMAKE atom_feature_common_builders_files.cmake + PLATFORM_INCLUDE_FILES + ${pal_source_dir}/runtime_dependencies_tools.cmake INCLUDE_DIRECTORIES PRIVATE Source/Builders BUILD_DEPENDENCIES PRIVATE AZ::AzCore + RUNTIME_DEPENDENCIES + Gem::Atom_RHI.Private ) endif() diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h index ce911fecf7..fc261fb57b 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h @@ -100,10 +100,13 @@ namespace AZ virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0; //! Sets the shadowmap Pcf (percentage closer filtering) method. virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0; + //! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow. + virtual void SetEsmExponent(LightHandle handle, float exponent) = 0; //! Sets all of the the disk data for the provided LightHandle. virtual void SetDiskData(LightHandle handle, const DiskLightData& data) = 0; - + + }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h index 30d88cb839..c781030220 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h @@ -82,6 +82,8 @@ namespace AZ virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0; //! Sets the shadowmap Pcf (percentage closer filtering) method. virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0; + //! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow. + virtual void SetEsmExponent(LightHandle handle, float exponent) = 0; //! Sets all of the the point data for the provided LightHandle. virtual void SetPointData(LightHandle handle, const PointLightData& data) = 0; }; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp index 9fca9b512b..5c686b492c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp @@ -343,6 +343,11 @@ namespace AZ SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method); } + void DiskLightFeatureProcessor::SetEsmExponent(LightHandle handle, float exponent) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, exponent); + } + void DiskLightFeatureProcessor::UpdateShadow(LightHandle handle) { const DiskLightData& diskLight = m_diskLightData.GetData(handle.GetIndex()); diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h index 8391506f63..1147272204 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h @@ -60,6 +60,7 @@ namespace AZ void SetPredictionSampleCount(LightHandle handle, uint16_t count) override; void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; void SetPcfMethod(LightHandle handle, PcfMethod method) override; + void SetEsmExponent(LightHandle handle, float esmExponent) override; void SetDiskData(LightHandle handle, const DiskLightData& data) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingTilePreparePass.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingTilePreparePass.cpp index 4f2a4f0346..7742036171 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingTilePreparePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingTilePreparePass.cpp @@ -192,9 +192,7 @@ namespace AZ OnShaderReloaded(); } - void LightCullingTilePreparePass::OnShaderVariantReinitialized( - const AZ::RPI::Shader&, const AZ::RPI::ShaderVariantId&, - AZ::RPI::ShaderVariantStableId) + void LightCullingTilePreparePass::OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant&) { OnShaderReloaded(); } diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingTilePreparePass.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingTilePreparePass.h index 0febb66e3d..674f5d9914 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingTilePreparePass.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/LightCullingTilePreparePass.h @@ -56,7 +56,7 @@ namespace AZ // ShaderReloadNotificationBus overrides... void OnShaderReinitialized(const AZ::RPI::Shader& shader) override; void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override; - void OnShaderVariantReinitialized(const AZ::RPI::Shader& shader, const AZ::RPI::ShaderVariantId& shaderVariantId, AZ::RPI::ShaderVariantStableId shaderVariantStableId) override; + void OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant& shaderVariant) override; // Scope producer functions... void CompileResources(const RHI::FrameGraphCompileContext& context) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp index ef5d7f0d03..21a62b9e84 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp @@ -312,5 +312,10 @@ namespace AZ SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method); } + void PointLightFeatureProcessor::SetEsmExponent(LightHandle handle, float esmExponent) + { + SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, esmExponent); + } + } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h index c0c377e960..897bf6dc3e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h @@ -57,6 +57,7 @@ namespace AZ void SetPredictionSampleCount(LightHandle handle, uint16_t count) override; void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; void SetPcfMethod(LightHandle handle, PcfMethod method) override; + void SetEsmExponent(LightHandle handle, float esmExponent) override; void SetPointData(LightHandle handle, const PointLightData& data) override; const Data::Instance GetLightBuffer() const; diff --git a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp index ae48c7defb..32d93a3f03 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp @@ -50,7 +50,18 @@ namespace AZ if (auto behaviorContext = azrtti_cast(context)) { - behaviorContext->Class("OutputDeviceTransformType"); + behaviorContext->Class("OutputDeviceTransformType") + ->Enum("OutputDeviceTransformType_48Nits") + ->Attribute(AZ::Script::Attributes::Module, "atom") + ->Enum("OutputDeviceTransformType_100Nits") + ->Attribute(AZ::Script::Attributes::Module, "atom") + ->Enum("OutputDeviceTransformType_2000Nits") + ->Attribute(AZ::Script::Attributes::Module, "atom") + ->Enum("OutputDeviceTransformType_4000Nits") + ->Attribute(AZ::Script::Attributes::Module, "atom") + ->Enum("OutputDeviceTransformType_NumOutputDeviceTransformTypes") + ->Attribute(AZ::Script::Attributes::Module, "atom") + ; behaviorContext->Class("AcesParameterOverrides") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) diff --git a/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.cpp b/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.cpp index 4373f66bd0..8fe271b1c1 100644 --- a/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.cpp @@ -194,7 +194,7 @@ namespace AZ } } - void MorphTargetDispatchItem::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset& shaderAsset) + void MorphTargetDispatchItem::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset& shaderAsset) { if (!Init()) { @@ -202,7 +202,7 @@ namespace AZ } } - void MorphTargetDispatchItem::OnShaderVariantReinitialized([[maybe_unused]] const RPI::Shader& shader, [[maybe_unused]] const RPI::ShaderVariantId& shaderVariantId, [[maybe_unused]] RPI::ShaderVariantStableId shaderVariantStableId) + void MorphTargetDispatchItem::OnShaderVariantReinitialized(const RPI::ShaderVariant&) { if (!Init()) { diff --git a/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.h b/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.h index ad1fd969a5..e7d78caf5f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.h +++ b/Gems/Atom/Feature/Common/Code/Source/MorphTargets/MorphTargetDispatchItem.h @@ -72,8 +72,8 @@ namespace AZ // ShaderInstanceNotificationBus::Handler overrides void OnShaderReinitialized(const RPI::Shader& shader) override; - void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override; - void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override; + void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override; + void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override; RHI::DispatchItem m_dispatchItem; diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_clients.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_clients.cmake new file mode 100644 index 0000000000..31c0cab74b --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_clients.cmake @@ -0,0 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Vulkan.Private +) diff --git a/Gems/PhysicsEntities/CMakeLists.txt b/Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_tools.cmake similarity index 94% rename from Gems/PhysicsEntities/CMakeLists.txt rename to Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_tools.cmake index 4d5680a30d..99eec9a733 100644 --- a/Gems/PhysicsEntities/CMakeLists.txt +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Android/runtime_dependencies_tools.cmake @@ -8,3 +8,6 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # + +set(LY_RUNTIME_DEPENDENCIES +) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_clients.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_clients.cmake new file mode 100644 index 0000000000..31c0cab74b --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_clients.cmake @@ -0,0 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Vulkan.Private +) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_tools.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_tools.cmake new file mode 100644 index 0000000000..c76527afa0 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Linux/runtime_dependencies_tools.cmake @@ -0,0 +1,19 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Vulkan.Private + Gem::Atom_RHI_DX12.Private + Gem::Atom_RHI_Metal.Private + Gem::Atom_RHI_Vulkan.Builders + Gem::Atom_RHI_DX12.Builders + Gem::Atom_RHI_Metal.Builders +) diff --git a/Gems/Atom/Feature/Common/Code/Platform/Common/atom_feature_common_clang.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_clients.cmake similarity index 89% rename from Gems/Atom/Feature/Common/Code/Platform/Common/atom_feature_common_clang.cmake rename to Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_clients.cmake index 5963f882c3..a0aa67c703 100644 --- a/Gems/Atom/Feature/Common/Code/Platform/Common/atom_feature_common_clang.cmake +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_clients.cmake @@ -9,7 +9,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -set(LY_COMPILE_OPTIONS - PRIVATE - -fexceptions +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Metal.Private ) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_tools.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_tools.cmake new file mode 100644 index 0000000000..81046d3071 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Mac/runtime_dependencies_tools.cmake @@ -0,0 +1,19 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Metal.Private + Gem::Atom_RHI_Vulkan.Private + Gem::Atom_RHI_DX12.Private + Gem::Atom_RHI_Metal.Builders + Gem::Atom_RHI_Vulkan.Builders + Gem::Atom_RHI_DX12.Builders +) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_clients.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_clients.cmake new file mode 100644 index 0000000000..dfd0319c05 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_clients.cmake @@ -0,0 +1,16 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Vulkan.Private + Gem::Atom_RHI_DX12.Private + Gem::Atom_RHI_Null.Private +) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_tools.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_tools.cmake new file mode 100644 index 0000000000..c76527afa0 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/Windows/runtime_dependencies_tools.cmake @@ -0,0 +1,19 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Vulkan.Private + Gem::Atom_RHI_DX12.Private + Gem::Atom_RHI_Metal.Private + Gem::Atom_RHI_Vulkan.Builders + Gem::Atom_RHI_DX12.Builders + Gem::Atom_RHI_Metal.Builders +) diff --git a/Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_clients.cmake b/Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_clients.cmake new file mode 100644 index 0000000000..a0aa67c703 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_clients.cmake @@ -0,0 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(LY_RUNTIME_DEPENDENCIES + Gem::Atom_RHI_Metal.Private +) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/__init__.py b/Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_tools.cmake old mode 100755 new mode 100644 similarity index 94% rename from AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/__init__.py rename to Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_tools.cmake index a6510a297f..99eec9a733 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/auxiliary_content_tests/__init__.py +++ b/Gems/Atom/Feature/Common/Code/Source/Platform/iOS/runtime_dependencies_tools.cmake @@ -7,4 +7,7 @@ # or, if provided, by the license below or the license accompanying this file. Do not # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# \ No newline at end of file +# + +set(LY_RUNTIME_DEPENDENCIES +) diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index 9cc98a15ec..4fa466589c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -458,9 +458,13 @@ namespace AZ bool ProfilingCaptureSystemComponent::CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath) { // Start the cpu profiling - RHI::CpuProfiler::Get()->SetProfilerEnabled(true); + bool wasEnabled = RHI::CpuProfiler::Get()->IsProfilerEnabled(); + if (!wasEnabled) + { + RHI::CpuProfiler::Get()->SetProfilerEnabled(true); + } - const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath]() + const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath, wasEnabled]() { JsonSerializerSettings serializationSettings; serializationSettings.m_keepDefaults = true; @@ -481,14 +485,22 @@ namespace AZ saveResult.GetError().c_str()); AZ_Warning("ProfilingCaptureSystemComponent", false, captureInfo.c_str()); } + else + { + AZ_Printf("ProfilingCaptureSystemComponent", "Cpu profiling statistics was saved to file [%s]\n", outputFilePath.c_str()); + } // Disable the profiler again - RHI::CpuProfiler::Get()->SetProfilerEnabled(false); + if (!wasEnabled) + { + RHI::CpuProfiler::Get()->SetProfilerEnabled(false); + } // Notify listeners that the pass' PipelineStatistics queries capture has finished. ProfilingCaptureNotificationBus::Broadcast(&ProfilingCaptureNotificationBus::Events::OnCaptureCpuProfilingStatisticsFinished, saveResult.IsSuccess(), captureInfo); + }); // Start the TickBus. diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.cpp index 158cf795ad..016270eb80 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.cpp @@ -353,9 +353,9 @@ namespace AZ Init(); } - void RayTracingPass::OnShaderVariantReinitialized([[maybe_unused]] const RPI::Shader& shader, [[maybe_unused]] const RPI::ShaderVariantId& shaderVariantId, [[maybe_unused]] RPI::ShaderVariantStableId shaderVariantStableId) + void RayTracingPass::OnShaderVariantReinitialized(const RPI::ShaderVariant&) { Init(); } - } // namespace RPI + } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.h index 6ad082e894..92da052d09 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.h @@ -53,7 +53,7 @@ namespace AZ // ShaderReloadNotificationBus::Handler overrides void OnShaderReinitialized(const RPI::Shader& shader) override; void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override; - void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override; + void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override; // load the raytracing shaders and setup pipeline states void Init(); diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp index a2d1491cad..b1f3a04d77 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp @@ -162,12 +162,21 @@ namespace AZ::Render void ProjectedShadowFeatureProcessor::SetPcfMethod(ShadowId id, PcfMethod method) { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetPcfMethod()."); ShadowData& shadowData = m_shadowData.GetElement(id.GetIndex()); shadowData.m_pcfMethod = method; m_deviceBufferNeedsUpdate = true; } + void ProjectedShadowFeatureProcessor::SetEsmExponent(ShadowId id, float exponent) + { + AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetEsmExponent()."); + ShadowData& shadowData = m_shadowData.GetElement(id.GetIndex()); + shadowData.m_esmExponent = exponent; + m_deviceBufferNeedsUpdate = true; + } + void ProjectedShadowFeatureProcessor::SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) { AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowFilterMethod()."); diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h index a131c914f2..bf03e490a6 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h @@ -52,6 +52,7 @@ namespace AZ::Render void SetFieldOfViewY(ShadowId id, float fieldOfViewYRadians) override; void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) override; void SetPcfMethod(ShadowId id, PcfMethod method); + void SetEsmExponent(ShadowId id, float exponent); void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) override; void SetPredictionSampleCount(ShadowId id, uint16_t count) override; @@ -73,6 +74,8 @@ namespace AZ::Render uint32_t m_filteringSampleCount = 0; AZStd::array m_unprojectConstants = { {0, 0} }; float m_bias; + float m_esmExponent = 87.0f; + float m_padding[3]; }; // CPU data used for constructing & updating ShadowData diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshComputePass.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshComputePass.cpp index a3feddb0b6..b0d08314b1 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshComputePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshComputePass.cpp @@ -65,9 +65,13 @@ namespace AZ } } - void SkinnedMeshComputePass::OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId&, RPI::ShaderVariantStableId) + void SkinnedMeshComputePass::OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) { - OnShaderReinitialized(shader); + ComputePass::OnShaderVariantReinitialized(shaderVariant); + if (m_skinnedMeshFeatureProcessor) + { + m_skinnedMeshFeatureProcessor->OnSkinningShaderReinitialized(m_shader); + } } } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshComputePass.h b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshComputePass.h index 5f7ff08e47..dbd8704c54 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshComputePass.h +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshComputePass.h @@ -44,7 +44,7 @@ namespace AZ // ShaderReloadNotificationBus::Handler overrides... void OnShaderReinitialized(const RPI::Shader& shader) override; - void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override; + void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override; SkinnedMeshFeatureProcessor* m_skinnedMeshFeatureProcessor = nullptr; }; diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshRenderProxy.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshRenderProxy.cpp index 090b720406..0832bd0a25 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshRenderProxy.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshRenderProxy.cpp @@ -134,7 +134,10 @@ namespace AZ void SkinnedMeshRenderProxy::SetSkinningMatrices(const AZStd::vector& data) { - WriteToBuffer(m_boneTransforms->GetRHIBuffer(), data); + if (m_boneTransforms) + { + WriteToBuffer(m_boneTransforms->GetRHIBuffer(), data); + } } void SkinnedMeshRenderProxy::SetMorphTargetWeights(uint32_t lodIndex, const AZStd::vector& weights) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h index cf3a31adf6..b5c8f144ba 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfiler.h @@ -12,6 +12,7 @@ #pragma once +#include #include #include #include @@ -87,6 +88,8 @@ namespace AZ //! Enable/Disable the CpuProfiler virtual void SetProfilerEnabled(bool enabled) = 0; + + virtual bool IsProfilerEnabled() const = 0 ; }; } // namespace RPI diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h index 30523194b6..9685f9be98 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/CpuProfilerImpl.h @@ -102,6 +102,7 @@ namespace AZ void EndTimeRegion() final; void FlushTimeRegionMap(TimeRegionMap& timeRegionMap) final; void SetProfilerEnabled(bool enabled) final; + bool IsProfilerEnabled() const final; private: // Lazily create and register the local thread data diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/MemorySubAllocator.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/MemorySubAllocator.h index 47abf5409d..75fd3035bf 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/MemorySubAllocator.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/MemorySubAllocator.h @@ -11,6 +11,7 @@ */ #pragma once +#include #include #include #include @@ -160,6 +161,7 @@ namespace AZ template void MemorySubAllocator::GarbageCollect() { + AZ_ATOM_PROFILE_FUNCTION("RHI", "MemorySubAllocator: GarbageCollect"); for (PageContext& pageContext : m_pageContexts) { pageContext.m_allocator.GarbageCollect(); diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h index 98d63accc9..a3a07c1533 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h @@ -11,6 +11,7 @@ */ #pragma once +#include #include #include #include @@ -169,6 +170,7 @@ namespace AZ template void ObjectCollector::Collect(bool forceFlush) { + AZ_ATOM_PROFILE_FUNCTION("DX12", "ObjectCollector: Collect"); m_mutex.lock(); if (m_pendingObjects.size()) { diff --git a/Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp b/Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp index 700d09d7bf..57a2b541f1 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp @@ -11,6 +11,7 @@ */ #include +#include #include namespace AZ @@ -86,6 +87,7 @@ namespace AZ void CommandQueue::FlushCommands() { + AZ_ATOM_PROFILE_FUNCTION("RHI", "CommandQueue: FlushCommands"); while (!m_isWorkQueueEmpty && !m_isQuitting) { AZStd::this_thread::yield(); diff --git a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp index 8242c89886..9b77e7566f 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp @@ -186,6 +186,12 @@ namespace AZ } } + bool CpuProfilerImpl::IsProfilerEnabled() const + { + return m_enabled; + } + + void CpuProfilerImpl::RegisterThreadStorage() { AZStd::unique_lock lock(m_threadRegisterMutex); diff --git a/Gems/Atom/RHI/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/Code/Source/RHI/Device.cpp index 4c54ce3237..7b7dc2de8c 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/Device.cpp @@ -10,6 +10,7 @@ * */ +#include #include #include @@ -151,6 +152,7 @@ namespace AZ { if (ValidateIsInitialized() && ValidateIsInFrame()) { + AZ_ATOM_PROFILE_FUNCTION("RHI", "Device: EndFrame"); EndFrameInternal(); m_isInFrame = false; return ResultCode::Success; @@ -172,6 +174,7 @@ namespace AZ { if (ValidateIsInitialized() && ValidateIsNotInFrame()) { + AZ_ATOM_PROFILE_FUNCTION("RHI", "Device: CompileMemoryStatistics"); MemoryStatisticsBuilder builder; builder.Begin(memoryStatistics, reportFlags); CompileMemoryStatisticsInternal(builder); diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp index 767ab83c47..1788d0e85c 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp @@ -9,18 +9,19 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include -#include #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include +#include #include +#include #include +#include +#include #include #include @@ -76,6 +77,7 @@ namespace AZ void FrameGraph::Clear() { + AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameGraph: Clear"); for (Scope* scope : m_scopes) { scope->Deactivate(); diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp index dff49a9086..06c8791655 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp @@ -9,10 +9,11 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include #include -#include +#include #include +#include +#include #include #include @@ -80,7 +81,7 @@ namespace AZ void FrameGraphExecuter::End() { - AZ_TRACE_METHOD(); + AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameGraphExecuter: End"); AZ_Assert(m_pendingGroups.empty(), "Pending contexts in queue."); m_groups.clear(); EndInternal(); diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp index 67cad6c4dc..cf8f3aa2ed 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp @@ -181,7 +181,10 @@ namespace AZ m_compileRequest = compileRequest; - FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompile); + { + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "FrameScheduler: Compile: OnFrameCompile"); + FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompile); + } FrameGraphCompileRequest frameGraphCompileRequest; frameGraphCompileRequest.m_frameGraph = m_frameGraph.get(); @@ -193,7 +196,10 @@ namespace AZ const MessageOutcome outcome = m_frameGraphCompiler->Compile(frameGraphCompileRequest); if (outcome.IsSuccess()) { - FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompileEnd, *m_frameGraph); + { + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "FrameScheduler: Compile: OnFrameCompileEnd"); + FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompileEnd, *m_frameGraph); + } FrameGraphLogger::Log(*m_frameGraph, compileRequest.m_logVerbosity); @@ -400,7 +406,11 @@ namespace AZ m_scopeProducers.clear(); m_scopeProducerLookup.clear(); - FrameEventBus::Event(m_device, &FrameEventBus::Events::OnFrameEnd); + + { + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "FrameScheduler: EndFrame: OnFrameEnd"); + FrameEventBus::Event(m_device, &FrameEventBus::Events::OnFrameEnd); + } const AZStd::sys_time_t timeNowTicks = AZStd::GetTimeNowTicks(); m_cpuTimingStatistics.m_frameToFrameTime = timeNowTicks - m_lastFrameEndTime; diff --git a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp index 81409e2c18..16ddc8599d 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp @@ -10,6 +10,7 @@ * */ +#include #include #include #include @@ -213,6 +214,7 @@ namespace AZ void RHISystem::FrameUpdate(FrameGraphCallback frameGraphCallback) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender); + AZ_ATOM_PROFILE_FUNCTION("RHI", "RHISystem: FrameUpdate"); { AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzRender, "main per-frame work"); @@ -224,8 +226,11 @@ namespace AZ * This exists as a hook to enable RHI sample tests, which are allowed to queue their * own RHI scopes to the frame scheduler. This happens prior to the RPI pass graph registration. */ - RHISystemNotificationBus::Broadcast(&RHISystemNotificationBus::Events::OnFramePrepare, m_frameScheduler); - + { + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "RHISystem :FrameUpdate: OnFramePrepare"); + RHISystemNotificationBus::Broadcast(&RHISystemNotificationBus::Events::OnFramePrepare, m_frameScheduler); + } + RHI::MessageOutcome outcome = m_frameScheduler.Compile(m_compileRequest); if (outcome.IsSuccess()) { diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandListPool.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandListPool.cpp index d43129a626..5510b4e924 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandListPool.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandListPool.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include namespace AZ @@ -179,6 +180,7 @@ namespace AZ void CommandListAllocator::Collect() { + AZ_ATOM_PROFILE_FUNCTION("DX12", "CommandListAllocator: Collect"); for (uint32_t queueIdx = 0; queueIdx < RHI::HardwareQueueClassCount; ++queueIdx) { m_commandListSubAllocators[queueIdx].ForEach([](Internal::CommandListSubAllocator& commandListSubAllocator) diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp index a31e105b19..5bf0a84700 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp @@ -137,6 +137,7 @@ namespace AZ void CommandQueueContext::End() { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender); + AZ_ATOM_PROFILE_FUNCTION("DX12", "CommandQueueContext: End"); QueueGpuSignals(m_frameFences[m_currentFrameIndex]); @@ -150,7 +151,7 @@ namespace AZ { AZ_PROFILE_SCOPE_IDLE(AZ::Debug::ProfileCategory::AzRender, "Wait and Reset Fence"); - AZ_ATOM_PROFILE_FUNCTION("RHI", "CommandQueueContext: Wait on Fences"); + AZ_ATOM_PROFILE_TIME_GROUP_REGION("DX12", "CommandQueueContext: Wait on Fences"); FenceEvent event("FrameFence"); m_frameFences[m_currentFrameIndex].Wait(event); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/DescriptorContext.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/DescriptorContext.cpp index e11817a7d8..f83f169f2f 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/DescriptorContext.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/DescriptorContext.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace AZ @@ -345,6 +346,7 @@ namespace AZ void DescriptorContext::GarbageCollect() { + AZ_ATOM_PROFILE_FUNCTION("DX12", "DescriptorContext: GarbageCollect"); for (const auto& itr : m_platformLimitsDescriptor->m_descriptorHeapLimits) { for (uint32_t shaderVisibleIdx = 0; shaderVisibleIdx < PlatformLimitsDescriptor::NumHeapFlags; ++shaderVisibleIdx) diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/StagingMemoryAllocator.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/StagingMemoryAllocator.cpp index 47ae24f487..df5fc53468 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/StagingMemoryAllocator.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/StagingMemoryAllocator.cpp @@ -60,6 +60,7 @@ namespace AZ void StagingMemoryAllocator::GarbageCollect() { + AZ_ATOM_PROFILE_FUNCTION("DX12", "StagingMemoryAllocator: GarbageCollect"); m_mediumBlockAllocators.ForEach([](MemoryLinearSubAllocator& subAllocator) { subAllocator.GarbageCollect(); diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp index c4666578a7..600ef4bce5 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp @@ -417,7 +417,7 @@ namespace AZ AZ::IO::FileIOStream sourceMtlfileStream(inputMetalFile.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary); if (!sourceMtlfileStream.IsOpen()) { - AZ_Error(platformName, false, "Failed because the shader file \"%s\" could not be opened", inputMetalFile); + AZ_Error(platformName, false, "Failed because the shader file \"%s\" could not be opened", inputMetalFile.c_str()); return false; } diff --git a/Gems/Atom/RPI/Code/CMakeLists.txt b/Gems/Atom/RPI/Code/CMakeLists.txt index 8a2684347e..bd2af88816 100644 --- a/Gems/Atom/RPI/Code/CMakeLists.txt +++ b/Gems/Atom/RPI/Code/CMakeLists.txt @@ -66,6 +66,8 @@ ly_add_target( Gem::Atom_RPI.Public Gem::Atom_RHI.Public Gem::Atom_RHI.Reflect + RUNTIME_DEPENDENCIES + Gem::Atom_RHI.Private ) if(PAL_TRAIT_BUILD_HOST_TOOLS) @@ -129,6 +131,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) Gem::Atom_RPI.Editor.Static Gem::Atom_RPI.Edit Gem::Atom_RPI.Public + RUNTIME_DEPENDENCIES + Gem::Atom_RHI.Private ) endif() diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AssetInitBus.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AssetInitBus.h new file mode 100644 index 0000000000..e8a1d69ece --- /dev/null +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AssetInitBus.h @@ -0,0 +1,43 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +namespace AZ +{ + namespace RPI + { + //! Bus for post-load initialization of assets. + //! Assets that need to do post-load initialization should connect to this bus in their asset handler's LoadAssetData() function. + //! Be sure to disconnect from this bus as soon as initialization is complete, as it will be called every frame. + //! (Note this bus is needed rather than utilizing TickBus because TickBus is not protected by a mutex which means it can't be + //! connected on an asset load job thread). + class AssetInitEvents + : public EBusTraits + { + public: + // EBus Configuration + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + typedef AZStd::recursive_mutex MutexType; + + //! This function is called every frame on the main thread to perform any necessary post-load initialization. + //! Connect to the bus after loading the asset data, and disconnect when initialization is complete. + //! @return whether initialization was successful + virtual bool PostLoadInit() = 0; + }; + + using AssetInitBus = AZ::EBus; + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/Material.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/Material.h index d93f7acc85..fa1bb57166 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/Material.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/Material.h @@ -145,7 +145,7 @@ namespace AZ // ShaderReloadNotificationBus overrides... void OnShaderReinitialized(const Shader& shader) override; void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override; - void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override; + void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override; /////////////////////////////////////////////////////////////////// template diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/MaterialReloadNotificationBus.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/MaterialReloadNotificationBus.h index c28f6a3233..d62acab369 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/MaterialReloadNotificationBus.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/MaterialReloadNotificationBus.h @@ -24,6 +24,11 @@ namespace AZ //! Connect to this EBus to get notifications whenever material objects reload. //! The bus address is the AssetId of the MaterialAsset or MaterialTypeAsset. + //! + //! Be careful when using the parameters provided by these functions. The bus ID is an AssetId, and it's possible for the system to have + //! both *old* versions and *new reloaded* versions of the asset in memory at the same time, and they will have the same AssetId. Therefore + //! your bus Handlers could receive Reinitialized messages from multiple sources. It may be necessary to check the memory addresses of these + //! parameters against local members before using this data. class MaterialReloadNotifications : public EBusTraits { diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ComputePass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ComputePass.h index a4130deed1..450a9ce834 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ComputePass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ComputePass.h @@ -78,7 +78,7 @@ namespace AZ // ShaderReloadNotificationBus::Handler overrides... void OnShaderReinitialized(const Shader& shader) override; void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override; - void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override; + void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override; void LoadShader(); PassDescriptor m_passDescriptor; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/FullscreenTrianglePass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/FullscreenTrianglePass.h index 616fc4639a..e168a07f08 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/FullscreenTrianglePass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/FullscreenTrianglePass.h @@ -78,7 +78,7 @@ namespace AZ // ShaderReloadNotificationBus overrides... void OnShaderReinitialized(const Shader& shader) override; void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override; - void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override; + void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override; /////////////////////////////////////////////////////////////////// void LoadShader(); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/PipelineState.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/PipelineState.h index f0fa39d20f..815fc28cb6 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/PipelineState.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/PipelineState.h @@ -88,7 +88,7 @@ namespace AZ // ShaderReloadNotificationBus overrides... void OnShaderReinitialized(const AZ::RPI::Shader& shader) override; void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override; - void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override; + void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override; /////////////////////////////////////////////////////////////////// // Update shader variant from m_shader. It's called whenever shader, shader asset or shader variant were changed. diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/Shader.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/Shader.h index 938c8c06b1..c31f6b41b0 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/Shader.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/Shader.h @@ -12,6 +12,7 @@ #pragma once #include +#include #include #include @@ -57,6 +58,7 @@ namespace AZ : public Data::InstanceData , public Data::AssetBus::Handler , public ShaderVariantFinderNotificationBus::Handler + , public ShaderReloadNotificationBus::Handler { friend class ShaderSystem; public: @@ -162,6 +164,15 @@ namespace AZ void OnShaderVariantTreeAssetReady(Data::Asset /*shaderVariantTreeAsset*/, bool /*isError*/) override {}; void OnShaderVariantAssetReady(Data::Asset shaderVariantAsset, bool IsError) override; /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // ShaderReloadNotificationBus overrides... + void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override; + // Note we don't need OnShaderVariantReinitialized because the Shader class doesn't do anything with the data inside + // the ShaderVariant object. The only thing we might want to do is propagate the message upward, but that's unnecessary + // because the ShaderReloadNotificationBus uses the Shader's AssetId as the ID for all messages including those from the variants. + // And of course we don't need to handle OnShaderReinitialized because this *is* this Shader. + /////////////////////////////////////////////////////////////////// //! Returns the path to the pipeline library cache file. AZStd::string GetPipelineLibraryPath() const; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h index 769ada0293..46d8058b92 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h @@ -22,10 +22,16 @@ namespace AZ { class Shader; class ShaderAsset; + class ShaderVariant; /** - * Connect to this EBus to get notifications whenever a Data::Instance reloads its ShaderAsset. - * The bus address is the AssetId of the ShaderAsset. + * Connect to this EBus to get notifications whenever a shader system class reinitializes itself. + * The bus address is the AssetId of the ShaderAsset, even when the thing being reinitialized is a ShaderVariant or other shader related class. + * + * Be careful when using the parameters provided by these functions. The bus ID is an AssetId, and it's possible for the system to have + * both *old* versions and *new reloaded* versions of the asset in memory at the same time, and they will have the same AssetId. Therefore + * your bus Handlers could receive Reinitialized messages from multiple sources. It may be necessary to check the memory addresses of these + * parameters against local members before using this data. */ class ShaderReloadNotifications : public EBusTraits @@ -35,7 +41,7 @@ namespace AZ ////////////////////////////////////////////////////////////////////////// // EBusTraits overrides static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; - typedef Data::AssetId BusIdType; + typedef Data::AssetId BusIdType; ////////////////////////////////////////////////////////////////////////// virtual ~ShaderReloadNotifications() {} @@ -47,9 +53,7 @@ namespace AZ virtual void OnShaderReinitialized(const Shader& shader) { AZ_UNUSED(shader); } //! Called when a particular shader variant is reinitialized. - virtual void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) - { AZ_UNUSED(shader); AZ_UNUSED(shaderVariantId); AZ_UNUSED(shaderVariantStableId) } - }; + virtual void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) { AZ_UNUSED(shaderVariant); } }; typedef EBus ShaderReloadNotificationBus; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderVariant.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderVariant.h index bd02d03787..b21423e7fc 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderVariant.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderVariant.h @@ -23,10 +23,12 @@ namespace AZ //! the RHI::PipelineStateType of the parent Shader instance. For shaders on the raster //! pipeline, the RHI::DrawFilterTag is also provided. class ShaderVariant final + : public Data::AssetBus::MultiHandler { friend class Shader; public: ShaderVariant() = default; + virtual ~ShaderVariant(); AZ_DEFAULT_COPY_MOVE(ShaderVariant); //! Fills a pipeline state descriptor with settings provided by the ShaderVariant. (Note that @@ -50,13 +52,22 @@ namespace AZ ShaderVariantStableId GetStableId() const { return m_shaderVariantAsset->GetStableId(); } + const Data::Asset& GetShaderAsset() const { return m_shaderAsset; } + const Data::Asset& GetShaderVariantAsset() const { return m_shaderVariantAsset; } + private: // Called by Shader. Initializes runtime data from asset data. Returns whether the call succeeded. bool Init( - const ShaderAsset& shaderAsset, - Data::Asset shaderVariantAsset, + const Data::Asset& shaderAsset, + const Data::Asset& shaderVariantAsset); SupervariantIndex supervariantIndex); + // AssetBus overrides... + void OnAssetReloaded(Data::Asset asset) override; + + //! A reference to the shader asset that this is a variant of. + Data::Asset m_shaderAsset; + // Cached state from the asset to avoid an indirection. RHI::PipelineStateType m_pipelineStateType = RHI::PipelineStateType::Count; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h index a219e69acd..ab68918468 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -38,6 +39,7 @@ namespace AZ : public AZ::Data::AssetData , public Data::AssetBus::Handler , public MaterialReloadNotificationBus::Handler + , public AssetInitBus::Handler { friend class MaterialAssetCreator; friend class MaterialAssetHandler; @@ -108,13 +110,17 @@ namespace AZ AZStd::array_view GetPropertyValues() const; private: - bool PostLoadInit(); + bool PostLoadInit() override; //! Called by asset creators to assign the asset to a ready state. void SetReady(); // AssetBus overrides... void OnAssetReloaded(Data::Asset asset) override; + void OnAssetReady(Data::Asset asset) override; + + //! Replaces the MaterialTypeAsset when a reload occurs + void ReinitializeMaterialTypeAsset(Data::Asset asset); // MaterialReloadNotificationBus overrides... void OnMaterialTypeAssetReinitialized(const Data::Asset& materialTypeAsset) override; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAsset.h index 7bc3a7c491..828c2e6541 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialTypeAsset.h @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -52,6 +53,7 @@ namespace AZ class MaterialTypeAsset : public AZ::Data::AssetData , public Data::AssetBus::MultiHandler + , public AssetInitBus::Handler { friend class MaterialTypeAssetCreator; friend class MaterialTypeAssetHandler; @@ -126,7 +128,7 @@ namespace AZ MaterialUvNameMap GetUvNameMap() const; private: - bool PostLoadInit(); + bool PostLoadInit() override; const RHI::Ptr& GetSrgLayout(uint32_t shaderIndex, const SupervariantIndex& supervariantIndex, uint32_t srgBindingSlot) const; const RHI::Ptr& GetSrgLayout(uint32_t shaderIndex, const AZ::Name& supervariantName, uint32_t srgBindingSlot) const; @@ -136,6 +138,10 @@ namespace AZ // AssetBus overrides... void OnAssetReloaded(Data::Asset asset) override; + void OnAssetReady(Data::Asset asset) override; + + //! Replaces the appropriate asset members when a reload occurs + void ReinitializeAsset(Data::Asset asset); //! Holds values for each material property, used to initialize Material instances. //! This is indexed by MaterialPropertyIndex and aligns with entries in m_materialPropertiesLayout. diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderAsset.h index a09f866bde..569358e642 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderAsset.h @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -57,6 +58,7 @@ namespace AZ : public Data::AssetData , public ShaderVariantFinderNotificationBus::Handler , public Data::AssetBus::Handler + , public AssetInitBus::Handler { friend class ShaderAssetCreator; friend class ShaderAssetHandler; @@ -224,8 +226,11 @@ namespace AZ /////////////////////////////////////////////////////////////////// /// AssetBus overrides void OnAssetReloaded(Data::Asset asset) override; + void OnAssetReady(Data::Asset asset) override; /////////////////////////////////////////////////////////////////// + void ReinitializeRootShaderVariant(Data::Asset asset); + /////////////////////////////////////////////////////////////////// /// ShaderVariantFinderNotificationBus overrides void OnShaderVariantTreeAssetReady(Data::Asset shaderVariantTreeAsset, bool isError) override; @@ -267,8 +272,13 @@ namespace AZ AZStd::vector m_supervariants; }; - bool FinalizeAfterLoad(); + bool PostLoadInit() override; void SetReady(); + + //! SelectShaderApiData() must be called before most other ShaderAsset functions. + bool SelectShaderApiData(); + + //! Returns the active ShaderApiDataContainer which was selected in SelectShaderApiData(). ShaderApiDataContainer& GetCurrentShaderApiData(); const ShaderApiDataContainer& GetCurrentShaderApiData() const; @@ -330,7 +340,6 @@ namespace AZ const Data::Asset& asset, AZStd::shared_ptr stream, const Data::AssetFilterCB& assetLoadFilterCB) override; - Data::AssetHandler::LoadResult PostLoadInit(const Data::Asset& asset); }; ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/BuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/BuilderComponent.cpp index a67bce4acb..0f7dfdb28f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/BuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/BuilderComponent.cpp @@ -99,20 +99,6 @@ namespace AZ m_assetHandlers.emplace_back(MakeAssetHandler()); m_assetHandlers.emplace_back(MakeAssetHandler()); m_assetHandlers.emplace_back(MakeAssetHandler()); - - RPI::MaterialFunctorSourceDataRegistration* materialFunctorRegistration = RPI::MaterialFunctorSourceDataRegistration::Get(); - AZ_Assert(materialFunctorRegistration, - "MaterialFunctorSourceDataRegistration must be added to a component of the current module, " - "and initialize it in the component's Init() call."); - materialFunctorRegistration->RegisterMaterialFunctor("Lua", azrtti_typeid()); - - - // Add asset types and extensions to AssetCatalog. Uses "AssetCatalogService". - auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler(); - if (assetCatalog) - { - assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid()); - } } void BuilderComponent::Deactivate() diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQuerySystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQuerySystem.cpp index 2c9c1faf4a..e6d7aa01c9 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQuerySystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQuerySystem.cpp @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -78,6 +79,7 @@ namespace AZ void GpuQuerySystem::Update() { + AZ_ATOM_PROFILE_FUNCTION("RPI", "GpuQuerySystem: Update"); for (auto& queryPool : m_queryPoolArray) { if (queryPool) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp index c498632393..4d134257e5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp @@ -242,8 +242,16 @@ namespace AZ // MaterialReloadNotificationBus overrides... void Material::OnMaterialAssetReinitialized(const Data::Asset& materialAsset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnMaterialAssetReinitialized %s", this, materialAsset.GetHint().c_str()); - OnAssetReloaded(materialAsset); + // It's important that we don't just pass materialAsset to Init() because when reloads occur, + // it's possible for old Asset objects to hang around and report reinitialization, so materialAsset + // might be stale data. + + if (materialAsset.Get() == m_materialAsset.Get()) + { + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnMaterialAssetReinitialized %s", this, materialAsset.GetHint().c_str()); + + OnAssetReloaded(m_materialAsset); + } } /////////////////////////////////////////////////////////////////// @@ -259,8 +267,6 @@ namespace AZ void Material::OnShaderAssetReinitialized(const Data::Asset& shaderAsset) { - // TODO: I think we should make Shader handle OnShaderAssetReinitialized and treat it just like the shader reloaded. - ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str()); // Note that it might not be strictly necessary to reinitialize the entire material, we might be able to get away with // just bumping the m_currentChangeId or some other minor updates. But it's pretty hard to know what exactly needs to be @@ -268,9 +274,9 @@ namespace AZ OnAssetReloaded(m_materialAsset); } - void Material::OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& /*shaderVariantId*/, ShaderVariantStableId shaderVariantStableId) + void Material::OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) { - ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderVariantReinitialized %s variant %u", this, shader.GetAsset().GetHint().c_str(), shaderVariantStableId.GetIndex()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderVariantReinitialized %s", this, shaderVariant.GetShaderVariantAsset().GetHint().c_str()); // Note that it would be better to check the shaderVariantId to see if that variant is relevant to this particular material before reinitializing it. // There could be hundreds or even thousands of variants for a shader, but only one of those variants will be used by any given material. So we could diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ComputePass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ComputePass.cpp index 0253ef0c9b..9be6d10111 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ComputePass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ComputePass.cpp @@ -241,9 +241,8 @@ namespace AZ LoadShader(); } - void ComputePass::OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) + void ComputePass::OnShaderVariantReinitialized(const ShaderVariant&) { - AZ_UNUSED(shader); AZ_UNUSED(shaderVariantId); AZ_UNUSED(shaderVariantStableId); LoadShader(); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp index 7235bb343d..806310ef35 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp @@ -57,7 +57,7 @@ namespace AZ LoadShader(); } - void FullscreenTrianglePass::OnShaderVariantReinitialized(const Shader&, const ShaderVariantId&, ShaderVariantStableId) + void FullscreenTrianglePass::OnShaderVariantReinitialized(const ShaderVariant&) { LoadShader(); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp index 2c88ca60c9..f1206e469d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp @@ -62,6 +62,11 @@ namespace AZ { const PassAttachmentBinding& binding = m_attachmentBindings[slotIndex]; + if (!binding.m_attachment) + { + continue; + } + // Handle the depth-stencil attachment. There should be only one. if (binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::DepthStencil) { @@ -99,6 +104,10 @@ namespace AZ { continue; } + if (!binding.m_attachment) + { + continue; + } if (binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::RenderTarget || binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::DepthStencil) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/PipelineState.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/PipelineState.cpp index 545e71e117..8b13817897 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/PipelineState.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/PipelineState.cpp @@ -124,12 +124,9 @@ namespace AZ RefreshShaderVariant(); } - void PipelineStateForDraw::OnShaderVariantReinitialized( - [[maybe_unused]] const Shader& shader, - const ShaderVariantId& shaderVariantId, - [[maybe_unused]] ShaderVariantStableId shaderVariantStableId) + void PipelineStateForDraw::OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) { - if(shaderVariantId == m_shaderVariantId) + if(shaderVariant.GetShaderVariantId() == m_shaderVariantId) { RefreshShaderVariant(); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp index 768869834f..797e467baa 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -247,6 +248,8 @@ namespace AZ } AZ_ATOM_PROFILE_FUNCTION("RPI", "RPISystem: SimulationTick"); + AssetInitBus::Broadcast(&AssetInitBus::Events::PostLoadInit); + // Update tick time info FillTickTimeInfo(); @@ -286,24 +289,27 @@ namespace AZ m_rhiSystem.FrameUpdate( [this](RHI::FrameGraphBuilder& frameGraphBuilder) + { + // Pass system's frame update, which includes the logic of adding scope producers, has to be added here since the + // scope producers only can be added to the frame when frame started which cleans up previous scope producers. + m_passSystem.FrameUpdate(frameGraphBuilder); + + // Update View Srgs + for (auto& scenePtr : m_scenes) + { + scenePtr->UpdateSrgs(); + } + }); + { - // Pass system's frame update, which includes the logic of adding scope producers, has to be added here since the scope producers only can be added to the frame - // when frame started which cleans up previous scope producers. - m_passSystem.FrameUpdate(frameGraphBuilder); + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "RPISystem: FrameEnd"); + m_dynamicDraw.FrameEnd(); + m_passSystem.FrameEnd(); - // Update View Srgs for (auto& scenePtr : m_scenes) { - scenePtr->UpdateSrgs(); + scenePtr->OnFrameEnd(); } - }); - - m_dynamicDraw.FrameEnd(); - m_passSystem.FrameEnd(); - - for (auto& scenePtr : m_scenes) - { - scenePtr->OnFrameEnd(); } m_renderTick++; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp index d87f119a7a..c6457e2c2e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp @@ -404,6 +404,7 @@ namespace AZ { AZ_PROFILE_SCOPE(Debug::ProfileCategory::AzRender, "WaitForSimulationCompletion"); + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "WaitForSimulationCompletion"); WaitAndCleanCompletionJob(m_simulationCompletion); } @@ -420,12 +421,15 @@ namespace AZ // Get active pipelines which need to be rendered and notify them frame started AZStd::vector activePipelines; - for (auto& pipeline : m_pipelines) { - if (pipeline->NeedsRender()) + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "OnStartFrame"); + for (auto& pipeline : m_pipelines) { - activePipelines.push_back(pipeline); - pipeline->OnStartFrame(tickInfo); + if (pipeline->NeedsRender()) + { + activePipelines.push_back(pipeline); + pipeline->OnStartFrame(tickInfo); + } } } @@ -444,7 +448,7 @@ namespace AZ { - AZ_PROFILE_SCOPE(Debug::ProfileCategory::AzRender, "Setup Views"); + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Setup Views"); // Collect persistent views from all pipelines to be rendered AZStd::map persistentViews; @@ -490,7 +494,6 @@ namespace AZ { const auto renderLambda = [this, &fp]() { - AZ_PROFILE_SCOPE_DYNAMIC(Debug::ProfileCategory::AzRender, "renderJob - fp:%s", fp->RTTI_GetTypeName()); fp->Render(m_renderPacket); }; @@ -526,12 +529,14 @@ namespace AZ // Add dynamic draw data for all the views if (m_dynamicDrawSystem) { + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "DynamicDraw SubmitDrawData"); m_dynamicDrawSystem->SubmitDrawData(this, m_renderPacket.m_views); } } { AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzRender, "FinalizeDrawLists"); + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "FinalizeDrawLists"); if (jobPolicy == RHI::JobPolicy::Serial) { for (auto& view : m_renderPacket.m_views) @@ -542,7 +547,6 @@ namespace AZ else { AZ::JobCompletion* finalizeDrawListsCompletion = aznew AZ::JobCompletion(); - AZ_PROFILE_EVENT_BEGIN(Debug::ProfileCategory::AzRender, "StartFinalizeDrawListsJobs"); for (auto& view : m_renderPacket.m_views) { const auto finalizeDrawListsLambda = [view]() @@ -559,11 +563,15 @@ namespace AZ } } - SceneNotificationBus::Event(GetId(), &SceneNotification::OnEndPrepareRender); + { + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Scene OnEndPrepareRender"); + SceneNotificationBus::Event(GetId(), &SceneNotification::OnEndPrepareRender); + } } void Scene::OnFrameEnd() { + AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: OnFrameEnd"); for (auto& pipeline : m_pipelines) { if (pipeline->NeedsRender()) @@ -702,6 +710,7 @@ namespace AZ void Scene::RebuildPipelineStatesLookup() { + AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: RebuildPipelineStatesLookup"); m_pipelineStatesLookup.clear(); AZStd::queue parents; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp index 2c06755d78..81d9544329 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp @@ -21,7 +21,6 @@ #include #include -#include #include namespace AZ @@ -69,9 +68,8 @@ namespace AZ RHI::ResultCode Shader::Init(ShaderAsset& shaderAsset) { AZ_Assert(m_supervariantIndex != InvalidSupervariantIndex, "Invalid supervariant index"); - - ShaderVariantFinderNotificationBus::Handler::BusDisconnect(); - ShaderVariantFinderNotificationBus::Handler::BusConnect(shaderAsset.GetId()); + Data::AssetBus::Handler::BusDisconnect(); + ShaderReloadNotificationBus::Handler::BusDisconnect(); ShaderVariantFinderNotificationBus::Handler::BusDisconnect(); RHI::RHISystemInterface* rhiSystem = RHI::RHISystemInterface::Get(); RHI::DrawListTagRegistry* drawListTagRegistry = rhiSystem->GetDrawListTagRegistry(); @@ -83,7 +81,8 @@ namespace AZ AZStd::unique_lock lock(m_variantCacheMutex); m_shaderVariants.clear(); } - m_rootVariant.Init(shaderAsset, shaderAsset.GetRootVariant(m_supervariantIndex), m_supervariantIndex); + m_rootVariant.Init(shaderAsset, shaderAsset.GetRootVariant()); + m_rootVariant.Init(Data::Asset{&shaderAsset, AZ::Data::AssetLoadBehavior::PreLoad}, shaderAsset.GetRootVariant(m_supervariantIndex), m_supervariantIndex); if (m_pipelineLibraryHandle.IsNull()) { @@ -115,8 +114,10 @@ namespace AZ AZ_Error("Shader", false, "Failed to acquire a DrawListTag. Entries are full."); } } - + + ShaderVariantFinderNotificationBus::Handler::BusConnect(m_asset.GetId()); Data::AssetBus::Handler::BusConnect(m_asset.GetId()); + ShaderReloadNotificationBus::Handler::BusConnect(m_asset.GetId()); return RHI::ResultCode::Success; } @@ -125,6 +126,7 @@ namespace AZ { ShaderVariantFinderNotificationBus::Handler::BusDisconnect(); Data::AssetBus::Handler::BusDisconnect(); + ShaderReloadNotificationBus::Handler::BusDisconnect(); if (m_pipelineLibraryHandle.IsValid()) { @@ -154,7 +156,6 @@ namespace AZ Data::Asset newAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; AZ_Assert(newAsset, "Reloaded ShaderAsset is null"); - Data::AssetBus::Handler::BusDisconnect(); Init(*newAsset.Get()); ShaderReloadNotificationBus::Event(asset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderReinitialized, *this); } @@ -167,7 +168,14 @@ namespace AZ { AZ_Assert(shaderVariantAsset, "Reloaded ShaderVariantAsset is null"); const ShaderVariantStableId stableId = shaderVariantAsset->GetStableId(); - const ShaderVariantId& shaderVariantId = shaderVariantAsset->GetShaderVariantId(); + + // We make a copy of the updated variant because OnShaderVariantReinitialized must not be called inside + // m_variantCacheMutex or deadlocks may occur. + // Or if there is an error, we leave this object in its default state to indicate there was an error. + // [GFX TODO] We really should have a dedicated message/event for this, but that will be covered by a future task where + // we will merge ShaderReloadNotificationBus messages into one. For now, we just indicate the error by passing an empty ShaderVariant, + // all our call sites don't use this data anyway. + ShaderVariant updatedVariant; if (isError) { @@ -178,7 +186,7 @@ namespace AZ return; } AZStd::unique_lock lock(m_variantCacheMutex); - m_shaderVariants.erase(stableId); + m_shaderVariants.erase(stableId); } else { @@ -191,26 +199,48 @@ namespace AZ { ShaderVariant& shaderVariant = iter->second; - if (!shaderVariant.Init(*m_asset.Get(), shaderVariantAsset, m_supervariantIndex)) + if (!shaderVariant.Init(m_asset, shaderVariantAsset, m_supervariantIndex)) { AZ_Error("Shader", false, "Failed to init shaderVariant with StableId=%u", shaderVariantAsset->GetStableId()); m_shaderVariants.erase(stableId); } + else + { + updatedVariant = shaderVariant; + } } else { //This is the first time the shader variant asset comes to life. ShaderVariant newVariant; - newVariant.Init(*m_asset, shaderVariantAsset, m_supervariantIndex); + newVariant.Init(m_asset, shaderVariantAsset, m_supervariantIndex); m_shaderVariants.emplace(stableId, newVariant); } } - //Even if there was an error, the interested parties should be notified. - ShaderReloadNotificationBus::Event(m_asset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this, shaderVariantId, stableId); + // [GFX TODO] It might make more sense to call OnShaderReinitialized here + ShaderReloadNotificationBus::Event(m_asset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, updatedVariant); + } + /////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////// + // ShaderReloadNotificationBus overrides... + void Shader::OnShaderAssetReinitialized(const Data::Asset& shaderAsset) + { + // When reloads occur, it's possible for old Asset objects to hang around and report reinitialization, + // so we can reduce unnecessary reinitialization in that case. + if (shaderAsset.Get() == m_asset.Get()) + { + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Shader::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str()); + + Init(*m_asset.Get()); + ShaderReloadNotificationBus::Event(shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderReinitialized, *this); + } } /////////////////////////////////////////////////////////////////// + ConstPtr Shader::LoadPipelineLibrary() const { if (IO::FileIOBase::GetInstance()) @@ -340,7 +370,7 @@ namespace AZ } ShaderVariant newVariant; - newVariant.Init(*m_asset, shaderVariantAsset, m_supervariantIndex); + newVariant.Init(m_asset, shaderVariantAsset, m_supervariantIndex); m_shaderVariants.emplace(shaderVariantStableId, newVariant); return m_shaderVariants.at(shaderVariantStableId); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariant.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariant.cpp index 09b1359e08..21b5c4248e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariant.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariant.cpp @@ -9,11 +9,13 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ + #include +#include +#include #include #include - #include namespace AZ @@ -21,17 +23,21 @@ namespace AZ namespace RPI { bool ShaderVariant::Init( - const ShaderAsset& shaderAsset, - Data::Asset shaderVariantAsset, + const Data::Asset& shaderAsset, + const Data::Asset& shaderVariantAsset, SupervariantIndex supervariantIndex) { m_pipelineStateType = shaderAsset.GetPipelineStateType(); - m_pipelineLayoutDescriptor = shaderAsset.GetPipelineLayoutDescriptor(supervariantIndex); - m_shaderVariantAsset = shaderVariantAsset; + m_pipelineLayoutDescriptor = shaderAsset.GetPipelineLayoutDescriptor(supervariantIndex); m_shaderVariantAsset = shaderVariantAsset; m_renderStates = &shaderAsset.GetRenderStates(supervariantIndex); return true; } + ShaderVariant::~ShaderVariant() + { + Data::AssetBus::MultiHandler::BusDisconnect(); + } + void ShaderVariant::ConfigurePipelineState(RHI::PipelineStateDescriptor& descriptor) const { descriptor.m_pipelineLayoutDescriptor = m_pipelineLayoutDescriptor; @@ -72,5 +78,25 @@ namespace AZ } } + + void ShaderVariant::OnAssetReloaded(Data::Asset asset) + { + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderVariant::OnAssetReloaded %s", this, asset.GetHint().c_str()); + + if (asset.GetAs()) + { + Data::Asset shaderVariantAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; + Init(m_shaderAsset, shaderVariantAsset); + ShaderReloadNotificationBus::Event(m_shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this); + } + + if (asset.GetAs()) + { + Data::Asset shaderAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; + Init(shaderAsset, m_shaderVariantAsset); + ShaderReloadNotificationBus::Event(m_shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this); + } + } + } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp index bc371a6e42..fe93b92ede 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp @@ -325,9 +325,8 @@ namespace AZ void ShaderVariantAsyncLoader::Reset() { - // [GFX TODO ATOM-14544] Idealy we want to be able to reset the ShaderVariantAsyncLoader but this is causing some problems that need to be worked out first. - //Shutdown(); - //Init(); + Shutdown(); + Init(); } /////////////////////////////////////////////////////////////////// diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp index 4d9e150a42..7d9feb0b63 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp @@ -18,6 +18,7 @@ #include #include +#include namespace AZ { @@ -47,6 +48,7 @@ namespace AZ { MaterialReloadNotificationBus::Handler::BusDisconnect(); Data::AssetBus::Handler::BusDisconnect(); + AssetInitBus::Handler::BusDisconnect(); } const Data::Asset& MaterialAsset::GetMaterialTypeAsset() const @@ -117,6 +119,8 @@ namespace AZ { if (!m_materialTypeAsset.Get()) { + AssetInitBus::Handler::BusDisconnect(); + // Any MaterialAsset with invalid MaterialTypeAsset is not a successfully-loaded asset. return false; } @@ -124,23 +128,30 @@ namespace AZ { Data::AssetBus::Handler::BusConnect(m_materialTypeAsset.GetId()); MaterialReloadNotificationBus::Handler::BusConnect(m_materialTypeAsset.GetId()); + + AssetInitBus::Handler::BusDisconnect(); return true; } } - void MaterialAsset::OnMaterialTypeAssetReinitialized(const Data::Asset&) + void MaterialAsset::OnMaterialTypeAssetReinitialized(const Data::Asset& materialTypeAsset) { - // MaterialAsset doesn't need to reinitialize any of its own data when MaterialTypeAsset reinitializes, - // because all it depends on is the MaterialTypeAsset reference, rather than the data inside it. - // Ultimately it's the Material that cares about these changes, so we just forward any signal we get. - MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialAssetReinitialized, Data::Asset{this, AZ::Data::AssetLoadBehavior::PreLoad}); - } + // When reloads occur, it's possible for old Asset objects to hang around and report reinitialization, + // so we can reduce unnecessary reinitialization in that case. + if (materialTypeAsset.Get() == m_materialTypeAsset.Get()) + { + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnMaterialTypeAssetReinitialized %s", this, materialTypeAsset.GetHint().c_str()); - void MaterialAsset::OnAssetReloaded(Data::Asset asset) + // MaterialAsset doesn't need to reinitialize any of its own data when MaterialTypeAsset reinitializes, + // because all it depends on is the MaterialTypeAsset reference, rather than the data inside it. + // Ultimately it's the Material that cares about these changes, so we just forward any signal we get. + MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialAssetReinitialized, Data::Asset{this, AZ::Data::AssetLoadBehavior::PreLoad}); + } + } + + void MaterialAsset::ReinitializeMaterialTypeAsset(Data::Asset asset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnAssetReloaded %s", this, asset.GetHint().c_str()); - Data::Asset newMaterialTypeAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; if (newMaterialTypeAsset) @@ -155,16 +166,31 @@ namespace AZ } } + void MaterialAsset::OnAssetReloaded(Data::Asset asset) + { + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnAssetReloaded %s", this, asset.GetHint().c_str()); + ReinitializeMaterialTypeAsset(asset); + } + + void MaterialAsset::OnAssetReady(Data::Asset asset) + { + // Regarding why we listen to both OnAssetReloaded and OnAssetReady, see explanation in ShaderAsset::OnAssetReady. + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnAssetReady %s", this, asset.GetHint().c_str()); + ReinitializeMaterialTypeAsset(asset); + } + Data::AssetHandler::LoadResult MaterialAssetHandler::LoadAssetData( const AZ::Data::Asset& asset, AZStd::shared_ptr stream, const AZ::Data::AssetFilterCB& assetLoadFilterCB) { - Data::AssetHandler::LoadResult baseResult = Base::LoadAssetData(asset, stream, assetLoadFilterCB); - bool postLoadResult = asset.GetAs()->PostLoadInit(); - return ((baseResult == Data::AssetHandler::LoadResult::LoadComplete) && postLoadResult) ? - Data::AssetHandler::LoadResult::LoadComplete : - Data::AssetHandler::LoadResult::Error; + if (Base::LoadAssetData(asset, stream, assetLoadFilterCB) == Data::AssetHandler::LoadResult::LoadComplete) + { + asset.GetAs()->AssetInitBus::Handler::BusConnect(); + return Data::AssetHandler::LoadResult::LoadComplete; + } + + return Data::AssetHandler::LoadResult::Error; } } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp index b62ab02023..4cdd0137af 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp @@ -65,6 +65,7 @@ namespace AZ MaterialTypeAsset::~MaterialTypeAsset() { Data::AssetBus::MultiHandler::BusDisconnect(); + AssetInitBus::Handler::BusDisconnect(); } const ShaderCollection& MaterialTypeAsset::GetShaderCollection() const @@ -175,6 +176,8 @@ namespace AZ { Data::AssetBus::MultiHandler::BusConnect(shaderItem.GetShaderAsset().GetId()); } + AssetInitBus::Handler::BusDisconnect(); + return true; } @@ -186,11 +189,9 @@ namespace AZ assetToReplace = newAsset; } } - - void MaterialTypeAsset::OnAssetReloaded(Data::Asset asset) + + void MaterialTypeAsset::ReinitializeAsset(Data::Asset asset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialTypeAsset::OnAssetReloaded %s", this, asset.GetHint().c_str()); - // The order of asset reloads is non-deterministic. If the MaterialTypeAsset reloads before these // dependency assets, this will make sure the MaterialTypeAsset gets the latest ones when they reload. // Or in some cases a these assets could get updated and reloaded without reloading the MaterialTypeAsset at all. @@ -203,16 +204,31 @@ namespace AZ MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialTypeAssetReinitialized, Data::Asset{this, AZ::Data::AssetLoadBehavior::PreLoad}); } + void MaterialTypeAsset::OnAssetReloaded(Data::Asset asset) + { + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialTypeAsset::OnAssetReloaded %s", this, asset.GetHint().c_str()); + ReinitializeAsset(asset); + } + + void MaterialTypeAsset::OnAssetReady(Data::Asset asset) + { + // Regarding why we listen to both OnAssetReloaded and OnAssetReady, see explanation in ShaderAsset::OnAssetReady. + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialTypeAsset::OnAssetReady %s", this, asset.GetHint().c_str()); + ReinitializeAsset(asset); + } + AZ::Data::AssetHandler::LoadResult MaterialTypeAssetHandler::LoadAssetData( const AZ::Data::Asset& asset, AZStd::shared_ptr stream, const AZ::Data::AssetFilterCB& assetLoadFilterCB) { - Data::AssetHandler::LoadResult baseResult = Base::LoadAssetData(asset, stream, assetLoadFilterCB); - bool postLoadResult = asset.GetAs()->PostLoadInit(); - return ((baseResult == Data::AssetHandler::LoadResult::LoadComplete) && postLoadResult) ? - Data::AssetHandler::LoadResult::LoadComplete : - Data::AssetHandler::LoadResult::Error; + if (Base::LoadAssetData(asset, stream, assetLoadFilterCB) == Data::AssetHandler::LoadResult::LoadComplete) + { + asset.GetAs()->AssetInitBus::Handler::BusConnect(); + return Data::AssetHandler::LoadResult::LoadComplete; + } + + return Data::AssetHandler::LoadResult::Error; } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp index 3d1b99df46..f40152a906 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp @@ -112,6 +112,7 @@ namespace AZ { Data::AssetBus::Handler::BusDisconnect(); ShaderVariantFinderNotificationBus::Handler::BusDisconnect(); + AssetInitBus::Handler::BusDisconnect(); } const Name& ShaderAsset::GetName() const @@ -467,7 +468,7 @@ namespace AZ return &supervariants[index]; } - bool ShaderAsset::FinalizeAfterLoad() + bool ShaderAsset::SelectShaderApiData() { // Use the current RHI that is active to select which shader data to use. // We don't assert if the Factory is not available because this method could be called during build time, @@ -509,18 +510,47 @@ namespace AZ } } + return true; + } + + bool ShaderAsset::PostLoadInit() + { // Once the ShaderAsset is loaded, it is necessary to listen for changes in the Root Variant Asset. Data::AssetBus::Handler::BusConnect(GetRootVariant().GetId()); ShaderVariantFinderNotificationBus::Handler::BusConnect(GetId()); + + AssetInitBus::Handler::BusDisconnect(); return true; } + + void ShaderAsset::ReinitializeRootShaderVariant(Data::Asset asset) + { + Data::Asset shaderVariantAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; + AZ_Assert(shaderVariantAsset->GetStableId() == RootShaderVariantStableId, "Was expecting to update the root variant"); + GetCurrentShaderApiData().m_rootShaderVariantAsset = asset; + ShaderReloadNotificationBus::Event(GetId(), &ShaderReloadNotificationBus::Events::OnShaderAssetReinitialized, Data::Asset{ this, AZ::Data::AssetLoadBehavior::PreLoad } ); + } /////////////////////////////////////////////////////////////////////// // AssetBus overrides... void ShaderAsset::OnAssetReloaded(Data::Asset asset) { ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderAsset::OnAssetReloaded %s", this, asset.GetHint().c_str()); + ReinitializeRootShaderVariant(asset); + } + void ShaderAsset::OnAssetReady(Data::Asset asset) + { + // We have to listen to OnAssetReady, OnAssetReloaded isn't enough, because of the following scenario: + // The user changes a .shader file, which causes the AP to rebuild the ShaderAsset and root ShaderVariantAsset. + // 1) Thread A creates the new ShaderAsset, loads it, and gets the old ShaderVariantAsset. + // 2) Thread B creates the new ShaderVariantAsset, loads it, and calls OnAssetReloaded. + // 3) Main thread calls ShaderAsset::PostLoadInit which connects to the AssetBus but it's too late to receive OnAssetReloaded, + // so it continues using the old ShaderVariantAsset instead of the new one. + // The OnAssetReady bus function is called automatically whenever a connection to AssetBus is made, so listening to this gives + // us the opportunity to assign the appropriate ShaderVariantAsset. + + ShaderReloadNotificationBus::Event(GetId(), &ShaderReloadNotificationBus::Events::OnShaderAssetReinitialized, Data::Asset{ this, AZ::Data::AssetLoadBehavior::PreLoad } ); Data::Asset shaderVariantAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; AZ_Assert(shaderVariantAsset->GetStableId() == RootShaderVariantStableId, @@ -529,9 +559,12 @@ namespace AZ GetCurrentShaderApiData().m_supervariants[supervariantIndex.GetIndex()].m_rootShaderVariantAsset = asset; ShaderReloadNotificationBus::Event(GetId(), &ShaderReloadNotificationBus::Events::OnShaderAssetReinitialized, Data::Asset{ this, AZ::Data::AssetLoadBehavior::PreLoad } ); + + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderAsset::OnAssetReady %s", this, asset.GetHint().c_str()); + ReinitializeRootShaderVariant(asset); } /////////////////////////////////////////////////////////////////////// - + /////////////////////////////////////////////////////////////////// /// ShaderVariantFinderNotificationBus overrides void ShaderAsset::OnShaderVariantTreeAssetReady(Data::Asset shaderVariantTreeAsset, bool isError) @@ -565,25 +598,25 @@ namespace AZ { if (Base::LoadAssetData(asset, stream, assetLoadFilterCB) == Data::AssetHandler::LoadResult::LoadComplete) { - return PostLoadInit(asset); - } - return Data::AssetHandler::LoadResult::Error; - } + ShaderAsset* shaderAsset = asset.GetAs(); - Data::AssetHandler::LoadResult ShaderAssetHandler::PostLoadInit(const Data::Asset& asset) - { - if (ShaderAsset* shaderAsset = asset.GetAs()) - { - if (!shaderAsset->FinalizeAfterLoad()) + // The shader API selection must occur immediately ofter loading, on the same thread, rather than + // deferring to AssetInitBus::PostLoadInit. Many functions in the ShaderAsset class are invalid + // until after SelectShaderApiData() is called and some client code may need to access data in + // the ShaderAsset before then. + if (!shaderAsset->SelectShaderApiData()) { - AZ_Error("ShaderAssetHandler", false, "Shader asset failed to finalize."); return Data::AssetHandler::LoadResult::Error; } + + shaderAsset->AssetInitBus::Handler::BusConnect(); + return Data::AssetHandler::LoadResult::LoadComplete; } + return Data::AssetHandler::LoadResult::Error; } - + /////////////////////////////////////////////////////////////////////// } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAssetCreator.cpp index 40daff8c8a..114bfc4414 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAssetCreator.cpp @@ -375,7 +375,7 @@ namespace AZ return false; } - if (!m_asset->FinalizeAfterLoad()) + if (!m_asset->SelectShaderApiData()) { ReportError("Failed to finalize the ShaderAsset."); return false; diff --git a/Gems/Atom/RPI/Code/Tests/Shader/ShaderTests.cpp b/Gems/Atom/RPI/Code/Tests/Shader/ShaderTests.cpp index cf13e21193..5a3737f701 100644 --- a/Gems/Atom/RPI/Code/Tests/Shader/ShaderTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Shader/ShaderTests.cpp @@ -55,7 +55,7 @@ namespace AZ AZ::Data::Asset SerializeInHelper(const AZ::Data::AssetId& assetId) { AZ::Data::Asset asset = Base::SerializeIn(assetId); - asset->FinalizeAfterLoad(); + asset->SelectShaderApiData(); asset->SetReady(); return asset; } diff --git a/Gems/Atom/RPI/Code/atom_rpi_public_files.cmake b/Gems/Atom/RPI/Code/atom_rpi_public_files.cmake index 6461edd291..8f6e5dbeeb 100644 --- a/Gems/Atom/RPI/Code/atom_rpi_public_files.cmake +++ b/Gems/Atom/RPI/Code/atom_rpi_public_files.cmake @@ -10,6 +10,7 @@ # set(FILES + Include/Atom/RPI.Public/AssetInitBus.h Include/Atom/RPI.Public/Base.h Include/Atom/RPI.Public/Culling.h Include/Atom/RPI.Public/FeatureProcessor.h diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index 64b6e01b61..6264a2aa2b 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -78,13 +78,13 @@ namespace MaterialEditor AZ::Name apiName = AZ::RHI::Factory::Get().GetName(); if (!apiName.IsEmpty()) { - QString title = QString{ "Material Editor (%1)" }.arg(apiName.GetCStr()); + QString title = QString{ "%1 (%2)" }.arg(QApplication::applicationName()).arg(apiName.GetCStr()); setWindowTitle(title); } else { AZ_Assert(false, "Render API name not found"); - setWindowTitle("Material Editor"); + setWindowTitle(QApplication::applicationName()); } m_advancedDockManager = new AzQtComponents::FancyDocking(this); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/main.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/main.cpp index 8c55adba46..ce44d9c640 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/main.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/main.cpp @@ -31,7 +31,7 @@ int main(int argc, char** argv) { QApplication::setOrganizationName("Amazon"); QApplication::setOrganizationDomain("amazon.com"); - QApplication::setApplicationName("MaterialEditor"); + QApplication::setApplicationName("O3DE Material Editor"); AzQtComponents::PrepareQtPaths(); diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h index 4c9ddbe50a..a9ed5b7008 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h @@ -13,6 +13,7 @@ #pragma once #include +#include namespace AZ { @@ -56,6 +57,16 @@ namespace AZ ImGuiTextFilter m_timedRegionFilter; GroupRegionMap m_groupRegionMap; + + // Pause cpu profiling. The profiler will show the statistics of the last frame before pause + bool m_paused = false; + + // Total frames need to be saved + int m_captureFrameCount = 1; + + AZ::RHI::CpuTimingStatistics m_cpuTimingStatisticsWhenPause; + + AZStd::string m_lastCapturedFilePath; }; } // namespace Render } diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index 7a453b4597..72e313157d 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -10,7 +10,10 @@ * */ -#include +#include +#include +#include +#include namespace AZ { @@ -34,16 +37,42 @@ namespace AZ } } - inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics) + inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics) { // Cache the value to detect if it was changed by ImGui(user pressed 'x') const bool cachedShowCpuProfiler = keepDrawing; const ImVec2 windowSize(640.0f, 480.0f); ImGui::SetNextWindowSize(windowSize, ImGuiCond_Once); + bool captureToFile = false; if (ImGui::Begin("Cpu Profiler", &keepDrawing, ImGuiWindowFlags_None)) { - UpdateGroupRegionMap(); + m_paused = !AZ::RHI::CpuProfiler::Get()->IsProfilerEnabled(); + if (ImGui::Button(m_paused ? "Resume" : "Pause")) + { + m_paused = !m_paused; + AZ::RHI::CpuProfiler::Get()->SetProfilerEnabled(!m_paused); + } + + // Update region map and cache the input cpu timing statistics when the profiling is not paused + if (!m_paused) + { + UpdateGroupRegionMap(); + m_cpuTimingStatisticsWhenPause = currentCpuTimingStatistics; + } + + if (ImGui::Button("Capture")) + { + captureToFile = true; + } + + if (!m_lastCapturedFilePath.empty()) + { + ImGui::SameLine(); + ImGui::Text(m_lastCapturedFilePath.c_str()); + } + + const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics = m_cpuTimingStatisticsWhenPause; const AZStd::sys_time_t ticksPerSecond = AZStd::GetTimeTicksPerSecond(); @@ -51,7 +80,7 @@ namespace AZ { // Note: converting to microseconds integer before converting to milliseconds float const float timeInMs = static_cast((duration * 1000) / (ticksPerSecond / 1000)) / 1000.0f; - ImGui::Text("%.1f ms", timeInMs); + ImGui::Text("%.2f ms", timeInMs); }; const auto ShowRow = [ticksPerSecond, &ShowTimeInMs](const char* regionLabel, AZStd::sys_time_t duration) @@ -158,6 +187,20 @@ namespace AZ } ImGui::End(); + if (captureToFile) + { + AZStd::sys_time_t timeNow = AZStd::GetTimeNowSecond(); + AZStd::string timeString; + AZStd::to_string(timeString, timeNow); + u64 currentTick = AZ::RPI::RPISystemInterface::Get()->GetCurrentTick(); + AZStd::string frameDataFilePath = AZStd::string::format("@user@/CpuProfiler/%s_%llu.json", timeString.c_str(), currentTick); + char resolvedPath[AZ::IO::MaxPathLength]; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(frameDataFilePath.c_str(), resolvedPath, AZ::IO::MaxPathLength); + m_lastCapturedFilePath = resolvedPath; + AZ::Render::ProfilingCaptureRequestBus::Broadcast(&AZ::Render::ProfilingCaptureRequestBus::Events::CaptureCpuProfilingStatistics, + frameDataFilePath); + } + // Toggle if the bool isn't the same as the cached value if (cachedShowCpuProfiler != keepDrawing) { diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiFrameVisualizer.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiFrameVisualizer.h index 7ce68c0cc7..0186f68282 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiFrameVisualizer.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiFrameVisualizer.h @@ -38,14 +38,13 @@ namespace AZ ~ImGuiFrameVisualizer() = default; AZStd::vector& GetFrameAttachments(); void Init(RHI::Device* device); - void Draw(bool draw); + void Draw(bool& draw); void DrawTreeView(); void Reset(); protected: AZStd::vector m_framesAttachments; RHI::Device* m_device = nullptr; bool m_deviceInit = false; - bool m_draw = false; ////////////////////////////////////////////////////////////////////////// // FrameEventBus::Handler void OnFrameCompileEnd(RHI::FrameGraph& frameGraph); diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiFrameVisualizer.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiFrameVisualizer.inl index b5cf2e8f6b..5230a6869b 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiFrameVisualizer.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiFrameVisualizer.inl @@ -466,10 +466,10 @@ namespace ImGui } //!Draw the UI and all the nodes. - void Paint() + void Paint(bool& draw) { ImGui::SetNextWindowSize(ImVec2((float)m_windowWidth, (float)m_windowHeight), ImGuiCond_FirstUseEver); - if (!ImGui::Begin(m_windowName.c_str(), &m_open)) + if (!ImGui::Begin(m_windowName.c_str(), &draw)) { ImGui::End(); return; @@ -572,7 +572,6 @@ namespace ImGui AZStd::string m_windowName; unsigned int m_windowWidth = 1; unsigned int m_windowHeight = 1; - bool m_open = false; bool m_frameCapture = false; bool m_showGrid = true; }; @@ -581,7 +580,7 @@ static ImGui::ImGuiFrameVisualizerWindow* visualizerWindow = nullptr; namespace AZ::Render { //! Draw the frame graph. - inline void ImGuiFrameVisualizer::Draw([[maybe_unused]] bool draw) + inline void ImGuiFrameVisualizer::Draw(bool& draw) { if (!visualizerWindow) { @@ -595,7 +594,7 @@ namespace AZ::Render visualizerWindow->CaptureFrame(this); visualizerWindow->DisableCaptureFrame(); } - visualizerWindow->Paint(); + visualizerWindow->Paint(draw); } } diff --git a/Gems/AtomContent/CMakeLists.txt b/Gems/AtomContent/CMakeLists.txt index 4d5680a30d..0e7057dd5a 100644 --- a/Gems/AtomContent/CMakeLists.txt +++ b/Gems/AtomContent/CMakeLists.txt @@ -8,3 +8,5 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +add_subdirectory(ReferenceMaterials) +add_subdirectory(Sponza) diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_AmbientOcclusion.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_AmbientOcclusion.png deleted file mode 100644 index 2ac4eadec2..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_AmbientOcclusion.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6cfa740b94b898e85d93f970a7d7d76581e065662dd8e2b350ea076bd6fe8d35 -size 37187591 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_BaseColor.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_BaseColor.png deleted file mode 100644 index 2d652b9e6f..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_BaseColor.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:254aacfb72ed12743f83740f9eb31a01d28c40c0abeacc39907d20ab82f42636 -size 390896034 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_Displacement.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_Displacement.png deleted file mode 100644 index bb501fb326..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_Displacement.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c164a61daf248f57eacee5167eb9d098a49d7dfc7aea6c68007d7e0c06a29906 -size 74644256 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_Normal.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_Normal.png deleted file mode 100644 index 2d29c01ada..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_Normal.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ade44968832bf7a3e9cab95ddccc4018c7250b07437cddc51c784815b1dcb930 -size 392066587 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_Roughness.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_Roughness.png deleted file mode 100644 index 26acb09325..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/Bricks038_8K_Roughness.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:51dacbe0048b892a196ea9e6178cca908ba46a6f86b7ec979cf0fd7e381720b3 -size 112681262 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material deleted file mode 100644 index 82b1cdb590..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material +++ /dev/null @@ -1,39 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "occlusion": { - "diffuseTextureMap": "Materials/Bricks038_8K/Bricks038_8K_AmbientOcclusion.png" - }, - "baseColor": { - "color": [ - 0.496940553188324, - 0.496940553188324, - 0.496940553188324, - 1.0 - ], - "factor": 0.6464645862579346, - "textureBlendMode": "LinearLight", - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_BaseColor.png" - }, - "general": { - "applySpecularAA": true - }, - "normal": { - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_Normal.png" - }, - "parallax": { - "algorithm": "POM", - "factor": 0.02500000037252903, - "pdo": true, - "quality": "Ultra", - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_Displacement.png" - }, - "roughness": { - "upperBound": 0.5, - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_Roughness.png" - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016.material deleted file mode 100644 index 03fb0ea5be..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016.material +++ /dev/null @@ -1,41 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.19562065601348878, - 0.22017242014408112, - 0.2503242492675781, - 1.0 - ], - "factor": 0.30000001192092898, - "textureBlendMode": "LinearLight", - "textureMap": "Materials/Concrete016_8K/Concrete016_8K_BaseColor.png" - }, - "clearCoat": { - "enable": true, - "normalMap": "Materials/Concrete016_8K/roller_painted_metal_normal.tif", - "roughness": 0.18181820213794709 - }, - "general": { - "applySpecularAA": true - }, - "normal": { - "factor": 0.6499999761581421, - "textureMap": "Materials/Concrete016_8K/Concrete016_8K_Normal.png" - }, - "parallax": { - "algorithm": "ContactRefinement", - "factor": 0.019999999552965165, - "quality": "Ultra", - "textureMap": "Materials/Concrete016_8K/Concrete016_8K_Displacement.png", - "useTexture": false - }, - "roughness": { - "textureMap": "Materials/Concrete016_8K/Concrete016_8K_Roughness.png" - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016_8K_BaseColor.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016_8K_BaseColor.png deleted file mode 100644 index ad611fc7e7..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016_8K_BaseColor.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:42d3ef187f7f98bcee42ffc4ae0629370f4fc19e6532c2db8cc130ce9ece072a -size 74279846 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016_8K_Displacement.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016_8K_Displacement.png deleted file mode 100644 index 6c7bd47ac6..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016_8K_Displacement.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b8e8149f5609ae85f876183f3b4461de4a334658660fc187c5fd469752e5b2d6 -size 93715669 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016_8K_Normal.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016_8K_Normal.png deleted file mode 100644 index 03fcd69a18..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016_8K_Normal.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6f997219d3bb846ea0db7786a394e508d59f99be9548b63d3c73824d97cdacd7 -size 379009988 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016_8K_Roughness.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016_8K_Roughness.png deleted file mode 100644 index 220a4651a3..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016_8K_Roughness.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9ea7f520b28d5232697ea9e4fb4cc7d655069d05f9de0313c92c56e4c1526556 -size 25594794 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/roller_painted_metal_normal.tif b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/roller_painted_metal_normal.tif deleted file mode 100644 index 8d7b594be3..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/roller_painted_metal_normal.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:94c9398b1f5d71aa3f4debb5a9571f0d9a4b1b1992b662e35ca94996b507e4ff -size 6933173 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001.material deleted file mode 100644 index 7d8c3d5142..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001.material +++ /dev/null @@ -1,31 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "textureMap": "Materials/Fabric001_8K/Fabric001_8K_BaseColor.png" - }, - "clearCoat": { - "enable": true, - "normalMap": "Materials/Fabric001_8K/Fabric001_8K_Normal.png", - "roughness": 0.4040403962135315 - }, - "general": { - "applySpecularAA": true - }, - "normal": { - "textureMap": "Materials/Fabric001_8K/Fabric001_8K_Normal.png" - }, - "parallax": { - "algorithm": "ContactRefinement", - "factor": 0.004999999888241291, - "quality": "Ultra", - "textureMap": "Materials/Fabric001_8K/Fabric001_8K_Displacement.png" - }, - "roughness": { - "textureMap": "Materials/Fabric001_8K/Fabric001_8K_Roughness.png" - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001_8K_BaseColor.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001_8K_BaseColor.png deleted file mode 100644 index aeb286f3ff..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001_8K_BaseColor.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e04ea2d456e13fb45a2c4f3f88d2ed07c2799fbdaeba6b52bab64dcd84fefc77 -size 69539547 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001_8K_Displacement.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001_8K_Displacement.png deleted file mode 100644 index eab791d40d..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001_8K_Displacement.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4b41f8b8aa685c443216220063cd6c1de3f620ef66776aecd374025a689dec77 -size 19743435 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001_8K_Normal.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001_8K_Normal.png deleted file mode 100644 index 48abbdef93..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001_8K_Normal.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:009302f8be232e7fd6b23d368c85afdb74ea4deda8147152f2c92d116a2ac585 -size 56894065 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001_8K_Roughness.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001_8K_Roughness.png deleted file mode 100644 index 5f00784e4b..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001_8K_Roughness.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a557862deee7f4ff9bb113f66b1fd432871338d5b801edec7c50f70aa302557d -size 26820294 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030.material deleted file mode 100644 index 493bfab455..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030.material +++ /dev/null @@ -1,32 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "textureMap": "Materials/Fabric030_4K/Fabric030_4K_BaseColor.png" - }, - "clearCoat": { - "enable": true, - "normalMap": "Materials/Fabric030_4K/Fabric030_4K_Normal.png", - "roughness": 0.7676767706871033, - "roughnessMap": "Materials/Fabric030_4K/Fabric030_4K_Roughness.png", - "useInfluenceMap": false - }, - "normal": { - "factor": 0.5, - "textureMap": "Materials/Fabric030_4K/Fabric030_4K_Normal.png" - }, - "parallax": { - "algorithm": "ContactRefinement", - "factor": 0.0020000000949949028, - "pdo": true, - "quality": "Medium", - "textureMap": "Materials/Fabric030_4K/Fabric030_4K_Displacement.png" - }, - "roughness": { - "textureMap": "Materials/Fabric030_4K/Fabric030_4K_Roughness.png" - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_AmbientOcclusion.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_AmbientOcclusion.png deleted file mode 100644 index fa7d1a700a..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_AmbientOcclusion.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:eb2f62e3166428f137b8712f4527c62d3905a8e177840b56fb1775e39417448d -size 11268075 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_BaseColor.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_BaseColor.png deleted file mode 100644 index 5d41fd1df6..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_BaseColor.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:194674f50a0c868d2a2c12cc7a4ddbe5abbe6ebb9687be4be4e49eece3976e29 -size 94910229 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_Displacement.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_Displacement.png deleted file mode 100644 index 4558f36d0b..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_Displacement.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c3f29be8c7afe73b12f5c7df3e3ffd69a0bce46218cef57f73c11638aa07ccc3 -size 19243987 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_Normal.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_Normal.png deleted file mode 100644 index daf33b8e74..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_Normal.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0bc0c08f0b8e33b3251f7dba85c5042138a201e912752135a0bdcfe9c381d5ab -size 63142427 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_Roughness.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_Roughness.png deleted file mode 100644 index 515967232a..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030_4K_Roughness.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aa5ffdb5b9ef2363c58eb85b47adc9e1bdde13256bdc6de05cbfb5b04cf91f91 -size 26802284 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material deleted file mode 100644 index a2bb2c7704..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material +++ /dev/null @@ -1,31 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "occlusion": { - "diffuseFactor": 0.30000001192092898, - "diffuseTextureMap": "Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_AmbientOcclusion.png" - }, - "baseColor": { - "textureMap": "Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_BaseColor.png" - }, - "general": { - "applySpecularAA": true - }, - "normal": { - "textureMap": "Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_Normal.png" - }, - "parallax": { - "algorithm": "ContactRefinement", - "factor": 0.009999999776482582, - "pdo": true, - "quality": "Ultra", - "textureMap": "Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_Displacement.png" - }, - "roughness": { - "textureMap": "Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_Roughness.png" - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_AmbientOcclusion.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_AmbientOcclusion.png deleted file mode 100644 index 4ec3357052..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_AmbientOcclusion.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c271d8a3f305bacafb74037898e8d5841fb8a2fedc0092cbe14134d2ec891d01 -size 115473298 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_BaseColor.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_BaseColor.png deleted file mode 100644 index ad471f2932..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_BaseColor.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:720d85d530e192da6e7daaab89501a9612e145f4aa41405958ff49f765f072ab -size 325006015 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_Displacement.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_Displacement.png deleted file mode 100644 index dc502609f5..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_Displacement.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:71f256cde0427ab8558b09d743d9379899a9a72b4388ca14529bfc9090dd811e -size 88972723 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_Normal.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_Normal.png deleted file mode 100644 index 92af1ccb1c..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_Normal.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4e7eb03dd1ae07ade8e8e99fe6f522fd268ef8e00d3e3f9c3594d9f887b864d8 -size 382741403 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_Roughness.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_Roughness.png deleted file mode 100644 index 8d73944285..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_Roughness.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3f065a3929ea98b54c725515528c2d40b3908a352d497bcce2f088a91b623b11 -size 98105202 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material deleted file mode 100644 index dee6ded191..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material +++ /dev/null @@ -1,42 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.496940553188324, - 0.496940553188324, - 0.496940553188324, - 1.0 - ], - "textureBlendMode": "LinearLight", - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_BaseColor.png", - "useTexture": false - }, - "emissive": { - "useTexture": false - }, - "general": { - "applySpecularAA": true - }, - "normal": { - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_Normal.png", - "useTexture": false - }, - "parallax": { - "algorithm": "POM", - "factor": 0.02500000037252903, - "pdo": true, - "quality": "Ultra", - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_Displacement.png", - "useTexture": false - }, - "roughness": { - "factor": 0.4343433976173401, - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_Roughness.png", - "useTexture": false - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material deleted file mode 100644 index d7e2050dbd..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material +++ /dev/null @@ -1,34 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.496940553188324, - 0.496940553188324, - 0.496940553188324, - 1.0 - ], - "factor": 0.6464645862579346, - "textureBlendMode": "LinearLight" - }, - "general": { - "applySpecularAA": true - }, - "normal": { - "textureMap": "Materials/Concrete016_8K/Concrete016_8K_Normal.png" - }, - "parallax": { - "algorithm": "POM", - "factor": 0.02500000037252903, - "pdo": true, - "quality": "Ultra", - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_Displacement.png" - }, - "roughness": { - "textureMap": "Materials/Concrete016_8K/Concrete016_8K_Roughness.png" - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/metal_fleck_2048_normal.jpg b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/metal_fleck_2048_normal.jpg deleted file mode 100644 index bfa2941bee..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/metal_fleck_2048_normal.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:486712a84618c56b79c6cb12966fe5c44a70bc6573c5eed74381ccdd68592e06 -size 20574 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/metal_fleck_normal.jpg b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/metal_fleck_normal.jpg deleted file mode 100644 index 6a74bf535e..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/metal_fleck_normal.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7c2826872e937f6794a62f75b10b5217dd541fc419ebc1ebe2d4469a38344332 -size 24339 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/round_metal_flecks_2048_normal.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/round_metal_flecks_2048_normal.png deleted file mode 100644 index 40e0054efc..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/round_metal_flecks_2048_normal.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9d603f570813bad6c2db2c055114a5990d5113f7b2c11074a0e8ba83c2007490 -size 1849470 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/round_metal_flecks_4096_normal.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/round_metal_flecks_4096_normal.png deleted file mode 100644 index 116e39935c..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/round_metal_flecks_4096_normal.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d2715b8a38b8198d84927a881440328b2fe565be27737c970da9366c9eab566a -size 3886331 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/round_metal_flecks_512_normal.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/round_metal_flecks_512_normal.png deleted file mode 100644 index 24cce5654a..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/round_metal_flecks_512_normal.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1658a8fbf035d669c88e112c3922f223e77cccece7cb51a0fa2df50412fb02d0 -size 435923 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/.source/LookDevStudio.mb b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/.source/LookDevStudio.mb deleted file mode 100644 index 59e85a30ab..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/.source/LookDevStudio.mb +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b63a99deac3bcf4b9d93359edb68bb22f28da4c9c3d5a7f1d715a84e8c603519 -size 7522972 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/.source/LookDevStudio_original.mb b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/.source/LookDevStudio_original.mb deleted file mode 100644 index 71eaea345b..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/.source/LookDevStudio_original.mb +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d4065dfea401af3b53bcd2906535239d54628c800704f96acbd2767042bc432c -size 8792244 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/Backdrop.fbx b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/Backdrop.fbx deleted file mode 100644 index 305685670e..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/Backdrop.fbx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:93f5e3663a69d9e29bcc64715363420fb8a1331c8f714b9dbdf4d6a6577f943b -size 175120 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/Cube_1m.fbx b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/Cube_1m.fbx deleted file mode 100644 index 3495326570..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/Cube_1m.fbx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d09adbd3e1ef1f1bed98c9ea3034c323bf3f1be25faba5d3721310f46029b0bb -size 24608 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/Lighthead.fbx b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/Lighthead.fbx deleted file mode 100644 index 638a7b0b8a..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/Lighthead.fbx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:391a2e1931263446ee2f38810ee9fc4bc4de29c171cf557398d6bf4a0eba1263 -size 110384 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/Lighthead_lightfacingemissive.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/Lighthead_lightfacingemissive.material deleted file mode 100644 index ddc298a08b..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/Lighthead_lightfacingemissive.material +++ /dev/null @@ -1,23 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 1.600000023841858, - 1.600000023841858, - 1.600000023841858, - 1.0 - ] - }, - "emissive": { - "enable": true, - "intensity": 0.0 - }, - "opacity": { - "factor": 1.0 - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot.fbx b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot.fbx deleted file mode 100644 index 0ac85540d4..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot.fbx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c6c174dde81f8a37f591108b62666347920d0765f3e61c6d557ebf807f38cd3b -size 4512544 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_base_inner.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_base_inner.material deleted file mode 100644 index 4921ff3051..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_base_inner.material +++ /dev/null @@ -1,25 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.4000000059604645, - 0.4000000059604645, - 0.4000000059604645, - 1.0 - ] - }, - "metallic": { - "factor": 1.0 - }, - "opacity": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.25 - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_base_outer1.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_base_outer1.material deleted file mode 100644 index 4cca9e9538..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_base_outer1.material +++ /dev/null @@ -1,25 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.6000000238418579, - 0.6000000238418579, - 0.6000000238418579, - 1.0 - ] - }, - "metallic": { - "factor": 1.0 - }, - "opacity": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.25 - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_cornell_white.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_cornell_white.material deleted file mode 100644 index d01303f3de..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_cornell_white.material +++ /dev/null @@ -1,25 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.8199999928474426, - 0.8199999928474426, - 0.8199999928474426, - 1.0 - ] - }, - "metallic": { - "factor": 1.0 - }, - "opacity": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.25 - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_playfulteapot.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_playfulteapot.material deleted file mode 100644 index da35fda141..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_playfulteapot.material +++ /dev/null @@ -1,40 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.0, - 0.800000011920929, - 0.800000011920929, - 1.0 - ] - }, - "clearCoat": { - "enable": true, - "normalMap": "EngineAssets/Textures/perlinNoiseNormal_ddn.tif", - "normalStrength": 0.10000000149011612 - }, - "general": { - "applySpecularAA": true - }, - "metallic": { - "factor": 0.10000000149011612 - }, - "normal": { - "factor": 0.05000000074505806, - "textureMap": "Materials/round_metal_flecks_4096_normal.png" - }, - "opacity": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.0 - }, - "specularF0": { - "enableMultiScatterCompensation": true - } - } -} \ No newline at end of file diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_playfulteapotfeet.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_playfulteapotfeet.material deleted file mode 100644 index dadb080e8b..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/PlayfulTeapot_playfulteapotfeet.material +++ /dev/null @@ -1,41 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.800000011920929, - 0.0, - 0.0, - 1.0 - ] - }, - "clearCoat": { - "enable": true, - "normalMap": "Materials/Concrete016_8K/roller_painted_metal_normal.tif", - "roughness": 0.1414141058921814 - }, - "general": { - "applySpecularAA": true - }, - "metallic": { - "factor": 0.20000000298023225 - }, - "normal": { - "factor": 0.10000000149011612, - "textureMap": "Materials/round_metal_flecks_2048_normal.png" - }, - "opacity": { - "factor": 1.0 - }, - "roughness": { - "factor": 0.5 - }, - "uv": { - "tileU": 2.0, - "tileV": 2.0 - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room.fbx b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room.fbx deleted file mode 100644 index d5e1f5665d..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room.fbx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c2f3ea6e00e15901263c06fee2aa4d54b96277f7ac103dd8b3c0f8441158d31e -size 83584 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_ceiling.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_ceiling.material deleted file mode 100644 index e0b3453735..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_ceiling.material +++ /dev/null @@ -1,19 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.0, - 0.0, - 0.800000011920929, - 1.0 - ] - }, - "opacity": { - "factor": 1.0 - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_cornell_green.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_cornell_green.material deleted file mode 100644 index 00b2da857b..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_cornell_green.material +++ /dev/null @@ -1,20 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.800000011920929, - 0.800000011920929, - 0.800000011920929, - 1.0 - ], - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_BaseColor.png" - }, - "opacity": { - "factor": 1.0 - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_cornell_red.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_cornell_red.material deleted file mode 100644 index 00b2da857b..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_cornell_red.material +++ /dev/null @@ -1,20 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.800000011920929, - 0.800000011920929, - 0.800000011920929, - 1.0 - ], - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_BaseColor.png" - }, - "opacity": { - "factor": 1.0 - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_cornell_white.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_cornell_white.material deleted file mode 100644 index 8a8044d19b..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_cornell_white.material +++ /dev/null @@ -1,20 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.8199999928474426, - 0.8199999928474426, - 0.8199999928474426, - 1.0 - ], - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_BaseColor.png" - }, - "opacity": { - "factor": 1.0 - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_crown.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_crown.material deleted file mode 100644 index 57991d40fb..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_crown.material +++ /dev/null @@ -1,19 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.800000011920929, - 0.800000011920929, - 0.0, - 1.0 - ] - }, - "opacity": { - "factor": 1.0 - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_floor.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_floor.material deleted file mode 100644 index 0720d45c14..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Objects/cornell_room_floor.material +++ /dev/null @@ -1,19 +0,0 @@ -{ - "description": "", - "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", - "propertyLayoutVersion": 3, - "properties": { - "baseColor": { - "color": [ - 0.4000000059604645, - 0.4000000059604645, - 0.4000000059604645, - 1.0 - ] - }, - "opacity": { - "factor": 1.0 - } - } -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Disk.slice b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Disk.slice deleted file mode 100644 index bec92cea44..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Disk.slice +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Omni.slice b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Omni.slice deleted file mode 100644 index 85dec3a415..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Omni.slice +++ /dev/null @@ -1,951 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Quad.slice b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Quad.slice deleted file mode 100644 index c675449806..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Quad.slice +++ /dev/null @@ -1,358 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Sphere.slice b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Sphere.slice deleted file mode 100644 index 0e2fc880cf..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Sphere.slice +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Spotlight.slice b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Spotlight.slice deleted file mode 100644 index 1efd2fe80b..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Slices/Lighthead-Spotlight.slice +++ /dev/null @@ -1,335 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Textures/sRGB_ColorChecker2014.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Textures/sRGB_ColorChecker2014.png deleted file mode 100644 index de365bc358..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Textures/sRGB_ColorChecker2014.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e2d7323c6a016fa8927a311e757ce1b929888537629abbe3cd9b0bf3277d2108 -size 41983 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Textures/sRGB_Labels_ColorChecker2014.png b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Textures/sRGB_Labels_ColorChecker2014.png deleted file mode 100644 index 1d3efacced..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Textures/sRGB_Labels_ColorChecker2014.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c26bdbdb2efe98742b44bf254295893e989bdb751bc3716f9fd87cb06f27490d -size 675101 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Launch_Cmd.bat b/Gems/AtomContent/LookDevelopmentStudioPixar/Launch_Cmd.bat deleted file mode 100644 index 2056a5bf44..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Launch_Cmd.bat +++ /dev/null @@ -1,49 +0,0 @@ -:: Need to set up - -@echo off - -REM -REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -REM its licensors. -REM -REM For complete copyright and license terms please see the LICENSE at the root of this -REM distribution (the "License"). All use of this software is governed by the License, -REM or, if provided, by the license below or the license accompanying this file. Do not -REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -REM - -:: Set up and run LY Python CMD prompt -:: Sets up the DccScriptingInterface_Env, -:: Puts you in the CMD within the dev environment - -:: Set up window -TITLE Lumberyard DCC Scripting Interface Cmd -:: Use obvious color to prevent confusion (Grey with Yellow Text) -COLOR 8E - -%~d0 -cd %~dp0 -PUSHD %~dp0 - -:: Keep changes local -SETLOCAL enableDelayedExpansion - -CALL %~dp0\Project_Env.bat - -echo. -echo _____________________________________________________________________ -echo. -echo ~ LY DCC Scripting Interface CMD ... -echo _____________________________________________________________________ -echo. - -:: Create command prompt with environment -CALL %windir%\system32\cmd.exe - -ENDLOCAL - -:: Return to starting directory -POPD - -:END_OF_FILE diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Launch_WingIDE-7-1.bat b/Gems/AtomContent/LookDevelopmentStudioPixar/Launch_WingIDE-7-1.bat deleted file mode 100644 index 9f143fd889..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Launch_WingIDE-7-1.bat +++ /dev/null @@ -1,82 +0,0 @@ -@echo off -:: Launches Wing IDE and the DccScriptingInterface Project Files - -REM -REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -REM its licensors. -REM -REM For complete copyright and license terms please see the LICENSE at the root of this -REM distribution (the "License"). All use of this software is governed by the License, -REM or, if provided, by the license below or the license accompanying this file. Do not -REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -REM - -echo. -echo _____________________________________________________________________ -echo. -echo ~ Setting up LY DCCsi WingIDE Dev Env... -echo _____________________________________________________________________ -echo. - -:: Store current dir -%~d0 -cd %~dp0 -PUSHD %~dp0 - -:: Keep changes local -SETLOCAL enableDelayedExpansion - -SET ABS_PATH=%~dp0 -echo Current Dir, %ABS_PATH% - -:: WingIDE version Major -SET WING_VERSION_MAJOR=7 -echo WING_VERSION_MAJOR = %WING_VERSION_MAJOR% - -:: WingIDE version Major -SET WING_VERSION_MINOR=1 -echo WING_VERSION_MINOR = %WING_VERSION_MINOR% - -:: note the changed path from IDE to Pro -set WINGHOME=%PROGRAMFILES(X86)%\Wing Pro %WING_VERSION_MAJOR%.%WING_VERSION_MINOR% -echo WINGHOME = %WINGHOME% - -CALL %~dp0\Project_Env.bat - -echo. -echo _____________________________________________________________________ -echo. -echo ~ WingIDE Version %WING_VERSION_MAJOR%.%WING_VERSION_MINOR% -echo _____________________________________________________________________ -echo. - -SET WING_PROJ=%DCCSIG_PATH%\Solutions\.wing\DCCsi_%WING_VERSION_MAJOR%x.wpr -echo WING_PROJ = %WING_PROJ% - -echo. -echo _____________________________________________________________________ -echo. -echo ~ Launching %LY_PROJECT% project in WingIDE %WING_VERSION_MAJOR%.%WING_VERSION_MINOR% ... -echo _____________________________________________________________________ -echo. - - -IF EXIST "%WINGHOME%\bin\wing.exe" ( - start "" "%WINGHOME%\bin\wing.exe" "%WING_PROJ%" -) ELSE ( - Where wing.exe 2> NUL - IF ERRORLEVEL 1 ( - echo wing.exe could not be found - pause - ) ELSE ( - start "" wing.exe "%WING_PROJ%" - ) -) - -ENDLOCAL - -:: Return to starting directory -POPD - -:END_OF_FILE diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Project_Env.bat b/Gems/AtomContent/LookDevelopmentStudioPixar/Project_Env.bat deleted file mode 100644 index 74bc374ab8..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Project_Env.bat +++ /dev/null @@ -1,74 +0,0 @@ -@echo off -:: Sets up environment for Lumberyard DCC tools and code access - -REM -REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -REM its licensors. -REM -REM For complete copyright and license terms please see the LICENSE at the root of this -REM distribution (the "License"). All use of this software is governed by the License, -REM or, if provided, by the license below or the license accompanying this file. Do not -REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -REM - - -:: Store current dir -%~d0 -cd %~dp0 -PUSHD %~dp0 - -for %%a in (.) do set LY_PROJECT=%%~na - -echo. -echo _____________________________________________________________________ -echo. -echo ~ Setting up LY DSI PROJECT Environment ... -echo _____________________________________________________________________ -echo. - -echo LY_PROJECT = %LY_PROJECT% - -:: Put you project env vars and overrides here - -:: chanhe the relative path up to dev -set DEV_REL_PATH=../../.. -set ABS_PATH=%~dp0 - -:: Override the default maya version -set MAYA_VERSION=2020 -echo MAYA_VERSION = %MAYA_VERSION% - -set LY_PROJECT_PATH=%ABS_PATH% -echo LY_PROJECT_PATH = %LY_PROJECT_PATH% - -:: Change to root Lumberyard dev dir -CD /d %LY_PROJECT_PATH%\%DEV_REL_PATH% -set LY_DEV=%CD% -echo LY_DEV = %LY_DEV% - -CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env.bat - -rem :: Constant Vars (Global) -rem SET LYPY_GDEBUG=0 -rem echo LYPY_GDEBUG = %LYPY_GDEBUG% -rem SET LYPY_DEV_MODE=0 -rem echo LYPY_DEV_MODE = %LYPY_DEV_MODE% -rem SET LYPY_DEBUGGER=WING -rem echo LYPY_DEBUGGER = %LYPY_DEBUGGER% - -:: Restore original directory -popd - -:: Change to root dir -CD /D %ABS_PATH% - -:: if the user has set up a custom env call it -IF EXIST "%~dp0User_Env.bat" CALL %~dp0User_Env.bat - -GOTO END_OF_FILE - -:: Return to starting directory -POPD - -:END_OF_FILE diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/gem.json b/Gems/AtomContent/LookDevelopmentStudioPixar/gem.json deleted file mode 100644 index 6481cb2e57..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/gem.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "gem_name": "LookDevelopmentStudioPixar", - "GemFormatVersion": 3, - "Uuid": "fe1e0506204f49a28ab352636ec62dfe", - "Name": "LookDevelopmentStudioPixar", - "DisplayName": "LookDevelopmentStudioPixar", - "Version": "0.1.0", - "LinkType": "NoCode", - "Summary": "This is a Asset Gem that includes a modified version of the Pixar Look Development Studio (public domain, non-licensed.) https:\/\/renderman.pixar.com\/look-development-studio ", - "Tags": ["Asset"], - "IconPath": "preview.png" -} diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/preview.png b/Gems/AtomContent/LookDevelopmentStudioPixar/preview.png deleted file mode 100644 index b6f5875b83..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/preview.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:416751d9b01390dce5951e47e75e9e4e0c4a561424486a41179c230fd2d919b7 -size 30881 diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/workspace.mel b/Gems/AtomContent/LookDevelopmentStudioPixar/workspace.mel deleted file mode 100644 index b43657866d..0000000000 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/workspace.mel +++ /dev/null @@ -1,88 +0,0 @@ -//Maya 2020 Project Definition - -workspace -fr "fluidCache" ""; -workspace -fr "images" "Assets/Textures"; -workspace -fr "JT_ATF" ""; -workspace -fr "offlineEdit" ".maya_data/scenes/edits"; -workspace -fr "STEP_ATF Export" ""; -workspace -fr "furShadowMap" ""; -workspace -fr "SVG" ""; -workspace -fr "scripts" "Maya/Scripts"; -workspace -fr "DAE_FBX" ""; -workspace -fr "shaders" "Maya/Shaders"; -workspace -fr "NX_ATF" ""; -workspace -fr "furFiles" ""; -workspace -fr "CATIAV5_ATF Export" ""; -workspace -fr "OBJ" ".maya_data/obj"; -workspace -fr "PARASOLID_ATF Export" ""; -workspace -fr "FBX export" "Assets/Objects"; -workspace -fr "furEqualMap" ""; -workspace -fr "textures" "Assets/textures"; -workspace -fr "BIF" ""; -workspace -fr "lights" ".maya_data/renderData/shaders"; -workspace -fr "DAE_FBX export" ""; -workspace -fr "aliasWire" ".maya_data/data"; -workspace -fr "CATIAV5_ATF" ""; -workspace -fr "SAT_ATF Export" ""; -workspace -fr "movie" ".maya_data/movies"; -workspace -fr "ASS Export" ""; -workspace -fr "autoSave" ".maya_data/autoSave"; -workspace -fr "move" ".maya_data"; -workspace -fr "mayaAscii" ""; -workspace -fr "NX_ATF Export" ""; -workspace -fr "sound" ".maya_data/sound"; -workspace -fr "mayaBinary" ""; -workspace -fr "timeEditor" ""; -workspace -fr "RIBexport" ".maya_data/data"; -workspace -fr "DWG_ATF" ""; -workspace -fr "mentalray" ".maya_data/renderData/mentalray"; -workspace -fr "JT_ATF Export" ""; -workspace -fr "iprImages" ".maya_data/renderData/iprImages"; -workspace -fr "FBX" "Assets/Objects"; -workspace -fr "renderData" ".maya_data/renderData"; -workspace -fr "CATIAV4_ATF" ""; -workspace -fr "fileCache" ""; -workspace -fr "eps" ""; -workspace -fr "Fbx" "Objects"; -workspace -fr "IGESexport" ".maya_data/data"; -workspace -fr "3dPaintTextures" ".maya_data/3dPaintTextures"; -workspace -fr "translatorData" ""; -workspace -fr "mel" ".maya_data/mel"; -workspace -fr "DXF_ATF Export" ""; -workspace -fr "IGES" ".maya_data/data"; -workspace -fr "particles" ".maya_data/particles"; -workspace -fr "DXFexport" ".maya_data/data"; -workspace -fr "DXF_ATF" ""; -workspace -fr "scene" "Assets/Objects"; -workspace -fr "renderScenes" ".maya_data/renderScenes"; -workspace -fr "SAT_ATF" ""; -workspace -fr "PROE_ATF" ""; -workspace -fr "WIRE_ATF Export" ""; -workspace -fr "sourceImages" "ArtSource/Images"; -workspace -fr "RIB" ".maya_data/data"; -workspace -fr "furImages" ""; -workspace -fr "clips" ".maya_data/clips"; -workspace -fr "Adobe(R) Illustrator(R)" ".maya_data/data"; -workspace -fr "animExport" ".maya_data/data"; -workspace -fr "mentalRay" ".maya_data/mentalRay"; -workspace -fr "STEP_ATF" ""; -workspace -fr "DWG_ATF Export" ""; -workspace -fr "depth" ".maya_data/renderData/depth"; -workspace -fr "sceneAssembly" ""; -workspace -fr "IGES_ATF Export" ""; -workspace -fr "teClipExports" ""; -workspace -fr "IGES_ATF" ""; -workspace -fr "PARASOLID_ATF" ""; -workspace -fr "ASS" ""; -workspace -fr "Substance" ".maya_data/data"; -workspace -fr "audio" ".maya_data/sound"; -workspace -fr "EPS" ".maya_data/data"; -workspace -fr "Alembic" "Assets/Objects"; -workspace -fr "diskCache" ".maya_data/cache"; -workspace -fr "illustrator" ""; -workspace -fr "WIRE_ATF" ""; -workspace -fr "templates" "ArtSource/SceneTemplates"; -workspace -fr "animImport" ".maya_data/data"; -workspace -fr "OBJexport" "Assets/Objects"; -workspace -fr "furAttrMap" ""; -workspace -fr "DXF" ".maya_data/data"; diff --git a/Gems/AtomContent/ReferenceMaterials/CMakeLists.txt b/Gems/AtomContent/ReferenceMaterials/CMakeLists.txt new file mode 100644 index 0000000000..9afc5af5a7 --- /dev/null +++ b/Gems/AtomContent/ReferenceMaterials/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +# This will export its "SourcePaths" to the generated "cmake_dependencies..assetbuilder.setreg" +if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_create_alias(NAME AtomContent_ReferenceMaterials.Builders NAMESPACE Gem) +endif() diff --git a/Gems/AtomContent/Sponza/.gitignore b/Gems/AtomContent/Sponza/.gitignore index c58f3de65f..8bbb0be455 100644 --- a/Gems/AtomContent/Sponza/.gitignore +++ b/Gems/AtomContent/Sponza/.gitignore @@ -1,3 +1,4 @@ /.maya_data/* /.mayaSwatches/* -*.swatch \ No newline at end of file +*.swatch +[Uu]ser_env.bat \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/.src/objects/sponza.ma b/Gems/AtomContent/Sponza/.src/objects/sponza.ma new file mode 100644 index 0000000000..fabe9dd9ee --- /dev/null +++ b/Gems/AtomContent/Sponza/.src/objects/sponza.ma @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c95e08274ea0051ee35f415918eaf1530f05475d6265f2ad7ec7c1ff79d29f2b +size 40549297 diff --git a/Gems/AtomContent/Sponza/.src/objects/sponza_cleanup.mb b/Gems/AtomContent/Sponza/.src/objects/sponza_cleanup.mb new file mode 100644 index 0000000000..bdd51c6f8c --- /dev/null +++ b/Gems/AtomContent/Sponza/.src/objects/sponza_cleanup.mb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b77710f70b80578339c826f51eef4d964e1136f27e67ff26a348542feec16dfa +size 22804176 diff --git a/Gems/AtomContent/Sponza/ArtSource/stub b/Gems/AtomContent/Sponza/.src/stub similarity index 100% rename from Gems/AtomContent/Sponza/ArtSource/stub rename to Gems/AtomContent/Sponza/.src/stub diff --git a/Gems/AtomContent/Sponza/ArtSource/objects/sponza.ma b/Gems/AtomContent/Sponza/ArtSource/objects/sponza.ma deleted file mode 100644 index 5bea07b7d6..0000000000 --- a/Gems/AtomContent/Sponza/ArtSource/objects/sponza.ma +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7250488d0ba6115089c5f83d6c352826b41d711550ca828853a139129ffcff9f -size 40549260 diff --git a/Gems/AtomContent/Sponza/ArtSource/objects/sponza_cleanup.mb b/Gems/AtomContent/Sponza/ArtSource/objects/sponza_cleanup.mb deleted file mode 100644 index 882496f2b0..0000000000 --- a/Gems/AtomContent/Sponza/ArtSource/objects/sponza_cleanup.mb +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9d3c18d76f00688d15c54736ef3d8c953df08baf46a796fa71627de18bdb3c0f -size 22804332 diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza.fbx b/Gems/AtomContent/Sponza/Assets/objects/sponza.fbx index 9061666968..38752bf32a 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza.fbx +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza.fbx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35a880abc018520d4b30d21a64f7a14fca74d936593320d5afd03ddf25771bf3 -size 9176416 +oid sha256:e24948f9f477a3a167e50a80b04148d0a598d8c40bed86d51870daa8842ce5dd +size 9175808 diff --git a/Gems/AtomContent/Sponza/CMakeLists.txt b/Gems/AtomContent/Sponza/CMakeLists.txt new file mode 100644 index 0000000000..05f3553ba2 --- /dev/null +++ b/Gems/AtomContent/Sponza/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# +# This will export its "SourcePaths" to the generated "cmake_dependencies..assetbuilder.setreg" +if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_create_alias(NAME AtomContent_Sponza.Builders NAMESPACE Gem) +endif() \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Launch_Maya_2020.bat b/Gems/AtomContent/Sponza/Launch_Maya_2020.bat deleted file mode 100644 index 224d8c15d0..0000000000 --- a/Gems/AtomContent/Sponza/Launch_Maya_2020.bat +++ /dev/null @@ -1,67 +0,0 @@ -@echo off - -REM -REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -REM its licensors. -REM -REM For complete copyright and license terms please see the LICENSE at the root of this -REM distribution (the "License"). All use of this software is governed by the License, -REM or, if provided, by the license below or the license accompanying this file. Do not -REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -REM - -%~d0 -cd %~dp0 -PUSHD %~dp0 - -echo ________________________________ -echo ~ calling PROJ_Env.bat - -:: Keep changes local -SETLOCAL enableDelayedExpansion - -:: PY version Major -set DCCSI_PY_VERSION_MAJOR=2 -echo DCCSI_PY_VERSION_MAJOR = %DCCSI_PY_VERSION_MAJOR% - -:: PY version Major -set DCCSI_PY_VERSION_MINOR=7 -echo DCCSI_PY_VERSION_MINOR = %DCCSI_PY_VERSION_MINOR% - -:: Maya Version -set MAYA_VERSION=2020 -echo MAYA_VERSION = %MAYA_VERSION% - -:: if a local customEnv.bat exists, run it -IF EXIST "%~dp0Project_Env.bat" CALL %~dp0Project_Env.bat - -echo ________________________________ -echo Launching Maya %MAYA_VERSION% for Lumberyard... - -:::: Set Maya native project acess to this project -::set MAYA_PROJECT=%LY_PROJECT% -::echo MAYA_PROJECT = %MAYA_PROJECT% - -:: DX11 Viewport -Set MAYA_VP2_DEVICE_OVERRIDE = VirtualDeviceDx11 - -:: Default to the right version of Maya if we can detect it... and launch -IF EXIST "%MAYA_LOCATION%\bin\Maya.exe" ( - start "" "%MAYA_LOCATION%\bin\Maya.exe" %* -) ELSE ( - Where maya.exe 2> NUL - IF ERRORLEVEL 1 ( - echo Maya.exe could not be found - pause - ) ELSE ( - start "" Maya.exe %* - ) -) - -:: Return to starting directory -POPD - -:END_OF_FILE - -exit /b 0 diff --git a/Gems/AtomContent/Sponza/Launch_WingIDE-7-1.bat b/Gems/AtomContent/Sponza/Launch_WingIDE-7-1.bat deleted file mode 100644 index f73fb640d5..0000000000 --- a/Gems/AtomContent/Sponza/Launch_WingIDE-7-1.bat +++ /dev/null @@ -1,82 +0,0 @@ -@echo off -REM -REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -REM its licensors. -REM -REM For complete copyright and license terms please see the LICENSE at the root of this -REM distribution (the "License"). All use of this software is governed by the License, -REM or, if provided, by the license below or the license accompanying this file. Do not -REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -REM - -:: Launches Wing IDE and the DccScriptingInterface Project Files - -echo. -echo _____________________________________________________________________ -echo. -echo ~ Setting up LY DCCsi WingIDE Dev Env... -echo _____________________________________________________________________ -echo. - -:: Store current dir -%~d0 -cd %~dp0 -PUSHD %~dp0 - -:: Keep changes local -SETLOCAL enableDelayedExpansion - -SET ABS_PATH=%~dp0 -echo Current Dir, %ABS_PATH% - -:: WingIDE version Major -SET WING_VERSION_MAJOR=7 -echo WING_VERSION_MAJOR = %WING_VERSION_MAJOR% - -:: WingIDE version Major -SET WING_VERSION_MINOR=1 -echo WING_VERSION_MINOR = %WING_VERSION_MINOR% - -:: note the changed path from IDE to Pro -set WINGHOME=%PROGRAMFILES(X86)%\Wing Pro %WING_VERSION_MAJOR%.%WING_VERSION_MINOR% -echo WINGHOME = %WINGHOME% - -CALL %~dp0\Project_Env.bat - -echo. -echo _____________________________________________________________________ -echo. -echo ~ WingIDE Version %WING_VERSION_MAJOR%.%WING_VERSION_MINOR% -echo _____________________________________________________________________ -echo. - -SET WING_PROJ=%DCCSIG_PATH%\Solutions\.wing\DCCsi_%WING_VERSION_MAJOR%x.wpr -echo WING_PROJ = %WING_PROJ% - -echo. -echo _____________________________________________________________________ -echo. -echo ~ Launching %LY_PROJECT% project in WingIDE %WING_VERSION_MAJOR%.%WING_VERSION_MINOR% ... -echo _____________________________________________________________________ -echo. - - -IF EXIST "%WINGHOME%\bin\wing.exe" ( - start "" "%WINGHOME%\bin\wing.exe" "%WING_PROJ%" -) ELSE ( - Where wing.exe 2> NUL - IF ERRORLEVEL 1 ( - echo wing.exe could not be found - pause - ) ELSE ( - start "" wing.exe "%WING_PROJ%" - ) -) - -ENDLOCAL - -:: Return to starting directory -POPD - -:END_OF_FILE diff --git a/Gems/AtomContent/Sponza/Project_Env.bat b/Gems/AtomContent/Sponza/Project_Env.bat index b06acfaa9a..7df40049f3 100644 --- a/Gems/AtomContent/Sponza/Project_Env.bat +++ b/Gems/AtomContent/Sponza/Project_Env.bat @@ -15,6 +15,7 @@ REM cd %~dp0 PUSHD %~dp0 +:: This is a legacy envar which is being migrated to LY_PROJECT_NAME for %%a in (.) do set LY_PROJECT=%%~na echo. @@ -26,6 +27,9 @@ echo. echo LY_PROJECT = %LY_PROJECT% +set LY_PROJECT_NAME=%LY_PROJECT% +echo LY_PROJECT_NAME = %LY_PROJECT_NAME% + :: Put you project env vars and overrides here :: chanhe the relative path up to dev diff --git a/Gems/AtomContent/Sponza/Registry/AssetProcessorPlatformConfig.setreg b/Gems/AtomContent/Sponza/Registry/AssetProcessorPlatformConfig.setreg new file mode 100644 index 0000000000..778d05dee9 --- /dev/null +++ b/Gems/AtomContent/Sponza/Registry/AssetProcessorPlatformConfig.setreg @@ -0,0 +1,14 @@ +{ + "Amazon": { + "AssetProcessor": { + "Settings": { + // ------------------------------------------------------------------------------ + // Sample Gems, Block source folders + // ------------------------------------------------------------------------------ + "Exclude Work In Progress Folders": { + "pattern": ".*\\\\/.[Ss]rc\\\\/.*" + } + } + } + } +} diff --git a/Gems/AtomContent/Sponza/Launch_Cmd.bat b/Gems/AtomContent/Sponza/Tools/Launch_Cmd.bat similarity index 95% rename from Gems/AtomContent/Sponza/Launch_Cmd.bat rename to Gems/AtomContent/Sponza/Tools/Launch_Cmd.bat index f69d4ef49c..570bc7c86d 100644 --- a/Gems/AtomContent/Sponza/Launch_Cmd.bat +++ b/Gems/AtomContent/Sponza/Tools/Launch_Cmd.bat @@ -1,5 +1,4 @@ @echo off - REM REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or REM its licensors. @@ -11,6 +10,7 @@ REM remove or modify any license notices. This file is distributed on an "AS IS" REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. REM +@echo off :: Set up and run LY Python CMD prompt :: Sets up the DccScriptingInterface_Env, :: Puts you in the CMD within the dev environment @@ -27,7 +27,7 @@ PUSHD %~dp0 :: Keep changes local SETLOCAL enableDelayedExpansion -CALL %~dp0\Project_Env.bat +CALL %~dp0\..\Project_Env.bat echo. echo _____________________________________________________________________ @@ -44,4 +44,4 @@ ENDLOCAL :: Return to starting directory POPD -:END_OF_FILE +:END_OF_FILE \ No newline at end of file diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Launch_Maya_2020.bat b/Gems/AtomContent/Sponza/Tools/Maya/Launch_Maya_2020.bat similarity index 84% rename from Gems/AtomContent/LookDevelopmentStudioPixar/Launch_Maya_2020.bat rename to Gems/AtomContent/Sponza/Tools/Maya/Launch_Maya_2020.bat index fab2bb21fd..3f53d90681 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Launch_Maya_2020.bat +++ b/Gems/AtomContent/Sponza/Tools/Maya/Launch_Maya_2020.bat @@ -1,8 +1,4 @@ -:: Launches maya wityh a bunch of local hooks for Lumberyard -:: ToDo: move all of this to a .json data driven boostrapping system - @echo off - REM REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or REM its licensors. @@ -14,6 +10,11 @@ REM remove or modify any license notices. This file is distributed on an "AS IS" REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. REM +:: Launches maya wityh a bunch of local hooks for Lumberyard +:: ToDo: move all of this to a .json data driven boostrapping system + +@echo off + %~d0 cd %~dp0 PUSHD %~dp0 @@ -37,7 +38,7 @@ set MAYA_VERSION=2020 echo MAYA_VERSION = %MAYA_VERSION% :: if a local customEnv.bat exists, run it -IF EXIST "%~dp0Project_Env.bat" CALL %~dp0Project_Env.bat +IF EXIST "%~dp0..\..\Project_Env.bat" CALL %~dp0..\..\Project_Env.bat echo ________________________________ echo Launching Maya %MAYA_VERSION% for Lumberyard... @@ -51,15 +52,15 @@ Set MAYA_VP2_DEVICE_OVERRIDE = VirtualDeviceDx11 :: Default to the right version of Maya if we can detect it... and launch IF EXIST "%MAYA_LOCATION%\bin\Maya.exe" ( - start "" "%MAYA_LOCATION%\bin\Maya.exe" %* + start "" "%MAYA_LOCATION%\bin\Maya.exe" %* ) ELSE ( - Where maya.exe 2> NUL - IF ERRORLEVEL 1 ( - echo Maya.exe could not be found - pause - ) ELSE ( - start "" Maya.exe %* - ) + Where maya.exe 2> NUL + IF ERRORLEVEL 1 ( + echo Maya.exe could not be found + pause + ) ELSE ( + start "" Maya.exe %* + ) ) :: Return to starting directory @@ -67,4 +68,4 @@ POPD :END_OF_FILE -exit /b 0 +exit /b 0 \ No newline at end of file diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/LyProjectRootStub b/Gems/AtomContent/Sponza/Tools/Maya/Scripts/stub similarity index 100% rename from Gems/AtomContent/LookDevelopmentStudioPixar/LyProjectRootStub rename to Gems/AtomContent/Sponza/Tools/Maya/Scripts/stub diff --git a/Gems/AtomContent/Sponza/User_env.bat.template b/Gems/AtomContent/Sponza/User_env.bat.template new file mode 100644 index 0000000000..99bc7a951d --- /dev/null +++ b/Gems/AtomContent/Sponza/User_env.bat.template @@ -0,0 +1 @@ +set LY_DEV=C:\Depot\o3de-engine \ No newline at end of file diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/Brass/brass_bake.spp b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/Brass/brass_bake.spp deleted file mode 100644 index 0252c59ba2..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/Brass/brass_bake.spp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bb8c1839f46df4623818bc1b02f626d85d8f83d77cbeabd0d56c6a5c997c3ab3 -size 495250984 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/Brass/low_Default_BaseColor.png b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/Brass/low_Default_BaseColor.png deleted file mode 100644 index 7cbf4b4c23..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/Brass/low_Default_BaseColor.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9bb547a502aa028624e3f95491d2e459860db5fdc5551eece757c271362c902d -size 42981863 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/Brass/low_Default_Metallic.png b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/Brass/low_Default_Metallic.png deleted file mode 100644 index 93d17390aa..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/Brass/low_Default_Metallic.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:962248929564f7a3a2a25813ba8ab83d72f2f4d8db71eb495bd650ad4eca5c25 -size 8681159 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/Brass/low_Default_Roughness.png b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/Brass/low_Default_Roughness.png deleted file mode 100644 index 2d971c65ed..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/Brass/low_Default_Roughness.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2c5998edda6eb34ace8b7a5f63e72f922e0daebb6aeb453142b31e605157736d -size 17366289 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/bake_channels.psd b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/bake_channels.psd deleted file mode 100644 index bfa8911b3f..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/bake_channels.psd +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a79b82df3f6f908b2ed31f9247d9befde7daf0ff53c87479920c0463cc12d437 -size 1308624196 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/high.fbx b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/high.fbx deleted file mode 100644 index fc13f2345c..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/high.fbx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b9892d5de71db58217f9c942f542c058891ab2f0949443c48111aa71fe621cae -size 128078160 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/low.fbx b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/low.fbx deleted file mode 100644 index a72ddaec16..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/low.fbx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:353ff22364447796ec01799a16e6ee39fbcde337a5fee4de409069316eccbb8f -size 6942256 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/marmoset_bake.tbscene b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/marmoset_bake.tbscene deleted file mode 100644 index 1b7605ff10..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/marmoset_bake.tbscene +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e934a8772f33e6c7bc11e70071c5d14147d01d123a5bed3bd51fc861047f17cb -size 305364828 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/stone/low_Default_BaseColor.png b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/stone/low_Default_BaseColor.png deleted file mode 100644 index c880cef561..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/stone/low_Default_BaseColor.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:247402172cb0539faaae937659507bd72087e629004e3eb2e8f67df97063a92f -size 70531613 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/stone/stone_bake.spp b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/stone/stone_bake.spp deleted file mode 100644 index a8249fbc6b..0000000000 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/.wip/stone/stone_bake.spp +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aa4f9fbb9fc332fa0fb3f35df3b21ef72439073a854ad55d637efbed89ad3b3c -size 562609478 diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt b/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt index 33fad00cbe..ea4f4259da 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt @@ -61,6 +61,21 @@ ly_add_target( BUILD_DEPENDENCIES PRIVATE Gem::AtomLyIntegration_CommonFeatures.Static + RUNTIME_DEPENDENCIES + Gem::Atom_RPI.Private + Gem::Atom_Feature_Common +) + +# The AtomLyIntegration_CommonFeatures module is used for Clients and Servers +ly_create_alias(NAME AtomLyIntegration_CommonFeatures.Clients NAMESPACE Gem + TARGETS + Gem::AtomLyIntegration_CommonFeatures + Gem::GradientSignal.Clients +) +ly_create_alias(NAME AtomLyIntegration_CommonFeatures.Servers NAMESPACE Gem + TARGETS + Gem::AtomLyIntegration_CommonFeatures + Gem::GradientSignal.Servers ) if(PAL_TRAIT_BUILD_HOST_TOOLS) @@ -94,5 +109,44 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) Legacy::Editor.Headers Legacy::EditorCommon Legacy::CryCommon + RUNTIME_DEPENDENCIES + Gem::Atom_RPI.Editor + Gem::Atom_Feature_Common.Editor + ) + + # The AtomLyIntegration_CommonFeatures.Editor module is used for Builders and Tools + ly_create_alias(NAME AtomLyIntegration_CommonFeatures.Builders NAMESPACE Gem + TARGETS + Gem::AtomLyIntegration_CommonFeatures.Editor + Gem::Atom_RPI.Builders + Gem::GradientSignal.Builders ) + ly_create_alias(NAME AtomLyIntegration_CommonFeatures.Tools NAMESPACE Gem + TARGETS + Gem::AtomLyIntegration_CommonFeatures.Editor + Gem::GradientSignal.Tools + ) + + # AtomLyIntergration_CommonFeatures gem targets are required as part of the Editor and AssetProcessor + # due to the AZ::Render::EditorDirectionalLightComponent, AZ::Render::EditorMeshComponent, + # AZ::Render::EditorGridComponent, AZ::Render::EditorHDRiSkyboxComponent, + # AZ::Render::EditorImageBasedLightComponent being saved as part of the DefaultLevel.prefab + ly_enable_gems(GEMS AtomLyIntegration_CommonFeatures VARIANTS Tools + TARGETS Editor) + ly_enable_gems(GEMS AtomLyIntegration_CommonFeatures VARIANTS Builders + TARGETS AssetBuilder AssetProcessor AssetProcessorBatch) endif() + + +# Added dependencies to the Client and Server Launchers +get_property(LY_PROJECTS_TARGET_NAME GLOBAL PROPERTY LY_PROJECTS_TARGET_NAME) +foreach(project_name IN LISTS LY_PROJECTS_TARGET_NAME) + # Add gem as a dependency of the Clients Launcher + ly_enable_gems(PROJECT_NAME ${project_name} GEMS AtomLyIntegration_CommonFeatures VARIANTS Clients + TARGETS ${project_name}.GameLauncher) + # Add gem as a dependency of the Servers Launcher + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) + ly_enable_gems(PROJECT_NAME ${project_name} GEMS AtomLyIntegration_CommonFeatures VARIANTS Servers + TARGETS ${project_name}.ServerLauncher) + endif() +endforeach() diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h index f4cb319c2f..9279326333 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h @@ -143,6 +143,13 @@ namespace AZ //! Sets the type of Pcf (percentage-closer filtering) to use. virtual void SetPcfMethod(PcfMethod method) = 0; + + //! Gets the Esm exponent. Higher values produce a steeper falloff between light and shadow. + virtual float GetEsmExponent() const = 0; + + //! Sets the Esm exponent. Higher values produce a steeper falloff between light and shadow. + virtual void SetEsmExponent(float exponent) = 0; + }; //! The EBus for requests to for setting and getting light component properties. diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h index 31cdb34ddd..e003d6a178 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h @@ -66,6 +66,7 @@ namespace AZ float m_boundaryWidthInDegrees = 0.25f; uint16_t m_predictionSampleCount = 4; uint16_t m_filteringSampleCount = 12; + float m_esmExponent = 87.0f; // The following functions provide information to an EditContext... @@ -124,6 +125,8 @@ namespace AZ //! Returns true if pcf boundary search is disabled. bool IsPcfBoundarySearchDisabled() const; + //! Returns true if exponential shadow maps are disabled. + bool IsEsmDisabled() const; }; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp index 8f10204ae9..71bb17d6c0 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp @@ -11,6 +11,7 @@ */ #include +#include namespace AZ { @@ -21,7 +22,7 @@ namespace AZ if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(5) // ATOM-14637 + ->Version(6) // ATOM-15654 ->Field("LightType", &AreaLightComponentConfig::m_lightType) ->Field("Color", &AreaLightComponentConfig::m_color) ->Field("IntensityMode", &AreaLightComponentConfig::m_intensityMode) @@ -41,7 +42,8 @@ namespace AZ ->Field("Softening Boundary Width", &AreaLightComponentConfig::m_boundaryWidthInDegrees) ->Field("Prediction Sample Count", &AreaLightComponentConfig::m_predictionSampleCount) ->Field("Filtering Sample Count", &AreaLightComponentConfig::m_filteringSampleCount) - ->Field("Pcf Method", &AreaLightComponentConfig::m_pcfMethod); + ->Field("Pcf Method", &AreaLightComponentConfig::m_pcfMethod) + ->Field("Esm Exponent", &AreaLightComponentConfig::m_esmExponent) ; } } @@ -134,23 +136,15 @@ namespace AZ case PhotometricUnit::Nit: return 0.0f; case PhotometricUnit::Ev100Luminance: - return -10.0f; + return AZStd::numeric_limits::lowest(); } return 0.0f; } float AreaLightComponentConfig::GetIntensityMax() const { - switch (m_intensityMode) - { - case PhotometricUnit::Candela: - case PhotometricUnit::Lumen: - case PhotometricUnit::Nit: - return 1'000'000.0f; - case PhotometricUnit::Ev100Luminance: - return 20.0f; - } - return 0.0f; + // While there is no hard-max, a max must be included when there is a hard min. + return AZStd::numeric_limits::max(); } float AreaLightComponentConfig::GetIntensitySoftMin() const @@ -200,5 +194,11 @@ namespace AZ return m_pcfMethod != PcfMethod::BoundarySearch; } + + bool AreaLightComponentConfig::IsEsmDisabled() const + { + return !(m_shadowFilterMethod == ShadowFilterMethod::Esm || m_shadowFilterMethod == ShadowFilterMethod::EsmPcf); + } + } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp index c1c957ed4c..f7e0d15c92 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp @@ -84,7 +84,9 @@ namespace AZ::Render ->Event("SetFilteringSampleCount", &AreaLightRequestBus::Events::SetFilteringSampleCount) ->Event("GetPcfMethod", &AreaLightRequestBus::Events::GetPcfMethod) ->Event("SetPcfMethod", &AreaLightRequestBus::Events::SetPcfMethod) - + ->Event("GetEsmExponent", &AreaLightRequestBus::Events::GetEsmExponent) + ->Event("SetEsmExponent", &AreaLightRequestBus::Events::SetEsmExponent) + ->VirtualProperty("AttenuationRadius", "GetAttenuationRadius", "SetAttenuationRadius") ->VirtualProperty("Color", "GetColor", "SetColor") ->VirtualProperty("EmitsLightBothDirections", "GetEmitsLightBothDirections", "SetEmitsLightBothDirections") @@ -101,8 +103,9 @@ namespace AZ::Render ->VirtualProperty("SofteningBoundaryWidthAngle", "GetSofteningBoundaryWidthAngle", "SetSofteningBoundaryWidthAngle") ->VirtualProperty("PredictionSampleCount", "GetPredictionSampleCount", "SetPredictionSampleCount") ->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount") - ->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod"); - ; + ->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod") + ->VirtualProperty("EsmExponent", "GetEsmExponent", "SetEsmExponent"); + ; } } @@ -314,6 +317,7 @@ namespace AZ::Render m_lightShapeDelegate->SetPredictionSampleCount(m_configuration.m_predictionSampleCount); m_lightShapeDelegate->SetFilteringSampleCount(m_configuration.m_filteringSampleCount); m_lightShapeDelegate->SetPcfMethod(m_configuration.m_pcfMethod); + m_lightShapeDelegate->SetEsmExponent(m_configuration.m_esmExponent); } } } @@ -565,6 +569,20 @@ namespace AZ::Render } } + float AreaLightComponentController::GetEsmExponent() const + { + return m_configuration.m_esmExponent; + } + + void AreaLightComponentController::SetEsmExponent(float esmExponent) + { + m_configuration.m_esmExponent = esmExponent; + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetEsmExponent(esmExponent); + } + } + void AreaLightComponentController::CreateLightShapeDelegate() { switch (m_configuration.m_lightType) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h index b5f342a522..a65f0be45f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h @@ -92,6 +92,8 @@ namespace AZ void SetFilteringSampleCount(uint32_t count) override; PcfMethod GetPcfMethod() const override; void SetPcfMethod(PcfMethod method) override; + float GetEsmExponent() const override; + void SetEsmExponent(float exponent) override; void HandleDisplayEntityViewport( const AzFramework::ViewportInfo& viewportInfo, diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp index 8abc790ada..b8b82bc8bb 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp @@ -175,5 +175,13 @@ namespace AZ::Render } } + void DiskLightDelegate::SetEsmExponent(float exponent) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetEsmExponent(GetLightHandle(), exponent); + } + } + } // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h index 5511b435d4..3e2704fd61 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h @@ -51,6 +51,7 @@ namespace AZ void SetPredictionSampleCount(uint32_t count) override; void SetFilteringSampleCount(uint32_t count) override; void SetPcfMethod(PcfMethod method) override; + void SetEsmExponent(float exponent) override; private: diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp index 992b6319d8..378059b766 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp @@ -179,8 +179,19 @@ namespace AZ ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) - ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled); - ; + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled) + ->DataElement( + Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_esmExponent, "Esm Exponent", + "Exponent used by Esm shadows. " + "Larger values increase the sharpness of the border between lit and unlit areas.") + ->Attribute(Edit::Attributes::Min, 50.0f) + ->Attribute(Edit::Attributes::Max, 5000.0f) + ->Attribute(AZ::Edit::Attributes::Decimals, 0) + ->Attribute(AZ::Edit::Attributes::SliderCurveMidpoint, 0.05f) + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsEsmDisabled) + ; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h index da221341c3..d106a13c07 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h @@ -63,6 +63,7 @@ namespace AZ void SetPredictionSampleCount([[maybe_unused]] uint32_t count) override {}; void SetFilteringSampleCount([[maybe_unused]] uint32_t count) override {}; void SetPcfMethod([[maybe_unused]] PcfMethod method) override {}; + void SetEsmExponent([[maybe_unused]] float esmExponent) override{}; protected: void InitBase(EntityId entityId); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h index b3f5fb6014..3ebf3802fa 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h @@ -85,6 +85,8 @@ namespace AZ virtual void SetFilteringSampleCount(uint32_t count) = 0; //! Sets the Pcf (Percentage closer filtering) method to use. virtual void SetPcfMethod(PcfMethod method) = 0; + //! Sets the Esm exponent to use. Higher values produce a steeper falloff between light and shadow. + virtual void SetEsmExponent(float exponent) = 0; }; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp index afb63dce9b..e701e3c22a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp @@ -122,5 +122,14 @@ namespace AZ } } + void SphereLightDelegate::SetEsmExponent(float esmExponent) + { + if (GetShadowsEnabled() && GetLightHandle().IsValid()) + { + GetFeatureProcessor()->SetEsmExponent(GetLightHandle(), esmExponent); + } + } + + } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h index 178540fd01..f964254d76 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h @@ -41,6 +41,7 @@ namespace AZ void SetPredictionSampleCount(uint32_t count) override; void SetFilteringSampleCount(uint32_t count) override; void SetPcfMethod(PcfMethod method) override; + void SetEsmExponent(float esmExponent) override; private: diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index e307bfcd07..80de8b03e4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -32,7 +32,7 @@ namespace AZ { namespace Render { - const char* EditorMaterialComponent::GenerateMaterialsButtonText = "Generate Source Materials..."; + const char* EditorMaterialComponent::GenerateMaterialsButtonText = "Generate/Manage Source Materials..."; const char* EditorMaterialComponent::GenerateMaterialsToolTipText = "Generate editable source material files from materials provided by the model."; const char* EditorMaterialComponent::ResetMaterialsButtonText = "Reset Materials"; @@ -228,10 +228,13 @@ namespace AZ action = menu->addAction(GenerateMaterialsButtonText, [this]() { OpenMaterialExporter(); }); action->setToolTip(GenerateMaterialsToolTipText); + menu->addSeparator(); + action = menu->addAction(ResetMaterialsButtonText, [this]() { ResetMaterialSlots(); }); action->setToolTip(ResetMaterialsToolTipText); menu->addSeparator(); + action = menu->addAction("Clear Model Materials", [this]() { AzToolsFramework::ScopedUndoBatch undoBatch("Clearing model materials."); SetDirty(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp index 34cc53a326..3a23c9be55 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp @@ -104,7 +104,7 @@ namespace AZ // Constructing a dialog with a table to display all configurable material export items QDialog dialog(activeWindow); - dialog.setWindowTitle("Generate Source Materials"); + dialog.setWindowTitle("Generate/Manage Source Materials"); const QStringList headerLabels = { "Material Slot", "Material Filename", "Overwrite" }; const int MaterialSlotColumn = 0; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index 65fa7bc286..cbde73962d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -273,32 +273,24 @@ namespace AZ QAction* action = nullptr; - action = menu.addAction("Open Material Editor...", [this]() { EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, ""); }); - action->setVisible(!m_materialAsset.GetId().IsValid()); - - action = menu.addAction("Clear", [this]() { Clear(); }); - action->setEnabled(m_materialAsset.GetId().IsValid() || !m_propertyOverrides.empty() || !m_matModUvOverrides.empty()); - - action = menu.addAction("Set Default Asset", [this]() { SetDefaultAsset(); }); - action->setEnabled(m_id.m_materialAssetId.IsValid()); - - menu.addSeparator(); - - action = menu.addAction("Generate Source Material...", [this]() { OpenMaterialExporter(); }); + action = menu.addAction("Generate/Manage Source Material...", [this]() { OpenMaterialExporter(); }); action->setEnabled(m_id.m_materialAssetId.IsValid()); menu.addSeparator(); - const auto instanceAssetId = m_materialAsset.GetId().IsValid() ? m_materialAsset.GetId() : m_id.m_materialAssetId; + action = menu.addAction("Edit Source Material...", [this]() { OpenMaterialEditor(); }); + action->setEnabled(HasSourceData()); action = menu.addAction("Edit Material Instance...", [this]() { OpenMaterialInspector(); }); action->setEnabled(m_materialAsset.GetId().IsValid()); - action = menu.addAction("Edit Material Model UV Map...", [this]() { OpenUvNameMapInspector(); }); + action = menu.addAction("Edit Material Instance UV Map...", [this]() { OpenUvNameMapInspector(); }); action->setEnabled(m_materialAsset.GetId().IsValid()); - action = menu.addAction("Edit Material in Material Editor...", [this]() { OpenMaterialEditor(); }); - action->setEnabled(HasSourceData()); + menu.addSeparator(); + + action = menu.addAction("Clear Material Instance Overrides", [this]() { m_propertyOverrides = {}; m_matModUvOverrides = {}; }); + action->setEnabled(!m_propertyOverrides.empty() || !m_matModUvOverrides.empty()); menu.exec(QCursor::pos()); } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 9337d5aad7..0c331740e6 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include @@ -469,7 +471,7 @@ namespace AZ if (m_skinnedMeshInputBuffers) { m_boneTransforms = CreateBoneTransformBufferFromActorInstance(m_actorInstance, GetSkinningMethod()); - AZ_Error("AtomActorInstance", m_boneTransforms, "Failed to create bone transform buffer."); + AZ_Error("AtomActorInstance", m_boneTransforms || AZ::RHI::IsNullRenderer(), "Failed to create bone transform buffer."); // If the instance is created before the default materials on the model have finished loading, the mesh feature processor will ignore it. // Wait for them all to be ready before creating the instance diff --git a/Gems/Blast/Code/Source/Components/BlastFamilyComponent.cpp b/Gems/Blast/Code/Source/Components/BlastFamilyComponent.cpp index 1da9663b8f..bf1f3bc5af 100644 --- a/Gems/Blast/Code/Source/Components/BlastFamilyComponent.cpp +++ b/Gems/Blast/Code/Source/Components/BlastFamilyComponent.cpp @@ -286,9 +286,13 @@ namespace Blast // Create damage and actor render managers m_damageManager = AZStd::make_unique(blastMaterial, m_family->GetActorTracker()); - m_actorRenderManager = AZStd::make_unique( - AZ::RPI::Scene::GetFeatureProcessorForEntity(GetEntityId()), - m_meshDataComponent, GetEntityId(), m_blastAsset->GetPxAsset()->getChunkCount(), AZ::Vector3(transform.GetUniformScale())); + + if (m_meshDataComponent) + { + m_actorRenderManager = AZStd::make_unique( + AZ::RPI::Scene::GetFeatureProcessorForEntity(GetEntityId()), + m_meshDataComponent, GetEntityId(), m_blastAsset->GetPxAsset()->getChunkCount(), AZ::Vector3(transform.GetUniformScale())); + } // Spawn the family m_family->Spawn(transform); @@ -540,7 +544,11 @@ namespace Blast void BlastFamilyComponent::OnActorCreated([[maybe_unused]] const BlastFamily& family, const BlastActor& actor) { - m_actorRenderManager->OnActorCreated(actor); + if (m_actorRenderManager) + { + m_actorRenderManager->OnActorCreated(actor); + } + m_solver->notifyActorCreated(*actor.GetTkActor().getActorLL()); if (auto* physicsSystem = AZ::Interface::Get()) @@ -576,7 +584,11 @@ namespace Blast } m_solver->notifyActorDestroyed(*actor.GetTkActor().getActorLL()); - m_actorRenderManager->OnActorDestroyed(actor); + + if (m_actorRenderManager) + { + m_actorRenderManager->OnActorDestroyed(actor); + } } // Update positions of entities with render meshes corresponding to their right dynamic bodies. diff --git a/Gems/Camera/Code/CMakeLists.txt b/Gems/Camera/Code/CMakeLists.txt index 703424416b..b45f768cb7 100644 --- a/Gems/Camera/Code/CMakeLists.txt +++ b/Gems/Camera/Code/CMakeLists.txt @@ -69,4 +69,22 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) # tools and builders use the above module. ly_create_alias(NAME Camera.Tools NAMESPACE Gem TARGETS Gem::Camera.Editor) ly_create_alias(NAME Camera.Builders NAMESPACE Gem TARGETS Gem::Camera.Editor) + + # The DefaultPrefab contains an EditorCameraComponent which makes this gem required + ly_enable_gems(GEMS Camera VARIANTS Tools TARGETS Editor) + ly_enable_gems(GEMS Camera VARIANTS Builders TARGETS AssetBuilder AssetProcessor AssetProcessorBatch) endif() + + +# Added dependencies to the Client and Server Launchers +get_property(LY_PROJECTS_TARGET_NAME GLOBAL PROPERTY LY_PROJECTS_TARGET_NAME) +foreach(project_name IN LISTS LY_PROJECTS_TARGET_NAME) + # Add gem as a dependency of the Clients Launcher + ly_enable_gems(PROJECT_NAME ${project_name} GEMS Camera VARIANTS Clients + TARGETS ${project_name}.GameLauncher) + # Add gem as a dependency of the Servers Launcher + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) + ly_enable_gems(PROJECT_NAME ${project_name} GEMS Camera VARIANTS Servers + TARGETS ${project_name}.ServerLauncher) + endif() +endforeach() diff --git a/Gems/DevTextures/CMakeLists.txt b/Gems/DevTextures/CMakeLists.txt index 4d5680a30d..6ec5ba947c 100644 --- a/Gems/DevTextures/CMakeLists.txt +++ b/Gems/DevTextures/CMakeLists.txt @@ -8,3 +8,8 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # + +# This will export its "SourcePaths" to the generated "cmake_dependencies..assetbuilder.setreg" +if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_create_alias(NAME DevTextures.Builders NAMESPACE Gem) +endif() diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Behaviors/ActorGroupBehavior.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Behaviors/ActorGroupBehavior.cpp index a58c48f1ef..34cb6a36eb 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Behaviors/ActorGroupBehavior.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/SceneAPIExt/Behaviors/ActorGroupBehavior.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -172,10 +173,13 @@ namespace EMotionFX AZ::SceneAPI::Events::ProcessingResult ActorGroupBehavior::BuildDefault(AZ::SceneAPI::Containers::Scene& scene) const { - const bool hasBoneOrSkinData = AZ::SceneAPI::Utilities::DoesSceneGraphContainDataLike(scene, true) || - AZ::SceneAPI::Utilities::DoesSceneGraphContainDataLike(scene, true); - const bool hasAnimationData = AZ::SceneAPI::Utilities::DoesSceneGraphContainDataLike(scene, true); - if (SceneHasActorGroup(scene) || !hasBoneOrSkinData || hasAnimationData) + const bool hasBoneData = AZ::SceneAPI::Utilities::DoesSceneGraphContainDataLike(scene, true); + const bool hasSkinData = AZ::SceneAPI::Utilities::DoesSceneGraphContainDataLike(scene, true); + const bool hasBlendShapeData = AZ::SceneAPI::Utilities::DoesSceneGraphContainDataLike(scene, true); + // Skip building the default actor in case a valid actor group with overwritten settings exists, or + // in the most common case for animation files, that do contain an animated skeleton while not containing a skin or blend shapes. + if (SceneHasActorGroup(scene) || + (hasBoneData && (!hasSkinData && !hasBlendShapeData))) { return AZ::SceneAPI::Events::ProcessingResult::Ignored; } diff --git a/Gems/Maestro/Code/CMakeLists.txt b/Gems/Maestro/Code/CMakeLists.txt index 01b22b1abf..d92f2ab643 100644 --- a/Gems/Maestro/Code/CMakeLists.txt +++ b/Gems/Maestro/Code/CMakeLists.txt @@ -78,8 +78,25 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) ly_create_alias(NAME Maestro.Tools NAMESPACE Gem TARGETS Gem::Maestro.Editor) ly_create_alias(NAME Maestro.Builders NAMESPACE Gem TARGETS Gem::Maestro.Editor) + # Maestro is still used by the CrySystem Level System and SystemInit and TrackView + # It is required by the GameLauncher, ServerLauncher and Editor applications + ly_enable_gems(GEMS Maestro VARIANTS Tools TARGETS Editor) + endif() +# Loop over each Project name to allow the ${ProjectName}.GameLauncher and ${ProjectName}.ServerLauncher +# target to add the gem the Clients and Servers variant +get_property(LY_PROJECTS_TARGET_NAME GLOBAL PROPERTY LY_PROJECTS_TARGET_NAME) +foreach(project_name IN LISTS LY_PROJECTS_TARGET_NAME) + # Add gem as a dependency of the Clients Launcher + ly_enable_gems(PROJECT_NAME ${project_name} GEMS Maestro VARIANTS Clients TARGETS ${project_name}.GameLauncher) + # Add gem as a dependency of the Servers Launcher + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) + ly_enable_gems(PROJECT_NAME ${project_name} GEMS Maestro VARIANTS Servers TARGETS ${project_name}.ServerLauncher) + endif() +endforeach() + + ################################################################################ # Tests ################################################################################ diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index 1848341c60..9e273d8d48 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -827,7 +827,7 @@ enum class NetworkProperties #} {% macro DefineNetworkPropertyBehaviorReflection(Component, ReplicateFrom, ReplicateTo, ClassName) %} {% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %} -{% if (Property.attrib['IsPublic'] | booleanTrue == true) and (Property.attrib['GenerateEventBindings'] | booleanTrue == true) -%} +{% if (Property.attrib['IsPublic'] | booleanTrue == true) and (Property.attrib['ExposeToScript'] | booleanTrue == true) -%} // {{ UpperFirst(Property.attrib['Name']) }}: Replicate from {{ ReplicateFrom }} to {{ ReplicateTo }} {% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %} ->Method("Get{{ UpperFirst(Property.attrib['Name']) }}", [](AZ::EntityId id, int32_t index) -> {{ Property.attrib['Type'] }} diff --git a/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml index b6edd0e3be..0c799a7b3f 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml @@ -17,7 +17,7 @@ - + diff --git a/Gems/Multiplayer/Code/Source/AutoGen/NetworkTransformComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/NetworkTransformComponent.AutoComponent.xml index a112cde4e6..8abc874aa6 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/NetworkTransformComponent.AutoComponent.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/NetworkTransformComponent.AutoComponent.xml @@ -12,12 +12,12 @@ - - - - - - + + + + + + &Preferences diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp index bc07d16a7e..356ee22ba3 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp @@ -3764,6 +3764,12 @@ namespace ScriptCanvas nextSlot = onceResetSlot; } + if (!nextSlot) + { + AddError(ID.m_node->GetEntityId(), once, "Once node missing next slot, likely needs replacement"); + return; + } + ParseExecutionTreeBody(nextParse, *nextSlot); nextParse->MarkDebugEmptyStatement(); } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/ParsingUtilities.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/ParsingUtilities.cpp index 131209a521..0c92876e2c 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/ParsingUtilities.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/ParsingUtilities.cpp @@ -928,6 +928,7 @@ namespace ScriptCanvas { return execution->GetId().m_node && IsOnce(*execution->GetId().m_node) + && execution->GetId().m_slot && execution->GetId().m_slot->GetType() == CombinedSlotType::ExecutionIn; } @@ -938,7 +939,7 @@ namespace ScriptCanvas bool IsOnceReset(const Node& node, const Slot* slot) { - return slot = OnceProperty::GetResetSlot(&node); + return slot == OnceProperty::GetResetSlot(&node); } bool IsOperatorArithmetic(const ExecutionTreeConstPtr& execution) diff --git a/Gems/UiBasics/CMakeLists.txt b/Gems/UiBasics/CMakeLists.txt index 4d5680a30d..91b24308b0 100644 --- a/Gems/UiBasics/CMakeLists.txt +++ b/Gems/UiBasics/CMakeLists.txt @@ -8,3 +8,8 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # + +# This will export its "SourcePaths" to the generated "cmake_dependencies..assetbuilder.setreg" +if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_create_alias(NAME UiBasics.Builders NAMESPACE Gem) +endif() diff --git a/Gems/Vegetation/Code/CMakeLists.txt b/Gems/Vegetation/Code/CMakeLists.txt index 7283f53c97..2b32368d5a 100644 --- a/Gems/Vegetation/Code/CMakeLists.txt +++ b/Gems/Vegetation/Code/CMakeLists.txt @@ -28,7 +28,6 @@ ly_add_target( Gem::LmbrCentral Gem::SurfaceData PUBLIC - Legacy::CryCommon Gem::AtomLyIntegration_CommonFeatures.Static RUNTIME_DEPENDENCIES Gem::GradientSignal @@ -105,6 +104,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) BUILD_DEPENDENCIES PRIVATE AZ::AzTest + AZ::AzFrameworkTestShared Gem::Vegetation.Static ) ly_add_googletest( diff --git a/Gems/Vegetation/Code/Include/Vegetation/PrefabInstanceSpawner.h b/Gems/Vegetation/Code/Include/Vegetation/PrefabInstanceSpawner.h new file mode 100644 index 0000000000..3f65352abc --- /dev/null +++ b/Gems/Vegetation/Code/Include/Vegetation/PrefabInstanceSpawner.h @@ -0,0 +1,101 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#include +#include +#include +#include + +namespace Vegetation +{ + /** + * Instance spawner of prefab instances. + */ + class PrefabInstanceSpawner + : public InstanceSpawner + , private AZ::Data::AssetBus::MultiHandler + { + public: + AZ_RTTI(PrefabInstanceSpawner, "{74BEEDB5-81CF-409F-B375-0D93D81EF2E3}", InstanceSpawner); + AZ_CLASS_ALLOCATOR(PrefabInstanceSpawner, AZ::SystemAllocator, 0); + static void Reflect(AZ::ReflectContext* context); + + PrefabInstanceSpawner(); + virtual ~PrefabInstanceSpawner(); + + //! Start loading any assets that the spawner will need. + void LoadAssets() override; + + //! Unload any assets that the spawner loaded. + void UnloadAssets() override; + + //! Perform any extra initialization needed at the point of registering with the vegetation system. + void OnRegisterUniqueDescriptor() override; + + //! Perform any extra cleanup needed at the point of unregistering with the vegetation system. + void OnReleaseUniqueDescriptor() override; + + //! Does this exist but have empty asset references? + bool HasEmptyAssetReferences() const override; + + //! Has this finished loading any assets that are needed? + bool IsLoaded() const override; + + //! Are the assets loaded, initialized, and spawnable? + bool IsSpawnable() const override; + + //! Display name of the instances that will be spawned. + AZStd::string GetName() const override; + + //! Create a single instance. + InstancePtr CreateInstance(const InstanceData& instanceData) override; + + //! Destroy a single instance. + void DestroyInstance(InstanceId id, InstancePtr instance) override; + + AZStd::string GetSpawnableAssetPath() const; + void SetSpawnableAssetPath(const AZStd::string& assetPath); + + AZ::Data::AssetId GetSpawnableAssetId() const; + void SetSpawnableAssetId(const AZ::Data::AssetId& assetId); + + private: + bool DataIsEquivalent(const InstanceSpawner& rhs) const override; + + ////////////////////////////////////////////////////////////////////////// + // AZ::Data::AssetBus::Handler + void OnAssetReady(AZ::Data::Asset asset) override; + void OnAssetReloaded(AZ::Data::Asset asset) override; + + AZ::u32 SpawnableAssetChanged(); + void ResetSpawnableAsset(); + + void UpdateCachedValues(); + + //! Verify that the spawnable asset only contains data compatible with the dynamic vegetation system. + bool ValidateAssetContents(const AZ::Data::Asset asset) const; + + //! Despawn an instance of a spawnable asset + void DespawnAssetInstance(AzFramework::EntitySpawnTicket* ticket); + + //! Cached values so that asset isn't accessed on other threads + bool m_assetLoadedAndSpawnable = false; + + //! Collection of spawned instance tickets, needed for destroying the instances. + AZStd::unordered_set m_instanceTickets; + + //! asset data + AZ::Data::Asset m_spawnableAsset; + }; + +} // namespace Vegetation diff --git a/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp b/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp index e54f523b43..d6e4be6e9b 100644 --- a/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp +++ b/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp @@ -10,7 +10,7 @@ * */ -#include "Vegetation_precompiled.h" +#include #include "AreaSystemComponent.h" #include diff --git a/Gems/Vegetation/Code/Source/Components/AreaBlenderComponent.cpp b/Gems/Vegetation/Code/Source/Components/AreaBlenderComponent.cpp index ff39f6321e..7c9d8013d0 100644 --- a/Gems/Vegetation/Code/Source/Components/AreaBlenderComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/AreaBlenderComponent.cpp @@ -10,7 +10,7 @@ * */ -#include "Vegetation_precompiled.h" +#include #include "AreaBlenderComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/AreaComponentBase.cpp b/Gems/Vegetation/Code/Source/Components/AreaComponentBase.cpp index 056006f64a..46e214534a 100644 --- a/Gems/Vegetation/Code/Source/Components/AreaComponentBase.cpp +++ b/Gems/Vegetation/Code/Source/Components/AreaComponentBase.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include #include #include diff --git a/Gems/Vegetation/Code/Source/Components/BlockerComponent.cpp b/Gems/Vegetation/Code/Source/Components/BlockerComponent.cpp index fa876c5cf0..5219334fd6 100644 --- a/Gems/Vegetation/Code/Source/Components/BlockerComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/BlockerComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "BlockerComponent.h" #include diff --git a/Gems/Vegetation/Code/Source/Components/DescriptorListCombinerComponent.cpp b/Gems/Vegetation/Code/Source/Components/DescriptorListCombinerComponent.cpp index ffa57a0326..3a903399d1 100644 --- a/Gems/Vegetation/Code/Source/Components/DescriptorListCombinerComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/DescriptorListCombinerComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "DescriptorListCombinerComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/DescriptorListComponent.cpp b/Gems/Vegetation/Code/Source/Components/DescriptorListComponent.cpp index c6939d520a..bc5be7423b 100644 --- a/Gems/Vegetation/Code/Source/Components/DescriptorListComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/DescriptorListComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "DescriptorListComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/DescriptorWeightSelectorComponent.cpp b/Gems/Vegetation/Code/Source/Components/DescriptorWeightSelectorComponent.cpp index 840eec8dfa..19cf75e4d2 100644 --- a/Gems/Vegetation/Code/Source/Components/DescriptorWeightSelectorComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/DescriptorWeightSelectorComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "DescriptorWeightSelectorComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/DistanceBetweenFilterComponent.cpp b/Gems/Vegetation/Code/Source/Components/DistanceBetweenFilterComponent.cpp index 16b1bb5f7e..99050638b5 100644 --- a/Gems/Vegetation/Code/Source/Components/DistanceBetweenFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/DistanceBetweenFilterComponent.cpp @@ -10,7 +10,7 @@ * */ -#include "Vegetation_precompiled.h" +#include #include "DistanceBetweenFilterComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/DistributionFilterComponent.cpp b/Gems/Vegetation/Code/Source/Components/DistributionFilterComponent.cpp index 2ba07f95b3..aff560d7d4 100644 --- a/Gems/Vegetation/Code/Source/Components/DistributionFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/DistributionFilterComponent.cpp @@ -10,7 +10,7 @@ * */ -#include "Vegetation_precompiled.h" +#include #include "DistributionFilterComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/LevelSettingsComponent.cpp b/Gems/Vegetation/Code/Source/Components/LevelSettingsComponent.cpp index 748ba0506a..4196619ffc 100644 --- a/Gems/Vegetation/Code/Source/Components/LevelSettingsComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/LevelSettingsComponent.cpp @@ -9,7 +9,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" #include "LevelSettingsComponent.h" #include diff --git a/Gems/Vegetation/Code/Source/Components/MeshBlockerComponent.cpp b/Gems/Vegetation/Code/Source/Components/MeshBlockerComponent.cpp index d37dc4a82d..8eedf4019b 100644 --- a/Gems/Vegetation/Code/Source/Components/MeshBlockerComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/MeshBlockerComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "MeshBlockerComponent.h" #include diff --git a/Gems/Vegetation/Code/Source/Components/PositionModifierComponent.cpp b/Gems/Vegetation/Code/Source/Components/PositionModifierComponent.cpp index 5781e53b41..5c1c48aa39 100644 --- a/Gems/Vegetation/Code/Source/Components/PositionModifierComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/PositionModifierComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "PositionModifierComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/ReferenceShapeComponent.cpp b/Gems/Vegetation/Code/Source/Components/ReferenceShapeComponent.cpp index c5f99239d3..fc62eb39a7 100644 --- a/Gems/Vegetation/Code/Source/Components/ReferenceShapeComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/ReferenceShapeComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "ReferenceShapeComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/RotationModifierComponent.cpp b/Gems/Vegetation/Code/Source/Components/RotationModifierComponent.cpp index 9dda59463e..d88b606aa3 100644 --- a/Gems/Vegetation/Code/Source/Components/RotationModifierComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/RotationModifierComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "RotationModifierComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/ScaleModifierComponent.cpp b/Gems/Vegetation/Code/Source/Components/ScaleModifierComponent.cpp index 63755e5325..6e0397b410 100644 --- a/Gems/Vegetation/Code/Source/Components/ScaleModifierComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/ScaleModifierComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "ScaleModifierComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/ShapeIntersectionFilterComponent.cpp b/Gems/Vegetation/Code/Source/Components/ShapeIntersectionFilterComponent.cpp index b1512f89a4..b7f9f7fe9c 100644 --- a/Gems/Vegetation/Code/Source/Components/ShapeIntersectionFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/ShapeIntersectionFilterComponent.cpp @@ -10,7 +10,7 @@ * */ -#include "Vegetation_precompiled.h" +#include #include "ShapeIntersectionFilterComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/SlopeAlignmentModifierComponent.cpp b/Gems/Vegetation/Code/Source/Components/SlopeAlignmentModifierComponent.cpp index 3ff45bad74..78d4d4729c 100644 --- a/Gems/Vegetation/Code/Source/Components/SlopeAlignmentModifierComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/SlopeAlignmentModifierComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "SlopeAlignmentModifierComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/SpawnerComponent.cpp b/Gems/Vegetation/Code/Source/Components/SpawnerComponent.cpp index 6c1db9037b..321613dd08 100644 --- a/Gems/Vegetation/Code/Source/Components/SpawnerComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/SpawnerComponent.cpp @@ -10,7 +10,7 @@ * */ -#include "Vegetation_precompiled.h" +#include #include "SpawnerComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/SurfaceAltitudeFilterComponent.cpp b/Gems/Vegetation/Code/Source/Components/SurfaceAltitudeFilterComponent.cpp index 7e6737ecf7..ebc8896fe6 100644 --- a/Gems/Vegetation/Code/Source/Components/SurfaceAltitudeFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/SurfaceAltitudeFilterComponent.cpp @@ -10,7 +10,7 @@ * */ -#include "Vegetation_precompiled.h" +#include #include "SurfaceAltitudeFilterComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Components/SurfaceMaskDepthFilterComponent.cpp b/Gems/Vegetation/Code/Source/Components/SurfaceMaskDepthFilterComponent.cpp index d8e8b47f7b..2a191245ee 100644 --- a/Gems/Vegetation/Code/Source/Components/SurfaceMaskDepthFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/SurfaceMaskDepthFilterComponent.cpp @@ -10,7 +10,7 @@ * */ -#include "Vegetation_precompiled.h" +#include #include "SurfaceMaskDepthFilterComponent.h" #include diff --git a/Gems/Vegetation/Code/Source/Components/SurfaceMaskFilterComponent.cpp b/Gems/Vegetation/Code/Source/Components/SurfaceMaskFilterComponent.cpp index d18a7434ae..0749d9473a 100644 --- a/Gems/Vegetation/Code/Source/Components/SurfaceMaskFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/SurfaceMaskFilterComponent.cpp @@ -10,7 +10,7 @@ * */ -#include "Vegetation_precompiled.h" +#include #include "SurfaceMaskFilterComponent.h" #include diff --git a/Gems/Vegetation/Code/Source/Components/SurfaceSlopeFilterComponent.cpp b/Gems/Vegetation/Code/Source/Components/SurfaceSlopeFilterComponent.cpp index f856e4bd8f..27938b9c74 100644 --- a/Gems/Vegetation/Code/Source/Components/SurfaceSlopeFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Components/SurfaceSlopeFilterComponent.cpp @@ -10,7 +10,7 @@ * */ -#include "Vegetation_precompiled.h" +#include #include "SurfaceSlopeFilterComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/DebugSystemComponent.cpp b/Gems/Vegetation/Code/Source/DebugSystemComponent.cpp index c62905766e..984f8fd538 100644 --- a/Gems/Vegetation/Code/Source/DebugSystemComponent.cpp +++ b/Gems/Vegetation/Code/Source/DebugSystemComponent.cpp @@ -9,7 +9,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" #include "DebugSystemComponent.h" #include diff --git a/Gems/Vegetation/Code/Source/Debugger/AreaDebugComponent.cpp b/Gems/Vegetation/Code/Source/Debugger/AreaDebugComponent.cpp index 12ba003cc0..91ab9279fe 100644 --- a/Gems/Vegetation/Code/Source/Debugger/AreaDebugComponent.cpp +++ b/Gems/Vegetation/Code/Source/Debugger/AreaDebugComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include #include #include diff --git a/Gems/Vegetation/Code/Source/Debugger/AreaDebugComponent.h b/Gems/Vegetation/Code/Source/Debugger/AreaDebugComponent.h index 014e45249a..7bea99a2fa 100644 --- a/Gems/Vegetation/Code/Source/Debugger/AreaDebugComponent.h +++ b/Gems/Vegetation/Code/Source/Debugger/AreaDebugComponent.h @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -31,13 +32,13 @@ namespace Vegetation { AZ_INLINE AZ::Color GetDebugColor() { - static uint32 debugColor = 0xff << 8; + static uint32_t debugColor = 0xff << 8; AZ::Color value; value.FromU32(debugColor | (0xff << 24)); // add in alpha 255 // use a golden ratio sequence to generate the next color // new color = fract(old color * 1.6) // Treat the 24 bits as normalized 0 - 1 - debugColor = (uint32)((((uint64)debugColor * 0x1999999ull) - 0xffffffull) & 0xffffffull); + debugColor = azlossy_cast(((aznumeric_cast(debugColor) * 0x1999999ull) - 0xffffffull) & 0xffffffull); return value; } diff --git a/Gems/Vegetation/Code/Source/Debugger/DebugComponent.cpp b/Gems/Vegetation/Code/Source/Debugger/DebugComponent.cpp index 099bd2e90c..cb241c4fd2 100644 --- a/Gems/Vegetation/Code/Source/Debugger/DebugComponent.cpp +++ b/Gems/Vegetation/Code/Source/Debugger/DebugComponent.cpp @@ -10,7 +10,7 @@ * */ -#include "Vegetation_precompiled.h" +#include #include "DebugComponent.h" #include "AreaSystemComponent.h" #include "InstanceSystemComponent.h" diff --git a/Gems/Vegetation/Code/Source/Debugger/DebugComponent.h b/Gems/Vegetation/Code/Source/Debugger/DebugComponent.h index ae834b3632..9283c1da90 100644 --- a/Gems/Vegetation/Code/Source/Debugger/DebugComponent.h +++ b/Gems/Vegetation/Code/Source/Debugger/DebugComponent.h @@ -167,7 +167,7 @@ namespace Vegetation using AreaData = AZStd::vector; AZStd::size_t MakeAreaSectorKey(AZ::EntityId areaId, SectorId sectorId); - AZStd::unordered_map m_currentAreasTiming; + AZStd::unordered_map m_currentAreasTiming; AreaData m_areaData; AZStd::vector m_currentSortedTimingList; diff --git a/Gems/Vegetation/Code/Source/Debugger/EditorAreaDebugComponent.cpp b/Gems/Vegetation/Code/Source/Debugger/EditorAreaDebugComponent.cpp index bf942f78c4..2069dd66bb 100644 --- a/Gems/Vegetation/Code/Source/Debugger/EditorAreaDebugComponent.cpp +++ b/Gems/Vegetation/Code/Source/Debugger/EditorAreaDebugComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorAreaDebugComponent.h" #include diff --git a/Gems/Vegetation/Code/Source/Debugger/EditorDebugComponent.cpp b/Gems/Vegetation/Code/Source/Debugger/EditorDebugComponent.cpp index 533a1daf00..0dc66ee3b8 100644 --- a/Gems/Vegetation/Code/Source/Debugger/EditorDebugComponent.cpp +++ b/Gems/Vegetation/Code/Source/Debugger/EditorDebugComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorDebugComponent.h" #include diff --git a/Gems/Vegetation/Code/Source/Descriptor.cpp b/Gems/Vegetation/Code/Source/Descriptor.cpp index d0075f2d7b..cb1a4e45b7 100644 --- a/Gems/Vegetation/Code/Source/Descriptor.cpp +++ b/Gems/Vegetation/Code/Source/Descriptor.cpp @@ -10,8 +10,6 @@ * */ -#include "Vegetation_precompiled.h" - #include #include #include diff --git a/Gems/Vegetation/Code/Source/DescriptorListAsset.cpp b/Gems/Vegetation/Code/Source/DescriptorListAsset.cpp index 90728718ed..4e0294c58c 100644 --- a/Gems/Vegetation/Code/Source/DescriptorListAsset.cpp +++ b/Gems/Vegetation/Code/Source/DescriptorListAsset.cpp @@ -10,8 +10,6 @@ * */ -#include "Vegetation_precompiled.h" - #include #include #include diff --git a/Gems/Vegetation/Code/Source/DynamicSliceInstanceSpawner.cpp b/Gems/Vegetation/Code/Source/DynamicSliceInstanceSpawner.cpp index a185c9a601..9ed23c7dd2 100644 --- a/Gems/Vegetation/Code/Source/DynamicSliceInstanceSpawner.cpp +++ b/Gems/Vegetation/Code/Source/DynamicSliceInstanceSpawner.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorAreaBlenderComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorAreaBlenderComponent.cpp index 7371a96ba1..7511d6b8be 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorAreaBlenderComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorAreaBlenderComponent.cpp @@ -10,14 +10,11 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorAreaBlenderComponent.h" #include #include #include #include -#include -#include #include #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorBlockerComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorBlockerComponent.cpp index bbd116b091..da0a2b5f53 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorBlockerComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorBlockerComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorBlockerComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorDescriptorListCombinerComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorDescriptorListCombinerComponent.cpp index ade8121b06..cbe62e0444 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorDescriptorListCombinerComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorDescriptorListCombinerComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorDescriptorListCombinerComponent.h" #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorDescriptorListComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorDescriptorListComponent.cpp index 51ecc03c5a..18c045346b 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorDescriptorListComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorDescriptorListComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorDescriptorListComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorDescriptorWeightSelectorComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorDescriptorWeightSelectorComponent.cpp index 1c23745831..5ae65d3c21 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorDescriptorWeightSelectorComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorDescriptorWeightSelectorComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorDescriptorWeightSelectorComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorDistanceBetweenFilterComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorDistanceBetweenFilterComponent.cpp index ea6ab5eec1..e43be749bd 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorDistanceBetweenFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorDistanceBetweenFilterComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorDistanceBetweenFilterComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorDistributionFilterComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorDistributionFilterComponent.cpp index 8ea0acb78d..6b75ca73bc 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorDistributionFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorDistributionFilterComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorDistributionFilterComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorLevelSettingsComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorLevelSettingsComponent.cpp index 6f6a6f2ec4..5faae032a3 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorLevelSettingsComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorLevelSettingsComponent.cpp @@ -10,8 +10,6 @@ * */ -#include "Vegetation_precompiled.h" - #include "EditorLevelSettingsComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorMeshBlockerComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorMeshBlockerComponent.cpp index fe519877e2..63c63d3d87 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorMeshBlockerComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorMeshBlockerComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorMeshBlockerComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorPositionModifierComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorPositionModifierComponent.cpp index 14ae748168..e12444b83e 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorPositionModifierComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorPositionModifierComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorPositionModifierComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorReferenceShapeComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorReferenceShapeComponent.cpp index 5f3225e23d..4240e4914c 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorReferenceShapeComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorReferenceShapeComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorReferenceShapeComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorRotationModifierComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorRotationModifierComponent.cpp index 8d81ff1dae..ab9d55f221 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorRotationModifierComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorRotationModifierComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorRotationModifierComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorScaleModifierComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorScaleModifierComponent.cpp index d6dc70a523..1c1684f5d5 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorScaleModifierComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorScaleModifierComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorScaleModifierComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorShapeIntersectionFilterComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorShapeIntersectionFilterComponent.cpp index 93e5f41c75..b5a236bcee 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorShapeIntersectionFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorShapeIntersectionFilterComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorShapeIntersectionFilterComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorSlopeAlignmentModifierComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorSlopeAlignmentModifierComponent.cpp index 6002787404..ce036813d0 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorSlopeAlignmentModifierComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorSlopeAlignmentModifierComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorSlopeAlignmentModifierComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorSpawnerComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorSpawnerComponent.cpp index 9dd393e124..6aad60f051 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorSpawnerComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorSpawnerComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorSpawnerComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorSurfaceAltitudeFilterComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorSurfaceAltitudeFilterComponent.cpp index 6e46241b83..3ea5760a46 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorSurfaceAltitudeFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorSurfaceAltitudeFilterComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorSurfaceAltitudeFilterComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorSurfaceMaskDepthFilterComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorSurfaceMaskDepthFilterComponent.cpp index f28d134dd0..b4a37f679b 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorSurfaceMaskDepthFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorSurfaceMaskDepthFilterComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorSurfaceMaskDepthFilterComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorSurfaceMaskFilterComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorSurfaceMaskFilterComponent.cpp index 7567acdbde..7d64bc2423 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorSurfaceMaskFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorSurfaceMaskFilterComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorSurfaceMaskFilterComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorSurfaceSlopeFilterComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorSurfaceSlopeFilterComponent.cpp index 5b0868566d..ae93cf3c0b 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorSurfaceSlopeFilterComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorSurfaceSlopeFilterComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include "EditorSurfaceSlopeFilterComponent.h" #include #include diff --git a/Gems/Vegetation/Code/Source/Editor/EditorVegetationSystemComponent.cpp b/Gems/Vegetation/Code/Source/Editor/EditorVegetationSystemComponent.cpp index 17174fa132..fc056de636 100644 --- a/Gems/Vegetation/Code/Source/Editor/EditorVegetationSystemComponent.cpp +++ b/Gems/Vegetation/Code/Source/Editor/EditorVegetationSystemComponent.cpp @@ -9,14 +9,10 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" #include "EditorVegetationSystemComponent.h" #include #include - -#include - #include namespace Vegetation diff --git a/Gems/Vegetation/Code/Source/EmptyInstanceSpawner.cpp b/Gems/Vegetation/Code/Source/EmptyInstanceSpawner.cpp index 9146ea1090..11ceecefc4 100644 --- a/Gems/Vegetation/Code/Source/EmptyInstanceSpawner.cpp +++ b/Gems/Vegetation/Code/Source/EmptyInstanceSpawner.cpp @@ -10,7 +10,6 @@ * */ -#include "Vegetation_precompiled.h" #include #include #include diff --git a/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp b/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp index 4aaf0a0b49..cd50c1f898 100644 --- a/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp +++ b/Gems/Vegetation/Code/Source/InstanceSystemComponent.cpp @@ -9,7 +9,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" +#include #include "InstanceSystemComponent.h" #include diff --git a/Gems/Vegetation/Code/Source/PrefabInstanceSpawner.cpp b/Gems/Vegetation/Code/Source/PrefabInstanceSpawner.cpp new file mode 100644 index 0000000000..9ff66a875f --- /dev/null +++ b/Gems/Vegetation/Code/Source/PrefabInstanceSpawner.cpp @@ -0,0 +1,400 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +namespace Vegetation +{ + + PrefabInstanceSpawner::PrefabInstanceSpawner() + { + UnloadAssets(); + } + + PrefabInstanceSpawner::~PrefabInstanceSpawner() + { + UnloadAssets(); + AZ_Assert(m_instanceTickets.empty(), "Destroying spawner while %u spawn tickets still exist!", m_instanceTickets.size()); + } + + void PrefabInstanceSpawner::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serialize = azrtti_cast(context); + if (serialize) + { + serialize->Class() + ->Version(0)->Field( + "SpawnableAsset", &PrefabInstanceSpawner::m_spawnableAsset) + ; + + AZ::EditContext* edit = serialize->GetEditContext(); + if (edit) + { + edit->Class( + "Prefab", "Prefab Instance") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + + ->DataElement(AZ::Edit::UIHandlers::Default, &PrefabInstanceSpawner::m_spawnableAsset, "Prefab Asset", "Prefab asset") + ->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, false) + ->Attribute(AZ::Edit::Attributes::HideProductFilesInAssetPicker, true) + ->Attribute(AZ::Edit::Attributes::AssetPickerTitle, "a Prefab") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &PrefabInstanceSpawner::SpawnableAssetChanged) + ; + } + } + if (auto behaviorContext = azrtti_cast(context)) + { + behaviorContext->Class() + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Category, "Vegetation") + ->Attribute(AZ::Script::Attributes::Module, "vegetation") + ->Constructor() + ->Method("GetPrefabAssetPath", &PrefabInstanceSpawner::GetSpawnableAssetPath) + ->Method("SetPrefabAssetPath", &PrefabInstanceSpawner::SetSpawnableAssetPath) + ->Method("GetPrefabAssetId", &PrefabInstanceSpawner::GetSpawnableAssetId) + ->Method("SetPrefabAssetId", &PrefabInstanceSpawner::SetSpawnableAssetId); + } + } + + bool PrefabInstanceSpawner::DataIsEquivalent(const InstanceSpawner& baseRhs) const + { + if (const auto* rhs = azrtti_cast(&baseRhs)) + { + return m_spawnableAsset == rhs->m_spawnableAsset; + } + + // Not the same subtypes, so definitely not a data match. + return false; + } + + void PrefabInstanceSpawner::LoadAssets() + { + UnloadAssets(); + + // Note that the spawnable tickets manage and track asset loading as well. We *could* just rely on that and mark + // the spawner as immediately ready for use (i.e. always return "true" in IsLoaded() and IsSpawnable() ), but this + // would cause us to wait until the first instance is spawned to load the asset, creating a delay right at the point + // that the vegetation is becoming visible. It would also cause the asset to get auto-unloaded every time all the + // instances using it are despawned. By loading it *prior* to marking things as ready, we can ensure that we have the + // asset at the point that the first instance is spawned, and that it won't get auto-unloaded every time the instances + // are despawned. + m_spawnableAsset.QueueLoad(); + AZ::Data::AssetBus::MultiHandler::BusConnect(m_spawnableAsset.GetId()); + } + + void PrefabInstanceSpawner::UnloadAssets() + { + // It's possible under some circumstances that we might unload assets before destroying all spawned instances + // due to the way the vegetation system queues up delete requests and descriptor unregistrations. If so, + // despawn the actual spawned instances here, but leave the ticket entries in the instance ticket map and don't + // delete the ticket pointers. The tickets will get cleaned up when the vegetation system gets around to requesting + // the instance destroy. + if (!m_instanceTickets.empty()) + { + for (auto& ticket : m_instanceTickets) + { + DespawnAssetInstance(ticket); + } + } + ResetSpawnableAsset(); + NotifyOnAssetsUnloaded(); + } + + void PrefabInstanceSpawner::ResetSpawnableAsset() + { + AZ::Data::AssetBus::MultiHandler::BusDisconnect(); + + m_spawnableAsset.Release(); + UpdateCachedValues(); + m_spawnableAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::QueueLoad); + } + + void PrefabInstanceSpawner::UpdateCachedValues() + { + // Once our assets are loaded and at the point that they're getting registered, + // cache off the spawnable state for use from multiple threads. + + m_assetLoadedAndSpawnable = m_spawnableAsset.IsReady(); + } + + void PrefabInstanceSpawner::OnRegisterUniqueDescriptor() + { + UpdateCachedValues(); + } + + void PrefabInstanceSpawner::OnReleaseUniqueDescriptor() + { + } + + bool PrefabInstanceSpawner::HasEmptyAssetReferences() const + { + // If we don't have a valid Spawnable Asset, then that means we're expecting to spawn empty instances. + return !m_spawnableAsset.GetId().IsValid(); + } + + bool PrefabInstanceSpawner::IsLoaded() const + { + return m_assetLoadedAndSpawnable; + } + + bool PrefabInstanceSpawner::IsSpawnable() const + { + return m_assetLoadedAndSpawnable; + } + + AZStd::string PrefabInstanceSpawner::GetName() const + { + AZStd::string assetName; + if (!HasEmptyAssetReferences()) + { + // Get the asset file name + assetName = m_spawnableAsset.GetHint(); + if (!m_spawnableAsset.GetHint().empty()) + { + AzFramework::StringFunc::Path::GetFileName(m_spawnableAsset.GetHint().c_str(), assetName); + } + } + else + { + assetName = ""; + } + + return assetName; + } + + bool PrefabInstanceSpawner::ValidateAssetContents(const AZ::Data::Asset asset) const + { + bool validAsset = true; + + // Basic safety check: Make sure the asset is a spawnable. + auto spawnableAsset = azrtti_cast(asset.GetData()); + if (!spawnableAsset) + { + return false; + } + + // Loop through all the components on all the entities in the spawnable, looking for any type of Vegetation Area. + // If we try to dynamically spawn vegetation areas, as they spawn in they will non-deterministically start spawning + // (or blocking) other vegetation while we're in the midst of spawning the higher-level vegetation area. Threading + // and timing affects which one wins out. It may also cause other bugs. + + const AzFramework::Spawnable::EntityList& entities = spawnableAsset->GetEntities(); + for (auto& entity : entities) + { + auto components = entity->GetComponents(); + for (auto component : components) + { + if (azrtti_istypeof(component)) + { + validAsset = false; + AZ_Error("Vegetation", false, + "Vegetation system cannot spawn prefabs containing a component of type '%s'", + component->RTTI_GetTypeName()); + } + } + } + + return validAsset; + } + + void PrefabInstanceSpawner::OnAssetReady(AZ::Data::Asset asset) + { + if (m_spawnableAsset.GetId() == asset.GetId()) + { + // Make sure that the spawnable asset we're loading doesn't contain any data incompatible with + // the dynamic vegetation system. + // This check needs to be performed at asset loading time as opposed to authoring / configuration + // time because the spawnable asset can be changed independently from the authoring of this component. + bool validAsset = ValidateAssetContents(asset); + + ResetSpawnableAsset(); + if (validAsset) + { + m_spawnableAsset = asset; + } + UpdateCachedValues(); + NotifyOnAssetsLoaded(); + } + } + + void PrefabInstanceSpawner::OnAssetReloaded(AZ::Data::Asset asset) + { + OnAssetReady(asset); + } + + AZStd::string PrefabInstanceSpawner::GetSpawnableAssetPath() const + { + AZStd::string assetPathString; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + assetPathString, &AZ::Data::AssetCatalogRequests::GetAssetPathById, m_spawnableAsset.GetId()); + return assetPathString; + } + + void PrefabInstanceSpawner::SetSpawnableAssetPath(const AZStd::string& assetPath) + { + if (!assetPath.empty()) + { + AZ::Data::AssetId assetId; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + assetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, assetPath.c_str(), + AZ::Data::s_invalidAssetType, false); + if (assetId.IsValid()) + { + SetSpawnableAssetId(assetId); + } + else + { + AZ_Error("Vegetation", false, "Asset '%s' is invalid.", assetPath.c_str()); + } + } + else + { + SetSpawnableAssetId(AZ::Data::AssetId()); + } + } + + AZ::Data::AssetId PrefabInstanceSpawner::GetSpawnableAssetId() const + { + return m_spawnableAsset.GetId(); + } + + void PrefabInstanceSpawner::SetSpawnableAssetId(const AZ::Data::AssetId& assetId) + { + if (assetId.IsValid()) + { + AZ::Data::AssetInfo assetInfo; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, assetId); + if (assetInfo.m_assetType == m_spawnableAsset.GetType()) + { + m_spawnableAsset.Create(assetId, false); + LoadAssets(); + } + else + { + AZ_Error( + "Vegetation", false, "Asset '%s' is of type %s, but expected a Spawnable type.", + assetId.ToString().c_str(), assetInfo.m_assetType.ToString().c_str()); + } + } + else + { + // An invalid asset ID is treated as a valid way to spawn "empty" instances, so don't print an error, just clear out + // the asset to that it has an invalid asset reference. (See also HasEmptyAssetReferences() above) + m_spawnableAsset = AZ::Data::Asset(); + LoadAssets(); + } + } + + AZ::u32 PrefabInstanceSpawner::SpawnableAssetChanged() + { + // Whenever we change the spawnable asset, force a refresh of the Entity Inspector + // since we want the Descriptor List to refresh the name of the entry. + NotifyOnAssetsUnloaded(); + return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; + } + + InstancePtr PrefabInstanceSpawner::CreateInstance(const InstanceData& instanceData) + { + InstancePtr opaqueInstanceData = nullptr; + + // Create a Transform that represents our instance. + AZ::Transform world = AZ::Transform::CreateFromQuaternionAndTranslation( + instanceData.m_alignment * instanceData.m_rotation, instanceData.m_position); + world.MultiplyByUniformScale(instanceData.m_scale); + + // Create a callback for SpawnAllEntities that will set the transform of the root entity to the correct position / rotation / scale + // for our spawned instance. + auto preSpawnCB = [this, world]( + [[maybe_unused]] AzFramework::EntitySpawnTicket::Id ticketId, AzFramework::SpawnableEntityContainerView view) + { + AZ::Entity* rootEntity = *view.begin(); + + AzFramework::TransformComponent* entityTransform = rootEntity->FindComponent(); + + if (entityTransform) + { + entityTransform->SetWorldTM(world); + } + }; + + // Create the EntitySpawnTicket here. This pointer is going to get handed off to the vegetation system as opaque instance data, + // where it will be tracked and held onto for the lifetime of the vegetation instance. The vegetation system will pass it back + // in to DestroyInstance at the end of the lifetime, so that's the one place where we will delete the ticket pointers. + AzFramework::EntitySpawnTicket* ticket = new AzFramework::EntitySpawnTicket(m_spawnableAsset); + if (ticket->IsValid()) + { + // Track the ticket that we've created. + m_instanceTickets.emplace(ticket); + + AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs; + optionalArgs.m_preInsertionCallback = AZStd::move(preSpawnCB); + AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*ticket, AZStd::move(optionalArgs)); + + opaqueInstanceData = ticket; + } + else + { + // Something went wrong! + AZ_Assert(ticket->IsValid(), "Unable to instantiate spawnable asset"); + delete ticket; + } + + return opaqueInstanceData; + } + + void PrefabInstanceSpawner::DespawnAssetInstance(AzFramework::EntitySpawnTicket* ticket) + { + if (ticket->IsValid()) + { + AzFramework::SpawnableEntitiesInterface::Get()->DespawnAllEntities(*ticket); + } + } + + void PrefabInstanceSpawner::DestroyInstance([[maybe_unused]] InstanceId id, InstancePtr instance) + { + if (instance) + { + auto ticket = reinterpret_cast(instance); + + // If the spawnable asset instantiated successfully, we should have a record of it. + auto foundInstance = m_instanceTickets.find(ticket); + AZ_Assert(foundInstance != m_instanceTickets.end(), "Couldn't find CreateInstance entry for the EntitySpawnTicket."); + if (foundInstance != m_instanceTickets.end()) + { + // The call to DespawnAssetInstance above is technically redundant right now, because when we delete the ticket pointer + // below it will automatically despawn everything anyways. However, it's nice to have a single explicit call to despawn, + // in case we ever need a place to add logging, or have a callback when despawning is complete, etc. + DespawnAssetInstance(ticket); + m_instanceTickets.erase(foundInstance); + } + + // The vegetation system has stopped tracking this instance, so it's now safe to delete the ticket pointer. + delete ticket; + } + } +} // namespace Vegetation diff --git a/Gems/Vegetation/Code/Source/VegetationEditorModule.cpp b/Gems/Vegetation/Code/Source/VegetationEditorModule.cpp index ce1f129e1a..c044487704 100644 --- a/Gems/Vegetation/Code/Source/VegetationEditorModule.cpp +++ b/Gems/Vegetation/Code/Source/VegetationEditorModule.cpp @@ -10,8 +10,6 @@ * */ -#include "Vegetation_precompiled.h" - #include #include diff --git a/Gems/Vegetation/Code/Source/VegetationEditorModule.h b/Gems/Vegetation/Code/Source/VegetationEditorModule.h index 76e409f0b5..107d400d1e 100644 --- a/Gems/Vegetation/Code/Source/VegetationEditorModule.h +++ b/Gems/Vegetation/Code/Source/VegetationEditorModule.h @@ -12,7 +12,6 @@ #pragma once -#include "Vegetation_precompiled.h" #include namespace Vegetation diff --git a/Gems/Vegetation/Code/Source/VegetationModule.cpp b/Gems/Vegetation/Code/Source/VegetationModule.cpp index 90215e7996..7daa33b35c 100644 --- a/Gems/Vegetation/Code/Source/VegetationModule.cpp +++ b/Gems/Vegetation/Code/Source/VegetationModule.cpp @@ -10,8 +10,6 @@ * */ -#include "Vegetation_precompiled.h" - #include #include diff --git a/Gems/Vegetation/Code/Source/VegetationModule.h b/Gems/Vegetation/Code/Source/VegetationModule.h index 0b36eb3856..26d0a169aa 100644 --- a/Gems/Vegetation/Code/Source/VegetationModule.h +++ b/Gems/Vegetation/Code/Source/VegetationModule.h @@ -12,7 +12,6 @@ #pragma once -#include "Vegetation_precompiled.h" #include namespace Vegetation diff --git a/Gems/Vegetation/Code/Source/Vegetation_precompiled.h b/Gems/Vegetation/Code/Source/VegetationProfiler.h similarity index 90% rename from Gems/Vegetation/Code/Source/Vegetation_precompiled.h rename to Gems/Vegetation/Code/Source/VegetationProfiler.h index 92116dd175..fa8ff7865b 100644 --- a/Gems/Vegetation/Code/Source/Vegetation_precompiled.h +++ b/Gems/Vegetation/Code/Source/VegetationProfiler.h @@ -11,8 +11,6 @@ */ #pragma once -#include // Many CryCommon files require that this is included first. - // VEG_PROFILE_ENABLED is defined in the wscript // VEG_PROFILE_ENABLED is only defined in the Vegetation gem by default #if defined(VEG_PROFILE_ENABLED) diff --git a/Gems/Vegetation/Code/Source/VegetationSystemComponent.cpp b/Gems/Vegetation/Code/Source/VegetationSystemComponent.cpp index 7cad51e025..78a6a4171d 100644 --- a/Gems/Vegetation/Code/Source/VegetationSystemComponent.cpp +++ b/Gems/Vegetation/Code/Source/VegetationSystemComponent.cpp @@ -9,7 +9,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" #include "VegetationSystemComponent.h" #include @@ -25,8 +24,7 @@ #include #include #include - -#include +#include namespace Vegetation { @@ -73,6 +71,7 @@ namespace Vegetation InstanceSpawner::Reflect(context); EmptyInstanceSpawner::Reflect(context); DynamicSliceInstanceSpawner::Reflect(context); + PrefabInstanceSpawner::Reflect(context); Descriptor::Reflect(context); AreaConfig::Reflect(context); AreaComponentBase::Reflect(context); diff --git a/Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp b/Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp index c3aa910b47..3ced558c3d 100644 --- a/Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp +++ b/Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp @@ -9,8 +9,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" - #include "VegetationTest.h" #include "VegetationMocks.h" diff --git a/Gems/Vegetation/Code/Tests/EmptyInstanceSpawnerTests.cpp b/Gems/Vegetation/Code/Tests/EmptyInstanceSpawnerTests.cpp index 19ebca7602..dae9a692d5 100644 --- a/Gems/Vegetation/Code/Tests/EmptyInstanceSpawnerTests.cpp +++ b/Gems/Vegetation/Code/Tests/EmptyInstanceSpawnerTests.cpp @@ -9,8 +9,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" - #include "VegetationTest.h" #include "VegetationMocks.h" diff --git a/Gems/Vegetation/Code/Tests/PrefabInstanceSpawnerTests.cpp b/Gems/Vegetation/Code/Tests/PrefabInstanceSpawnerTests.cpp new file mode 100644 index 0000000000..ed618278d2 --- /dev/null +++ b/Gems/Vegetation/Code/Tests/PrefabInstanceSpawnerTests.cpp @@ -0,0 +1,345 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#include "VegetationTest.h" +#include "VegetationMocks.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace UnitTest +{ + // Mock VegetationSystemComponent is needed to reflect only the PrefabInstanceSpawner. + class MockPrefabInstanceVegetationSystemComponent + : public AZ::Component + { + public: + AZ_COMPONENT(MockPrefabInstanceVegetationSystemComponent, "{5EC9AA35-2653-4326-853F-F2056F0DE36C}", AZ::Component); + + void Activate() override {} + void Deactivate() override {} + + static void Reflect(AZ::ReflectContext* reflect) + { + Vegetation::InstanceSpawner::Reflect(reflect); + Vegetation::PrefabInstanceSpawner::Reflect(reflect); + Vegetation::EmptyInstanceSpawner::Reflect(reflect); + } + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("VegetationSystemService")); + } + }; + + // To test prefab spawning, we need to mock up enough of the asset management system and the spawnable + // asset handling to pretend like we're loading/unloading spawnables successfully. + class PrefabInstanceSpawnerTests + : public VegetationComponentTests + , public UnitTest::SetRestoreFileIOBaseRAII + , public Vegetation::DescriptorNotificationBus::Handler + , public AZ::Data::AssetCatalogRequestBus::Handler + , public AZ::Data::AssetHandler + , public AZ::Data::AssetCatalog + { + public: + PrefabInstanceSpawnerTests() + : UnitTest::SetRestoreFileIOBaseRAII(m_fileIOMock) + { + AZ::IO::MockFileIOBase::InstallDefaultReturns(m_fileIOMock); + AzFramework::MockSpawnableEntitiesInterface::InstallDefaultReturns(m_spawnableEntitiesInterfaceMock); + } + + void RegisterComponentDescriptors() override + { + m_app.RegisterComponentDescriptor(MockPrefabInstanceVegetationSystemComponent::CreateDescriptor()); + } + + void SetUp() override + { + VegetationComponentTests::SetUp(); + + // Create a real Asset Mananger, and point to ourselves as the handler for Spawnable. + AZ::AllocatorInstance::Create(); + AZ::AllocatorInstance::Create(); + + + // Initialize the job manager with 1 thread for the AssetManager to use. + AZ::JobManagerDesc jobDesc; + AZ::JobManagerThreadDesc threadDesc; + jobDesc.m_workerThreads.push_back(threadDesc); + m_jobManager = aznew AZ::JobManager(jobDesc); + m_jobContext = aznew AZ::JobContext(*m_jobManager); + AZ::JobContext::SetGlobalContext(m_jobContext); + + AZ::Data::AssetManager::Descriptor descriptor; + AZ::Data::AssetManager::Create(descriptor); + AZ::Data::AssetManager::Instance().RegisterHandler(this, AZ::AzTypeInfo::Uuid()); + AZ::Data::AssetManager::Instance().RegisterCatalog(this, AZ::AzTypeInfo::Uuid()); + + // Intercept messages for finding assets by name. + AZ::Data::AssetCatalogRequestBus::Handler::BusConnect(); + } + + void TearDown() override + { + // Give the AssetManager a chance to fire off any lingering events and perform cleanup for any + // spawnable assets we loaded. + AZ::Data::AssetManager::Instance().DispatchEvents(); + + AZ::Data::AssetManager::Instance().UnregisterCatalog(this); + AZ::Data::AssetManager::Instance().UnregisterHandler(this); + + AZ::Data::AssetCatalogRequestBus::Handler::BusDisconnect(); + + AZ::Data::AssetManager::Destroy(); + + AZ::JobContext::SetGlobalContext(nullptr); + delete m_jobContext; + delete m_jobManager; + + AZ::AllocatorInstance::Destroy(); + AZ::AllocatorInstance::Destroy(); + + VegetationComponentTests::TearDown(); + } + + // Helper methods: + + // Set up a mock asset with the given name and id and direct the instance spawner to use it. + void CreateAndSetMockAsset(Vegetation::PrefabInstanceSpawner& instanceSpawner, AZ::Data::AssetId assetId, AZStd::string assetPath) + { + // Save these off for use from our mock AssetCatalogRequestBus + m_assetId = assetId; + m_assetPath = assetPath; + + Vegetation::DescriptorNotificationBus::Handler::BusConnect(&instanceSpawner); + + // Tell the spawner to use this asset. Note that this also triggers a LoadAssets() call internally. + instanceSpawner.SetSpawnableAssetPath(m_assetPath); + + // Our instance spawner should now have a valid asset reference. + // It may or may not be loaded already by the time we get here, + // depending on how quickly the Asset Processor job thread picks it up. + EXPECT_FALSE(instanceSpawner.HasEmptyAssetReferences()); + + // Since the asset load is going through the real AssetManager, there's a delay while a separate + // job thread executes and actually loads our mock spawnable asset. + // If our asset hasn't loaded successfully after 5 seconds, it's unlikely to succeed. + // This choice of delay should be *reasonably* safe because it's all CPU-based processing, + // no actual I/O occurs as a part of the test. + constexpr int sleepMs = 10; + constexpr int totalWaitTimeMs = 5000; + int numRetries = totalWaitTimeMs / sleepMs; + while ((m_numOnLoadedCalls < 1) && (numRetries >= 0)) + { + AZ::Data::AssetManager::Instance().DispatchEvents(); + AZ::SystemTickBus::Broadcast(&AZ::SystemTickBus::Events::OnSystemTick); + AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(sleepMs)); + numRetries--; + } + + ASSERT_TRUE(m_numOnLoadedCalls == 1); + EXPECT_TRUE(instanceSpawner.IsLoaded()); + EXPECT_TRUE(instanceSpawner.IsSpawnable()); + + Vegetation::DescriptorNotificationBus::Handler::BusDisconnect(); + } + + + // AssetHandler + // Minimalist mocks to look like a Spawnable has been created/loaded/destroyed successfully + AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, [[maybe_unused]] const AZ::Data::AssetType& type) override + { + AzFramework::Spawnable* spawnableAsset = new AzFramework::Spawnable(id); + MockAssetData* temp = reinterpret_cast(spawnableAsset); + temp->SetStatus(AZ::Data::AssetData::AssetStatus::NotLoaded); + + return spawnableAsset; + } + + void DestroyAsset(AZ::Data::AssetPtr ptr) override { delete ptr; } + void GetHandledAssetTypes(AZStd::vector& assetTypes) override + { + assetTypes.push_back(AZ::AzTypeInfo::Uuid()); + } + AZ::Data::AssetHandler::LoadResult LoadAssetData( + const AZ::Data::Asset& asset, + AZStd::shared_ptr stream, + [[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB) + { + MockAssetData* temp = reinterpret_cast(asset.GetData()); + temp->SetStatus(AZ::Data::AssetData::AssetStatus::Ready); + return AZ::Data::AssetHandler::LoadResult::LoadComplete; + } + + // DescriptorNotificationBus + // Keep track of whether or not the Spawner successfully loaded the asset and notified listeners + void OnDescriptorAssetsLoaded() override { m_numOnLoadedCalls++; } + + // AssetCatalogRequestBus + // Minimalist mocks to provide our desired asset path or asset id + AZStd::string GetAssetPathById(const AZ::Data::AssetId& /*id*/) override { return m_assetPath; } + AZ::Data::AssetId GetAssetIdByPath(const char* /*path*/, const AZ::Data::AssetType& /*typeToRegister*/, bool /*autoRegisterIfNotFound*/) override { return m_assetId; } + AZ::Data::AssetInfo GetAssetInfoById(const AZ::Data::AssetId& /*id*/) override + { + AZ::Data::AssetInfo assetInfo; + assetInfo.m_assetId = m_assetId; + assetInfo.m_assetType = AZ::AzTypeInfo::Uuid(); + assetInfo.m_relativePath = m_assetPath; + return assetInfo; + } + + // AssetCatalog + // Minimalist mock to pretend like we've loaded a Spawnable asset + AZ::Data::AssetStreamInfo GetStreamInfoForLoad( + [[maybe_unused]] const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override + { + EXPECT_TRUE(type == AZ::AzTypeInfo::Uuid()); + AZ::Data::AssetStreamInfo info; + info.m_dataOffset = 0; + info.m_streamName = m_assetPath; + info.m_dataLen = 0; + info.m_streamFlags = AZ::IO::OpenMode::ModeRead; + + return info; + } + + AZStd::string m_assetPath; + AZ::Data::AssetId m_assetId; + int m_numOnLoadedCalls = 0; + + AZ::JobManager* m_jobManager{ nullptr }; + AZ::JobContext* m_jobContext{ nullptr }; + ::testing::NiceMock m_fileIOMock; + ::testing::NiceMock m_spawnableEntitiesInterfaceMock; + }; + + TEST_F(PrefabInstanceSpawnerTests, BasicInitializationTest) + { + // Basic test to make sure we can construct / destroy without errors. + + Vegetation::PrefabInstanceSpawner instanceSpawner; + } + + TEST_F(PrefabInstanceSpawnerTests, DefaultSpawnersAreEqual) + { + // Two different instances of the default PrefabInstanceSpawner should be considered data-equivalent. + + Vegetation::PrefabInstanceSpawner instanceSpawner1; + Vegetation::PrefabInstanceSpawner instanceSpawner2; + + EXPECT_TRUE(instanceSpawner1 == instanceSpawner2); + } + + TEST_F(PrefabInstanceSpawnerTests, DifferentSpawnersAreNotEqual) + { + // Two spawners with different data should *not* be data-equivalent. + + Vegetation::PrefabInstanceSpawner instanceSpawner1; + Vegetation::PrefabInstanceSpawner instanceSpawner2; + + // Give the second instance spawner a non-default asset reference. + CreateAndSetMockAsset(instanceSpawner2, AZ::Uuid::CreateRandom(), "test"); + + // The test is written this way because only the == operator is overloaded. + EXPECT_TRUE(!(instanceSpawner1 == instanceSpawner2)); + } + + TEST_F(PrefabInstanceSpawnerTests, LoadAndUnloadAssets) + { + // The spawner should successfully load/unload assets without errors. + + Vegetation::PrefabInstanceSpawner instanceSpawner; + + // Our instance spawner should be empty before we set the assets. + EXPECT_TRUE(instanceSpawner.HasEmptyAssetReferences()); + + // This will test the asset load. + CreateAndSetMockAsset(instanceSpawner, AZ::Uuid::CreateRandom(), "test"); + + // Test the asset unload works too. + Vegetation::DescriptorNotificationBus::Handler::BusConnect(&instanceSpawner); + instanceSpawner.UnloadAssets(); + EXPECT_FALSE(instanceSpawner.IsLoaded()); + EXPECT_FALSE(instanceSpawner.IsSpawnable()); + Vegetation::DescriptorNotificationBus::Handler::BusDisconnect(); + } + + TEST_F(PrefabInstanceSpawnerTests, CreateAndDestroyInstance) + { + // The spawner should successfully create and destroy an instance without errors. + + Vegetation::PrefabInstanceSpawner instanceSpawner; + + CreateAndSetMockAsset(instanceSpawner, AZ::Uuid::CreateRandom(), "test"); + + instanceSpawner.OnRegisterUniqueDescriptor(); + + Vegetation::InstanceData instanceData; + Vegetation::InstancePtr instance = instanceSpawner.CreateInstance(instanceData); + EXPECT_TRUE(instance); + instanceSpawner.DestroyInstance(0, instance); + + instanceSpawner.OnReleaseUniqueDescriptor(); + } + + TEST_F(PrefabInstanceSpawnerTests, SpawnerRegisteredWithDescriptor) + { + // Validate that the Descriptor successfully gets PrefabInstanceSpawner registered with it, + // as long as InstanceSpawner and PrefabInstanceSpawner have been reflected. + + MockPrefabInstanceVegetationSystemComponent* component = nullptr; + auto entity = CreateEntity(&component); + + Vegetation::Descriptor descriptor; + descriptor.RefreshSpawnerTypeList(); + auto spawnerTypes = descriptor.GetSpawnerTypeList(); + EXPECT_TRUE(spawnerTypes.size() > 0); + const auto& prefabSpawnerEntry = AZStd::find( + spawnerTypes.begin(), spawnerTypes.end(), + AZStd::pair(Vegetation::PrefabInstanceSpawner::RTTI_Type(), "PrefabInstanceSpawner")); + EXPECT_NE(prefabSpawnerEntry, spawnerTypes.end()); + } + + TEST_F(PrefabInstanceSpawnerTests, DescriptorCreatesCorrectSpawner) + { + // Validate that the Descriptor successfully creates a new PrefabInstanceSpawner if we change + // the spawner type on the Descriptor. + + MockPrefabInstanceVegetationSystemComponent* component = nullptr; + auto entity = CreateEntity(&component); + + // We expect the Descriptor to start off with something other than Prefab spawner, but then should correctly get an + // PrefabInstanceSpawner after we change spawnerType. + Vegetation::Descriptor descriptor; + EXPECT_NE(azrtti_typeid(*(descriptor.GetInstanceSpawner())),Vegetation::PrefabInstanceSpawner::RTTI_Type()); + descriptor.m_spawnerType = Vegetation::PrefabInstanceSpawner::RTTI_Type(); + descriptor.RefreshSpawnerTypeList(); + descriptor.SpawnerTypeChanged(); + EXPECT_EQ(azrtti_typeid(*(descriptor.GetInstanceSpawner())), Vegetation::PrefabInstanceSpawner::RTTI_Type()); + } +} diff --git a/Gems/Vegetation/Code/Tests/VegetationAreaSystemComponentTest.cpp b/Gems/Vegetation/Code/Tests/VegetationAreaSystemComponentTest.cpp index 8c72b01fd5..c06db1b9d8 100644 --- a/Gems/Vegetation/Code/Tests/VegetationAreaSystemComponentTest.cpp +++ b/Gems/Vegetation/Code/Tests/VegetationAreaSystemComponentTest.cpp @@ -9,8 +9,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" - #include #include #include diff --git a/Gems/Vegetation/Code/Tests/VegetationComponentDescriptorTests.cpp b/Gems/Vegetation/Code/Tests/VegetationComponentDescriptorTests.cpp index 6e2aa42c9b..a19a4f2516 100644 --- a/Gems/Vegetation/Code/Tests/VegetationComponentDescriptorTests.cpp +++ b/Gems/Vegetation/Code/Tests/VegetationComponentDescriptorTests.cpp @@ -9,8 +9,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" - #include "VegetationTest.h" #include "VegetationMocks.h" diff --git a/Gems/Vegetation/Code/Tests/VegetationComponentFilterTests.cpp b/Gems/Vegetation/Code/Tests/VegetationComponentFilterTests.cpp index cfd621b397..17e3626e32 100644 --- a/Gems/Vegetation/Code/Tests/VegetationComponentFilterTests.cpp +++ b/Gems/Vegetation/Code/Tests/VegetationComponentFilterTests.cpp @@ -9,8 +9,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" - #include "VegetationTest.h" #include "VegetationMocks.h" diff --git a/Gems/Vegetation/Code/Tests/VegetationComponentModifierTests.cpp b/Gems/Vegetation/Code/Tests/VegetationComponentModifierTests.cpp index 035e4efdc8..60a0e73250 100644 --- a/Gems/Vegetation/Code/Tests/VegetationComponentModifierTests.cpp +++ b/Gems/Vegetation/Code/Tests/VegetationComponentModifierTests.cpp @@ -9,8 +9,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" - #include "VegetationTest.h" #include "VegetationMocks.h" diff --git a/Gems/Vegetation/Code/Tests/VegetationComponentOperationTests.cpp b/Gems/Vegetation/Code/Tests/VegetationComponentOperationTests.cpp index c69024826b..b9dce45ccd 100644 --- a/Gems/Vegetation/Code/Tests/VegetationComponentOperationTests.cpp +++ b/Gems/Vegetation/Code/Tests/VegetationComponentOperationTests.cpp @@ -9,8 +9,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" - #include "VegetationTest.h" #include "VegetationMocks.h" diff --git a/Gems/Vegetation/Code/Tests/VegetationTest.cpp b/Gems/Vegetation/Code/Tests/VegetationTest.cpp index d570cd3386..b58b80a3a9 100644 --- a/Gems/Vegetation/Code/Tests/VegetationTest.cpp +++ b/Gems/Vegetation/Code/Tests/VegetationTest.cpp @@ -9,8 +9,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#include "Vegetation_precompiled.h" - #include #include #include "VegetationTest.h" diff --git a/Gems/Vegetation/Code/vegetation_files.cmake b/Gems/Vegetation/Code/vegetation_files.cmake index abfd568862..896720d30e 100644 --- a/Gems/Vegetation/Code/vegetation_files.cmake +++ b/Gems/Vegetation/Code/vegetation_files.cmake @@ -10,13 +10,13 @@ # set(FILES - Source/Vegetation_precompiled.h Include/Vegetation/DescriptorListAsset.h Include/Vegetation/Descriptor.h Include/Vegetation/InstanceData.h Include/Vegetation/InstanceSpawner.h Include/Vegetation/DynamicSliceInstanceSpawner.h Include/Vegetation/EmptyInstanceSpawner.h + Include/Vegetation/PrefabInstanceSpawner.h Include/Vegetation/AreaComponentBase.h Include/Vegetation/Ebuses/AreaSystemRequestBus.h Include/Vegetation/Ebuses/AreaNotificationBus.h @@ -104,6 +104,7 @@ set(FILES Source/Descriptor.cpp Source/DynamicSliceInstanceSpawner.cpp Source/EmptyInstanceSpawner.cpp + Source/PrefabInstanceSpawner.cpp Source/VegetationSystemComponent.cpp Source/VegetationSystemComponent.h Source/InstanceData.cpp diff --git a/Gems/Vegetation/Code/vegetation_shared_files.cmake b/Gems/Vegetation/Code/vegetation_shared_files.cmake index 82b02b3881..4a49699f79 100644 --- a/Gems/Vegetation/Code/vegetation_shared_files.cmake +++ b/Gems/Vegetation/Code/vegetation_shared_files.cmake @@ -14,4 +14,5 @@ set(FILES Source/AreaSystemComponent.h Source/VegetationModule.cpp Source/VegetationModule.h + Source/VegetationProfiler.h ) diff --git a/Gems/Vegetation/Code/vegetation_tests_files.cmake b/Gems/Vegetation/Code/vegetation_tests_files.cmake index 2ce54d3033..08656de9d2 100644 --- a/Gems/Vegetation/Code/vegetation_tests_files.cmake +++ b/Gems/Vegetation/Code/vegetation_tests_files.cmake @@ -17,6 +17,7 @@ set(FILES Tests/VegetationComponentFilterTests.cpp Tests/DynamicSliceInstanceSpawnerTests.cpp Tests/EmptyInstanceSpawnerTests.cpp + Tests/PrefabInstanceSpawnerTests.cpp Tests/VegetationAreaSystemComponentTest.cpp Tests/VegetationTest.cpp Tests/VegetationTest.h diff --git a/Gems/Vegetation_Gem_Assets/CMakeLists.txt b/Gems/Vegetation_Gem_Assets/CMakeLists.txt index 4d5680a30d..a410a242c7 100644 --- a/Gems/Vegetation_Gem_Assets/CMakeLists.txt +++ b/Gems/Vegetation_Gem_Assets/CMakeLists.txt @@ -8,3 +8,8 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # + +# This will export its "SourcePaths" to the generated "cmake_dependencies..assetbuilder.setreg" +if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_create_alias(NAME Vegetation_Gem_Assets.Builders NAMESPACE Gem) +endif() diff --git a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp index e8e03556e2..89b8035764 100644 --- a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp +++ b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp @@ -257,17 +257,18 @@ namespace WhiteBox void EditorWhiteBoxComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); + required.push_back(AZ_CRC_CE("TransformService")); } void EditorWhiteBoxComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC("WhiteBoxService", 0x2f2f42b8)); + provided.push_back(AZ_CRC_CE("WhiteBoxService")); } void EditorWhiteBoxComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { incompatible.push_back(AZ_CRC_CE("NonUniformScaleService")); + incompatible.push_back(AZ_CRC_CE("MeshService")); } EditorWhiteBoxComponent::EditorWhiteBoxComponent() = default; diff --git a/Templates/AssetGem/Template/CMakeLists.txt b/Templates/AssetGem/Template/CMakeLists.txt new file mode 100644 index 0000000000..a220cce911 --- /dev/null +++ b/Templates/AssetGem/Template/CMakeLists.txt @@ -0,0 +1,18 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +# This will export the path to the directory containing the gem.json +# to the "SourcePaths" entry within the "cmake_dependencies..assetbuilder.setreg" +# which is generated when cmake is run +# This path is the gem root directory +if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_create_alias(NAME ${Name}.Builders NAMESPACE Gem) +endif() diff --git a/Templates/AssetGem/Template/gem.json b/Templates/AssetGem/Template/gem.json new file mode 100644 index 0000000000..5b8fb3fde0 --- /dev/null +++ b/Templates/AssetGem/Template/gem.json @@ -0,0 +1,14 @@ +{ + "gem_name": "${Name}", + "origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", + "license": "What license ${Name} uses goes here: i.e. https://opensource.org/licenses/MIT", + "display_name": "${Name}", + "summary": "A short description of ${Name}.", + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "${Name}" + ], + "icon_path": "preview.png" +} diff --git a/Templates/AssetGem/Template/preview.png b/Templates/AssetGem/Template/preview.png new file mode 100644 index 0000000000..2f1ed47754 --- /dev/null +++ b/Templates/AssetGem/Template/preview.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d6204c6730e5675791765ca194e9b1cbec282208e280507de830afc2805e5fa +size 41127 diff --git a/Templates/AssetGem/template.json b/Templates/AssetGem/template.json new file mode 100644 index 0000000000..e858dc526d --- /dev/null +++ b/Templates/AssetGem/template.json @@ -0,0 +1,38 @@ +{ + "template_name": "AssetGem", + "origin": "The primary repo for AssetGem goes here: i.e. http://www.mydomain.com", + "license": "What license AssetGem uses goes here: i.e. https://opensource.org/licenses/MIT", + "display_name": "AssetGem", + "summary": "A short description of AssetGem template.", + "canonical_tags": [], + "user_tags": [ + "AssetGem" + ], + "icon_path": "preview.png", + "copyFiles": [ + { + "file": "CMakeLists.txt", + "origin": "CMakeLists.txt", + "isTemplated": true, + "isOptional": false + }, + { + "file": "gem.json", + "origin": "gem.json", + "isTemplated": true, + "isOptional": false + }, + { + "file": "preview.png", + "origin": "preview.png", + "isTemplated": false, + "isOptional": false + } + ], + "createDirectories": [ + { + "dir": "Assets", + "origin": "Assets" + } + ] +} diff --git a/Templates/DefaultGem/Template/Code/${NameLower}_editor_shared_files.cmake b/Templates/DefaultGem/Template/Code/${NameLower}_editor_shared_files.cmake index 6b9ddc02aa..415c25bfa1 100644 --- a/Templates/DefaultGem/Template/Code/${NameLower}_editor_shared_files.cmake +++ b/Templates/DefaultGem/Template/Code/${NameLower}_editor_shared_files.cmake @@ -10,5 +10,5 @@ # {END_LICENSE} set(FILES - Source/${Name}Module.cpp + Source/${Name}EditorModule.cpp ) diff --git a/Templates/DefaultGem/Template/Code/${NameLower}_files.cmake b/Templates/DefaultGem/Template/Code/${NameLower}_files.cmake index 0aec97f7cb..b61972a3f5 100644 --- a/Templates/DefaultGem/Template/Code/${NameLower}_files.cmake +++ b/Templates/DefaultGem/Template/Code/${NameLower}_files.cmake @@ -10,6 +10,8 @@ # {END_LICENSE} set(FILES + Include/${Name}/${Name}Bus.h + Source/${Name}ModuleInterface.h Source/${Name}SystemComponent.cpp Source/${Name}SystemComponent.h ) diff --git a/Templates/DefaultGem/Template/Code/CMakeLists.txt b/Templates/DefaultGem/Template/Code/CMakeLists.txt index b0e52dd79f..25b393302c 100644 --- a/Templates/DefaultGem/Template/Code/CMakeLists.txt +++ b/Templates/DefaultGem/Template/Code/CMakeLists.txt @@ -85,7 +85,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) ) ly_add_target( - NAME ${Name}.Editor MODULE + NAME ${Name}.Editor GEM_MODULE NAMESPACE Gem AUTOMOC OUTPUT_NAME Gem.${Name}.Editor diff --git a/Templates/DefaultGem/Template/Code/Include/${Name}/${Name}Bus.h b/Templates/DefaultGem/Template/Code/Include/${Name}/${Name}Bus.h index 32f34e309e..672e329db4 100644 --- a/Templates/DefaultGem/Template/Code/Include/${Name}/${Name}Bus.h +++ b/Templates/DefaultGem/Template/Code/Include/${Name}/${Name}Bus.h @@ -22,7 +22,7 @@ namespace ${SanitizedCppName} class ${SanitizedCppName}Requests { public: - AZ_RTTI(${SanitizedCppName}Requests, "${Random_Uuid}"); + AZ_RTTI(${SanitizedCppName}Requests, "{${Random_Uuid}}"); virtual ~${SanitizedCppName}Requests() = default; // Put your public methods here }; diff --git a/Templates/DefaultGem/Template/Code/Source/${Name}EditorModule.cpp b/Templates/DefaultGem/Template/Code/Source/${Name}EditorModule.cpp new file mode 100644 index 0000000000..d548e23162 --- /dev/null +++ b/Templates/DefaultGem/Template/Code/Source/${Name}EditorModule.cpp @@ -0,0 +1,51 @@ +// {BEGIN_LICENSE} +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ +// {END_LICENSE} + +#include <${Name}ModuleInterface.h> +#include <${Name}EditorSystemComponent.h> + +namespace ${SanitizedCppName} +{ + class ${SanitizedCppName}EditorModule + : public ${SanitizedCppName}ModuleInterface + { + public: + AZ_RTTI(${SanitizedCppName}EditorModule, "${ModuleClassId}", ${SanitizedCppName}ModuleInterface); + AZ_CLASS_ALLOCATOR(${SanitizedCppName}EditorModule, AZ::SystemAllocator, 0); + + ${SanitizedCppName}EditorModule() + { + // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here. + // Add ALL components descriptors associated with this gem to m_descriptors. + // This will associate the AzTypeInfo information for the components with the the SerializeContext, BehaviorContext and EditContext. + // This happens through the [MyComponent]::Reflect() function. + m_descriptors.insert(m_descriptors.end(), { + ${SanitizedCppName}EditorSystemComponent::CreateDescriptor(), + }); + } + + /** + * Add required SystemComponents to the SystemEntity. + * Non-SystemComponents should not be added here + */ + AZ::ComponentTypeList GetRequiredSystemComponents() const override + { + return AZ::ComponentTypeList { + azrtti_typeid<${SanitizedCppName}EditorSystemComponent>(), + }; + } + }; +}// namespace ${SanitizedCppName} + +AZ_DECLARE_MODULE_CLASS(Gem_${SanitizedCppName}, ${SanitizedCppName}::${SanitizedCppName}EditorModule) diff --git a/Templates/DefaultGem/Template/Code/Source/${Name}EditorSystemComponent.cpp b/Templates/DefaultGem/Template/Code/Source/${Name}EditorSystemComponent.cpp index fedc37da6b..3cb9551766 100644 --- a/Templates/DefaultGem/Template/Code/Source/${Name}EditorSystemComponent.cpp +++ b/Templates/DefaultGem/Template/Code/Source/${Name}EditorSystemComponent.cpp @@ -21,34 +21,47 @@ namespace ${SanitizedCppName} { if (auto serializeContext = azrtti_cast(context)) { - serializeContext->Class<${SanitizedCppName}EditorSystemComponent, AZ::Component>()->Version(1); + serializeContext->Class<${SanitizedCppName}EditorSystemComponent, ${SanitizedCppName}SystemComponent>() + ->Version(0); } } - ${SanitizedCppName}EditorSystemComponent::${SanitizedCppName}EditorSystemComponent() + ${SanitizedCppName}EditorSystemComponent::${SanitizedCppName}EditorSystemComponent() = default; + + ${SanitizedCppName}EditorSystemComponent::~${SanitizedCppName}EditorSystemComponent() = default; + + void ${SanitizedCppName}EditorSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - if (${SanitizedCppName}Interface::Get() == nullptr) - { - ${SanitizedCppName}Interface::Register(this); - } + BaseSystemComponent::GetProvidedServices(provided); + provided.push_back(AZ_CRC_CE("${SanitizedCppName}EditorService")); } - ${SanitizedCppName}EditorSystemComponent::~${SanitizedCppName}EditorSystemComponent() + void ${SanitizedCppName}EditorSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - if (${SanitizedCppName}Interface::Get() == this) - { - ${SanitizedCppName}Interface::Unregister(this); - } + BaseSystemComponent::GetIncompatibleServices(incompatible); + incompatible.push_back(AZ_CRC_CE("${SanitizedCppName}EditorService")); + } + + void ${SanitizedCppName}EditorSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) + { + BaseSystemComponent::GetRequiredServices(required); + } + + void ${SanitizedCppName}EditorSystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent) + { + BaseSystemComponent::GetDependentServices(dependent); } void ${SanitizedCppName}EditorSystemComponent::Activate() { + ${SanitizedCppName}SystemComponent::Activate(); AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); } void ${SanitizedCppName}EditorSystemComponent::Deactivate() { AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); + ${SanitizedCppName}SystemComponent::Deactivate(); } } // namespace ${SanitizedCppName} diff --git a/Templates/DefaultGem/Template/Code/Source/${Name}EditorSystemComponent.h b/Templates/DefaultGem/Template/Code/Source/${Name}EditorSystemComponent.h index ef7b0a2f2e..8e9a64946f 100644 --- a/Templates/DefaultGem/Template/Code/Source/${Name}EditorSystemComponent.h +++ b/Templates/DefaultGem/Template/Code/Source/${Name}EditorSystemComponent.h @@ -14,7 +14,7 @@ #pragma once -#include +#include <${Name}SystemComponent.h> #include @@ -22,26 +22,22 @@ namespace ${SanitizedCppName} { /// System component for ${SanitizedCppName} editor class ${SanitizedCppName}EditorSystemComponent - : public AZ::Component + : public ${SanitizedCppName}SystemComponent , private AzToolsFramework::EditorEvents::Bus::Handler { + using BaseSystemComponent = ${SanitizedCppName}SystemComponent; public: - AZ_COMPONENT(${SanitizedCppName}EditorSystemComponent, "${EditorSysCompClassId}"); + AZ_COMPONENT(${SanitizedCppName}EditorSystemComponent, "${EditorSysCompClassId}", BaseSystemComponent); static void Reflect(AZ::ReflectContext* context); ${SanitizedCppName}EditorSystemComponent(); ~${SanitizedCppName}EditorSystemComponent(); private: - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("${SanitizedCppName}EditorService")); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC("${SanitizedCppName}Service")); - } + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); // AZ::Component void Activate() override; diff --git a/Templates/DefaultGem/Template/Code/Source/${Name}Module.cpp b/Templates/DefaultGem/Template/Code/Source/${Name}Module.cpp index ca4a724f49..d7aa991395 100644 --- a/Templates/DefaultGem/Template/Code/Source/${Name}Module.cpp +++ b/Templates/DefaultGem/Template/Code/Source/${Name}Module.cpp @@ -12,38 +12,18 @@ */ // {END_LICENSE} -#include -#include +#include <${Name}ModuleInterface.h> #include <${Name}SystemComponent.h> namespace ${SanitizedCppName} { class ${SanitizedCppName}Module - : public AZ::Module + : public ${SanitizedCppName}ModuleInterface { public: - AZ_RTTI(${SanitizedCppName}Module, "${ModuleClassId}", AZ::Module); + AZ_RTTI(${SanitizedCppName}Module, "${ModuleClassId}", ${SanitizedCppName}ModuleInterface); AZ_CLASS_ALLOCATOR(${SanitizedCppName}Module, AZ::SystemAllocator, 0); - - ${SanitizedCppName}Module() - : AZ::Module() - { - // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here. - m_descriptors.insert(m_descriptors.end(), { - ${SanitizedCppName}SystemComponent::CreateDescriptor(), - }); - } - - /** - * Add required SystemComponents to the SystemEntity. - */ - AZ::ComponentTypeList GetRequiredSystemComponents() const override - { - return AZ::ComponentTypeList { - azrtti_typeid<${SanitizedCppName}SystemComponent>(), - }; - } }; }// namespace ${SanitizedCppName} diff --git a/Templates/DefaultGem/Template/Code/Source/${Name}ModuleInterface.h b/Templates/DefaultGem/Template/Code/Source/${Name}ModuleInterface.h new file mode 100644 index 0000000000..e2c96a4728 --- /dev/null +++ b/Templates/DefaultGem/Template/Code/Source/${Name}ModuleInterface.h @@ -0,0 +1,49 @@ +// {BEGIN_LICENSE} +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ +// {END_LICENSE} + +#include +#include +#include <${Name}SystemComponent.h> + +namespace ${SanitizedCppName} +{ + class ${SanitizedCppName}ModuleInterface + : public AZ::Module + { + public: + AZ_RTTI(${SanitizedCppName}ModuleInterface, "{${Random_Uuid}}", AZ::Module); + AZ_CLASS_ALLOCATOR(${SanitizedCppName}ModuleInterface, AZ::SystemAllocator, 0); + + ${SanitizedCppName}ModuleInterface() + { + // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here. + // Add ALL components descriptors associated with this gem to m_descriptors. + // This will associate the AzTypeInfo information for the components with the the SerializeContext, BehaviorContext and EditContext. + // This happens through the [MyComponent]::Reflect() function. + m_descriptors.insert(m_descriptors.end(), { + ${SanitizedCppName}SystemComponent::CreateDescriptor(), + }); + } + + /** + * Add required SystemComponents to the SystemEntity. + */ + AZ::ComponentTypeList GetRequiredSystemComponents() const override + { + return AZ::ComponentTypeList{ + azrtti_typeid<${SanitizedCppName}SystemComponent>(), + }; + } + }; +}// namespace ${SanitizedCppName} diff --git a/Templates/DefaultGem/Template/Code/Source/${Name}SystemComponent.cpp b/Templates/DefaultGem/Template/Code/Source/${Name}SystemComponent.cpp index 8f7eabf74e..17aa437151 100644 --- a/Templates/DefaultGem/Template/Code/Source/${Name}SystemComponent.cpp +++ b/Templates/DefaultGem/Template/Code/Source/${Name}SystemComponent.cpp @@ -41,22 +41,20 @@ namespace ${SanitizedCppName} void ${SanitizedCppName}SystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC("${SanitizedCppName}Service")); + provided.push_back(AZ_CRC_CE("${SanitizedCppName}Service")); } void ${SanitizedCppName}SystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC("${SanitizedCppName}Service")); + incompatible.push_back(AZ_CRC_CE("${SanitizedCppName}Service")); } - void ${SanitizedCppName}SystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + void ${SanitizedCppName}SystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) { - AZ_UNUSED(required); } - void ${SanitizedCppName}SystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) + void ${SanitizedCppName}SystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent) { - AZ_UNUSED(dependent); } ${SanitizedCppName}SystemComponent::${SanitizedCppName}SystemComponent() @@ -91,9 +89,8 @@ namespace ${SanitizedCppName} ${SanitizedCppName}RequestBus::Handler::BusDisconnect(); } - void ${SanitizedCppName}SystemComponent::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/) + void ${SanitizedCppName}SystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) { - } } // namespace ${SanitizedCppName} diff --git a/Templates/DefaultGem/Template/Code/Tests/${Name}EditorTest.cpp b/Templates/DefaultGem/Template/Code/Tests/${Name}EditorTest.cpp index 9b36a3aadb..f998ba88e0 100644 --- a/Templates/DefaultGem/Template/Code/Tests/${Name}EditorTest.cpp +++ b/Templates/DefaultGem/Template/Code/Tests/${Name}EditorTest.cpp @@ -14,24 +14,4 @@ #include -class ${SanitizedCppName}EditorTest - : public ::testing::Test -{ -protected: - void SetUp() override - { - - } - - void TearDown() override - { - - } -}; - -TEST_F(${SanitizedCppName}EditorTest, SanityTest) -{ - ASSERT_TRUE(true); -} - AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); diff --git a/Templates/DefaultGem/Template/Code/Tests/${Name}Test.cpp b/Templates/DefaultGem/Template/Code/Tests/${Name}Test.cpp index bee38fa9d7..f998ba88e0 100644 --- a/Templates/DefaultGem/Template/Code/Tests/${Name}Test.cpp +++ b/Templates/DefaultGem/Template/Code/Tests/${Name}Test.cpp @@ -14,24 +14,4 @@ #include -class ${SanitizedCppName}Test - : public ::testing::Test -{ -protected: - void SetUp() override - { - - } - - void TearDown() override - { - - } -}; - -TEST_F(${SanitizedCppName}Test, SanityTest) -{ - ASSERT_TRUE(true); -} - AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); diff --git a/Templates/DefaultGem/template.json b/Templates/DefaultGem/template.json index b653718095..e24632d6a0 100644 --- a/Templates/DefaultGem/template.json +++ b/Templates/DefaultGem/template.json @@ -156,6 +156,12 @@ "isTemplated": true, "isOptional": false }, + { + "file": "Code/Source/${Name}EditorModule.cpp", + "origin": "Code/Source/${Name}EditorModule.cpp", + "isTemplated": true, + "isOptional": false + }, { "file": "Code/Source/${Name}EditorSystemComponent.cpp", "origin": "Code/Source/${Name}EditorSystemComponent.cpp", @@ -174,6 +180,12 @@ "isTemplated": true, "isOptional": false }, + { + "file": "Code/Source/${Name}ModuleInterface.h", + "origin": "Code/Source/${Name}ModuleInterface.h", + "isTemplated": true, + "isOptional": false + }, { "file": "Code/Source/${Name}SystemComponent.cpp", "origin": "Code/Source/${Name}SystemComponent.cpp", diff --git a/Templates/DefaultProject/Template/Code/Source/${Name}SystemComponent.cpp b/Templates/DefaultProject/Template/Code/Source/${Name}SystemComponent.cpp index ed0a47d6db..051ad41b2f 100644 --- a/Templates/DefaultProject/Template/Code/Source/${Name}SystemComponent.cpp +++ b/Templates/DefaultProject/Template/Code/Source/${Name}SystemComponent.cpp @@ -49,14 +49,12 @@ namespace ${SanitizedCppName} incompatible.push_back(AZ_CRC("${SanitizedCppName}Service")); } - void ${SanitizedCppName}SystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + void ${SanitizedCppName}SystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) { - AZ_UNUSED(required); } - void ${SanitizedCppName}SystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) + void ${SanitizedCppName}SystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent) { - AZ_UNUSED(dependent); } ${SanitizedCppName}SystemComponent::${SanitizedCppName}SystemComponent() diff --git a/Templates/DefaultProject/Template/Code/enabled_gems.cmake b/Templates/DefaultProject/Template/Code/enabled_gems.cmake index ec45be0743..19d1849a4c 100644 --- a/Templates/DefaultProject/Template/Code/enabled_gems.cmake +++ b/Templates/DefaultProject/Template/Code/enabled_gems.cmake @@ -12,17 +12,22 @@ set(ENABLED_GEMS ${Name} Atom_AtomBridge - Camera + AudioSystem + AWSCore CameraFramework + DebugDraw EditorPythonBindings EMotionFX - GradientSignal + GameState ImGui - LmbrCentral + LandscapeCanvas LyShine - Maestro - NvCloth - SceneProcessing + Multiplayer + PhysX + SaveData + ScriptCanvasPhysics + ScriptEvents + StartingPointInput TextureAtlas WhiteBox ) diff --git a/Templates/DefaultProject/Template/EngineFinder.cmake b/Templates/DefaultProject/Template/EngineFinder.cmake index fbbe3d8cfe..f058f6e037 100644 --- a/Templates/DefaultProject/Template/EngineFinder.cmake +++ b/Templates/DefaultProject/Template/EngineFinder.cmake @@ -1,3 +1,4 @@ +# {BEGIN_LICENSE} # # All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or # its licensors. @@ -8,6 +9,7 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# {END_LICENSE} # This file is copied during engine registration. Edits to this file will be lost next # time a registration happens. @@ -15,6 +17,8 @@ include_guard() # Read the engine name from the project_json file file(READ ${CMAKE_CURRENT_LIST_DIR}/project.json project_json) +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/project.json) + string(JSON LY_ENGINE_NAME_TO_USE ERROR_VARIABLE json_error GET ${project_json} engine) if(json_error) message(FATAL_ERROR "Unable to read key 'engine' from 'project.json', error: ${json_error}") @@ -30,6 +34,7 @@ endif() # Find a key that matches LY_ENGINE_NAME_TO_USE and use that as the engine path. if(EXISTS ${manifest_path}) file(READ ${manifest_path} manifest_json) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${manifest_path}) string(JSON engines_path_count ERROR_VARIABLE json_error LENGTH ${manifest_json} engines_path) if(json_error) diff --git a/Templates/DefaultProject/Template/Registry/assets_scan_folders.setreg b/Templates/DefaultProject/Template/Registry/assets_scan_folders.setreg index 3da517eb83..a42f65efb4 100644 --- a/Templates/DefaultProject/Template/Registry/assets_scan_folders.setreg +++ b/Templates/DefaultProject/Template/Registry/assets_scan_folders.setreg @@ -7,8 +7,7 @@ [ "Assets", "ShaderLib", - "Shaders", - "Registry" + "Shaders" ] } } diff --git a/Templates/DefaultProject/Template/game.cfg b/Templates/DefaultProject/Template/game.cfg index 49fc0346e4..1da374a93b 100644 --- a/Templates/DefaultProject/Template/game.cfg +++ b/Templates/DefaultProject/Template/game.cfg @@ -1,7 +1,3 @@ -sys_game_name = "${Name}" -sys_localization_folder = Localization -ca_useIMG_CAF = 0 - -- Enable warnings when asset loads take longer than the given millisecond threshold cl_assetLoadWarningEnable=true cl_assetLoadWarningMsThreshold=100 diff --git a/Templates/DefaultProject/template.json b/Templates/DefaultProject/template.json index 6f74fb6b26..67df3cccf7 100644 --- a/Templates/DefaultProject/template.json +++ b/Templates/DefaultProject/template.json @@ -25,12 +25,6 @@ "isTemplated": true, "isOptional": false }, - { - "file": "EngineFinder.cmake", - "origin": "EngineFinder.cmake", - "isTemplated": false, - "isOptional": false - }, { "file": "Code/${NameLower}_files.cmake", "origin": "Code/${NameLower}_files.cmake", @@ -49,12 +43,6 @@ "isTemplated": true, "isOptional": false }, - { - "file": "Code/gem.json", - "origin": "Code/gem.json", - "isTemplated": true, - "isOptional": true - }, { "file": "Code/Include/${Name}/${Name}Bus.h", "origin": "Code/Include/${Name}/${Name}Bus.h", @@ -175,12 +163,24 @@ "isTemplated": true, "isOptional": false }, + { + "file": "Code/gem.json", + "origin": "Code/gem.json", + "isTemplated": true, + "isOptional": true + }, { "file": "Config/shader_global_build_options.json", "origin": "Config/shader_global_build_options.json", "isTemplated": false, "isOptional": false }, + { + "file": "EngineFinder.cmake", + "origin": "EngineFinder.cmake", + "isTemplated": false, + "isOptional": false + }, { "file": "Platform/Android/android_project.cmake", "origin": "Platform/Android/android_project.cmake", @@ -478,7 +478,7 @@ { "file": "ShaderLib/README.md", "origin": "ShaderLib/README.md", - "isTemplated": true, + "isTemplated": false, "isOptional": true }, { @@ -514,7 +514,7 @@ { "file": "game.cfg", "origin": "game.cfg", - "isTemplated": true, + "isTemplated": false, "isOptional": false }, { @@ -650,6 +650,10 @@ { "dir": "Shaders", "origin": "Shaders" + }, + { + "dir": "Shaders/ShaderResourceGroups", + "origin": "Shaders/ShaderResourceGroups" } ] } diff --git a/Templates/MinimalProject/Template/.gitignore b/Templates/MinimalProject/Template/.gitignore new file mode 100644 index 0000000000..9a6d119b1b --- /dev/null +++ b/Templates/MinimalProject/Template/.gitignore @@ -0,0 +1,3 @@ +[Bb]uild/ +[Cc]ache/ +[Uu]ser/ \ No newline at end of file diff --git a/Templates/MinimalProject/Template/CMakeLists.txt b/Templates/MinimalProject/Template/CMakeLists.txt new file mode 100644 index 0000000000..4dcfc5325b --- /dev/null +++ b/Templates/MinimalProject/Template/CMakeLists.txt @@ -0,0 +1,35 @@ +# {BEGIN_LICENSE} +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# +# {END_LICENSE} + +if(NOT PROJECT_NAME) + cmake_minimum_required(VERSION 3.20) + project(${Name} + LANGUAGES C CXX + VERSION 1.0.0.0 + ) + include(EngineFinder.cmake OPTIONAL) + find_package(o3de REQUIRED) + o3de_initialize() +else() + # Add the project_name to global LY_PROJECTS_TARGET_NAME property + file(READ "${CMAKE_CURRENT_LIST_DIR}/project.json" project_json) + + string(JSON project_target_name ERROR_VARIABLE json_error GET ${project_json} "project_name") + if(json_error) + message(FATAL_ERROR "Unable to read key 'project_name' from 'project.json'") + endif() + + set_property(GLOBAL APPEND PROPERTY LY_PROJECTS_TARGET_NAME ${project_target_name}) + + add_subdirectory(Code) +endif() diff --git a/Templates/MinimalProject/Template/Code/${NameLower}_files.cmake b/Templates/MinimalProject/Template/Code/${NameLower}_files.cmake new file mode 100644 index 0000000000..f77348395b --- /dev/null +++ b/Templates/MinimalProject/Template/Code/${NameLower}_files.cmake @@ -0,0 +1,17 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(FILES + Include/${Name}/${Name}Bus.h + Source/${Name}SystemComponent.cpp + Source/${Name}SystemComponent.h + enabled_gems.cmake +) diff --git a/Templates/MinimalProject/Template/Code/${NameLower}_shared_files.cmake b/Templates/MinimalProject/Template/Code/${NameLower}_shared_files.cmake new file mode 100644 index 0000000000..6b9ddc02aa --- /dev/null +++ b/Templates/MinimalProject/Template/Code/${NameLower}_shared_files.cmake @@ -0,0 +1,14 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(FILES + Source/${Name}Module.cpp +) diff --git a/Templates/MinimalProject/Template/Code/CMakeLists.txt b/Templates/MinimalProject/Template/Code/CMakeLists.txt new file mode 100644 index 0000000000..43459b1606 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/CMakeLists.txt @@ -0,0 +1,116 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +# Currently we are in the ${Name}/Code folder: ${CMAKE_CURRENT_LIST_DIR} +# Get the platform specific folder ${pal_dir} for the current folder: ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} +# Note: ly_get_list_relative_pal_filename will take care of the details for us, as this may be a restricted platform +# in which case it will see if that platform is present here or in the restricted folder. +# i.e. It could here : ${Name}/Code/Platform/ or +# //${Name}/Code +ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${o3de_project_restricted_path} ${o3de_project_path} ${o3de_project_name}) + +# Now that we have the platform abstraction layer (PAL) folder for this folder, thats where we will find the +# traits for this platform. Traits for a platform are defines for things like whether or not something in this project +# is supported by this platform. +include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) + +# Now that we have loaded our project traits for this platform, see if this project is even supported on this platform. +# If its not supported we just return after including the unsupported. +if(NOT PAL_TRAIT_${NameUpper}_SUPPORTED) + return() +endif() + +# We are on a supported platform, so add the ${Name} target +# Note: We include the common files and the platform specific files which are set in ${NameLower}_files.cmake and +# in ${pal_dir}/${NameLower}_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake +ly_add_target( + NAME ${Name}.Static STATIC + NAMESPACE Gem + FILES_CMAKE + ${NameLower}_files.cmake + ${pal_dir}/${NameLower}_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + INCLUDE_DIRECTORIES + PUBLIC + Include + BUILD_DEPENDENCIES + PRIVATE + AZ::AzGameFramework + Gem::Atom_AtomBridge.Static +) + +ly_add_target( + NAME ${Name} ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} + NAMESPACE Gem + FILES_CMAKE + ${NameLower}_shared_files.cmake + ${pal_dir}/${NameLower}_shared_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + INCLUDE_DIRECTORIES + PUBLIC + Include + BUILD_DEPENDENCIES + PRIVATE + Gem::${Name}.Static + AZ::AzCore +) + +# if enabled, ${Name} is used by all kinds of applications +ly_create_alias(NAME ${Name}.Builders NAMESPACE Gem TARGETS Gem::${Name}) +ly_create_alias(NAME ${Name}.Tools NAMESPACE Gem TARGETS Gem::${Name}) +ly_create_alias(NAME ${Name}.Clients NAMESPACE Gem TARGETS Gem::${Name}) +ly_create_alias(NAME ${Name}.Servers NAMESPACE Gem TARGETS Gem::${Name}) + +################################################################################ +# Gem dependencies +################################################################################ + +# The GameLauncher uses "Clients" gem variants: +ly_enable_gems( + PROJECT_NAME ${Name} GEM_FILE enabled_gems.cmake + TARGETS + ${Name}.GameLauncher + VARIANTS + Clients) + +if(PAL_TRAIT_BUILD_HOST_TOOLS) + + # the builder type applications use the "Builders" variants of the enabled gems. + ly_enable_gems( + PROJECT_NAME ${Name} GEM_FILE enabled_gems.cmake + TARGETS + AssetBuilder + AssetProcessor + AssetProcessorBatch + VARIANTS + Builders) + + # the Editor applications use the "Tools" variants of the enabled gems. + ly_enable_gems( + PROJECT_NAME ${Name} GEM_FILE enabled_gems.cmake + TARGETS + Editor + VARIANTS + Tools) +endif() + +if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) + # this property causes it to actually make a ServerLauncher. + # if you don't want a Server application, you can remove this and the + # following ly_enable_gems lines. + set_property(GLOBAL APPEND PROPERTY LY_LAUNCHER_SERVER_PROJECTS ${Name}) + + # The ServerLauncher uses the "Servers" variants of enabled gems: + ly_enable_gems( + PROJECT_NAME ${Name} GEM_FILE enabled_gems.cmake + TARGETS + ${Name}.ServerLauncher + VARIANTS + Servers) +endif() diff --git a/Templates/MinimalProject/Template/Code/Include/${Name}/${Name}Bus.h b/Templates/MinimalProject/Template/Code/Include/${Name}/${Name}Bus.h new file mode 100644 index 0000000000..05e434ec03 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Include/${Name}/${Name}Bus.h @@ -0,0 +1,44 @@ +// {BEGIN_LICENSE} +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + // {END_LICENSE} + +#pragma once + +#include +#include + +namespace ${SanitizedCppName} +{ + class ${SanitizedCppName}Requests + { + public: + AZ_RTTI(${SanitizedCppName}Requests, "${Random_Uuid}"); + virtual ~${SanitizedCppName}Requests() = default; + // Put your public methods here + }; + + class ${SanitizedCppName}BusTraits + : public AZ::EBusTraits + { + public: + ////////////////////////////////////////////////////////////////////////// + // EBusTraits overrides + static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + ////////////////////////////////////////////////////////////////////////// + }; + + using ${SanitizedCppName}RequestBus = AZ::EBus<${SanitizedCppName}Requests, ${SanitizedCppName}BusTraits>; + using ${SanitizedCppName}Interface = AZ::Interface<${SanitizedCppName}Requests>; + +} // namespace ${SanitizedCppName} diff --git a/Templates/MinimalProject/Template/Code/Platform/Android/${NameLower}_android_files.cmake b/Templates/MinimalProject/Template/Code/Platform/Android/${NameLower}_android_files.cmake new file mode 100644 index 0000000000..78fd98ba6c --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/Android/${NameLower}_android_files.cmake @@ -0,0 +1,14 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(FILES + PAL_android.cmake +) diff --git a/Gems/Atom/Feature/Common/Code/Platform/Common/atom_feature_common_msvc.cmake b/Templates/MinimalProject/Template/Code/Platform/Android/${NameLower}_shared_android_files.cmake similarity index 90% rename from Gems/Atom/Feature/Common/Code/Platform/Common/atom_feature_common_msvc.cmake rename to Templates/MinimalProject/Template/Code/Platform/Android/${NameLower}_shared_android_files.cmake index 74ca22aaea..d7112106d2 100644 --- a/Gems/Atom/Feature/Common/Code/Platform/Common/atom_feature_common_msvc.cmake +++ b/Templates/MinimalProject/Template/Code/Platform/Android/${NameLower}_shared_android_files.cmake @@ -1,4 +1,4 @@ -# +# {BEGIN_LICENSE} # All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or # its licensors. # @@ -7,9 +7,7 @@ # or, if provided, by the license below or the license accompanying this file. Do not # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# +# {END_LICENSE} -set(LY_COMPILE_OPTIONS - PRIVATE - /EHsc +set(FILES ) diff --git a/Templates/MinimalProject/Template/Code/Platform/Android/PAL_android.cmake b/Templates/MinimalProject/Template/Code/Platform/Android/PAL_android.cmake new file mode 100644 index 0000000000..8218d1c700 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/Android/PAL_android.cmake @@ -0,0 +1,12 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(PAL_TRAIT_${NameUpper}_SUPPORTED TRUE) diff --git a/Templates/MinimalProject/Template/Code/Platform/Linux/${NameLower}_linux_files.cmake b/Templates/MinimalProject/Template/Code/Platform/Linux/${NameLower}_linux_files.cmake new file mode 100644 index 0000000000..ee0b06efc4 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/Linux/${NameLower}_linux_files.cmake @@ -0,0 +1,14 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(FILES + PAL_linux.cmake +) diff --git a/Templates/MinimalProject/Template/Code/Platform/Linux/${NameLower}_shared_linux_files.cmake b/Templates/MinimalProject/Template/Code/Platform/Linux/${NameLower}_shared_linux_files.cmake new file mode 100644 index 0000000000..d7112106d2 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/Linux/${NameLower}_shared_linux_files.cmake @@ -0,0 +1,13 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(FILES +) diff --git a/Templates/MinimalProject/Template/Code/Platform/Linux/PAL_linux.cmake b/Templates/MinimalProject/Template/Code/Platform/Linux/PAL_linux.cmake new file mode 100644 index 0000000000..8218d1c700 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/Linux/PAL_linux.cmake @@ -0,0 +1,12 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(PAL_TRAIT_${NameUpper}_SUPPORTED TRUE) diff --git a/Templates/MinimalProject/Template/Code/Platform/Mac/${NameLower}_mac_files.cmake b/Templates/MinimalProject/Template/Code/Platform/Mac/${NameLower}_mac_files.cmake new file mode 100644 index 0000000000..e14e028c88 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/Mac/${NameLower}_mac_files.cmake @@ -0,0 +1,15 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(FILES + ../../../Resources/Platform/Mac/Info.plist + PAL_mac.cmake +) diff --git a/Templates/MinimalProject/Template/Code/Platform/Mac/${NameLower}_shared_mac_files.cmake b/Templates/MinimalProject/Template/Code/Platform/Mac/${NameLower}_shared_mac_files.cmake new file mode 100644 index 0000000000..d9f2e6ec6b --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/Mac/${NameLower}_shared_mac_files.cmake @@ -0,0 +1,14 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(FILES + ../../../Resources/Platform/Mac/Info.plist +) diff --git a/Templates/MinimalProject/Template/Code/Platform/Mac/PAL_mac.cmake b/Templates/MinimalProject/Template/Code/Platform/Mac/PAL_mac.cmake new file mode 100644 index 0000000000..8218d1c700 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/Mac/PAL_mac.cmake @@ -0,0 +1,12 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(PAL_TRAIT_${NameUpper}_SUPPORTED TRUE) diff --git a/Templates/MinimalProject/Template/Code/Platform/Windows/${NameLower}_shared_windows_files.cmake b/Templates/MinimalProject/Template/Code/Platform/Windows/${NameLower}_shared_windows_files.cmake new file mode 100644 index 0000000000..d7112106d2 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/Windows/${NameLower}_shared_windows_files.cmake @@ -0,0 +1,13 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(FILES +) diff --git a/Templates/MinimalProject/Template/Code/Platform/Windows/${NameLower}_windows_files.cmake b/Templates/MinimalProject/Template/Code/Platform/Windows/${NameLower}_windows_files.cmake new file mode 100644 index 0000000000..b6eb718a05 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/Windows/${NameLower}_windows_files.cmake @@ -0,0 +1,14 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(FILES + PAL_windows.cmake +) diff --git a/Templates/MinimalProject/Template/Code/Platform/Windows/PAL_windows.cmake b/Templates/MinimalProject/Template/Code/Platform/Windows/PAL_windows.cmake new file mode 100644 index 0000000000..8218d1c700 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/Windows/PAL_windows.cmake @@ -0,0 +1,12 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(PAL_TRAIT_${NameUpper}_SUPPORTED TRUE) diff --git a/Templates/MinimalProject/Template/Code/Platform/iOS/${NameLower}_ios_files.cmake b/Templates/MinimalProject/Template/Code/Platform/iOS/${NameLower}_ios_files.cmake new file mode 100644 index 0000000000..44f15538c8 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/iOS/${NameLower}_ios_files.cmake @@ -0,0 +1,15 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(FILES + ../Resources/Platform/iOS/Info.plist + PAL_ios.cmake +) diff --git a/Templates/MinimalProject/Template/Code/Platform/iOS/${NameLower}_shared_ios_files.cmake b/Templates/MinimalProject/Template/Code/Platform/iOS/${NameLower}_shared_ios_files.cmake new file mode 100644 index 0000000000..d7112106d2 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/iOS/${NameLower}_shared_ios_files.cmake @@ -0,0 +1,13 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(FILES +) diff --git a/Templates/MinimalProject/Template/Code/Platform/iOS/PAL_ios.cmake b/Templates/MinimalProject/Template/Code/Platform/iOS/PAL_ios.cmake new file mode 100644 index 0000000000..8218d1c700 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Platform/iOS/PAL_ios.cmake @@ -0,0 +1,12 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(PAL_TRAIT_${NameUpper}_SUPPORTED TRUE) diff --git a/Templates/MinimalProject/Template/Code/Source/${Name}Module.cpp b/Templates/MinimalProject/Template/Code/Source/${Name}Module.cpp new file mode 100644 index 0000000000..57b473b317 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Source/${Name}Module.cpp @@ -0,0 +1,50 @@ +// {BEGIN_LICENSE} +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + // {END_LICENSE} + +#include +#include + +#include "${Name}SystemComponent.h" + +namespace ${SanitizedCppName} +{ + class ${SanitizedCppName}Module + : public AZ::Module + { + public: + AZ_RTTI(${SanitizedCppName}Module, "${ModuleClassId}", AZ::Module); + AZ_CLASS_ALLOCATOR(${SanitizedCppName}Module, AZ::SystemAllocator, 0); + + ${SanitizedCppName}Module() + : AZ::Module() + { + // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here. + m_descriptors.insert(m_descriptors.end(), { + ${SanitizedCppName}SystemComponent::CreateDescriptor(), + }); + } + + /** + * Add required SystemComponents to the SystemEntity. + */ + AZ::ComponentTypeList GetRequiredSystemComponents() const override + { + return AZ::ComponentTypeList{ + azrtti_typeid<${SanitizedCppName}SystemComponent>(), + }; + } + }; +}// namespace ${SanitizedCppName} + +AZ_DECLARE_MODULE_CLASS(Gem_${SanitizedCppName}, ${SanitizedCppName}::${SanitizedCppName}Module) diff --git a/Templates/MinimalProject/Template/Code/Source/${Name}SystemComponent.cpp b/Templates/MinimalProject/Template/Code/Source/${Name}SystemComponent.cpp new file mode 100644 index 0000000000..ed0a47d6db --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Source/${Name}SystemComponent.cpp @@ -0,0 +1,91 @@ +// {BEGIN_LICENSE} +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + // {END_LICENSE} + +#include +#include +#include + +#include "${Name}SystemComponent.h" + +namespace ${SanitizedCppName} +{ + void ${SanitizedCppName}SystemComponent::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serialize = azrtti_cast(context)) + { + serialize->Class<${SanitizedCppName}SystemComponent, AZ::Component>() + ->Version(0) + ; + + if (AZ::EditContext* ec = serialize->GetEditContext()) + { + ec->Class<${SanitizedCppName}SystemComponent>("${SanitizedCppName}", "[Description of functionality provided by this System Component]") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System")) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ; + } + } + } + + void ${SanitizedCppName}SystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC("${SanitizedCppName}Service")); + } + + void ${SanitizedCppName}SystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC("${SanitizedCppName}Service")); + } + + void ${SanitizedCppName}SystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + AZ_UNUSED(required); + } + + void ${SanitizedCppName}SystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) + { + AZ_UNUSED(dependent); + } + + ${SanitizedCppName}SystemComponent::${SanitizedCppName}SystemComponent() + { + if (${SanitizedCppName}Interface::Get() == nullptr) + { + ${SanitizedCppName}Interface::Register(this); + } + } + + ${SanitizedCppName}SystemComponent::~${SanitizedCppName}SystemComponent() + { + if (${SanitizedCppName}Interface::Get() == this) + { + ${SanitizedCppName}Interface::Unregister(this); + } + } + + void ${SanitizedCppName}SystemComponent::Init() + { + } + + void ${SanitizedCppName}SystemComponent::Activate() + { + ${SanitizedCppName}RequestBus::Handler::BusConnect(); + } + + void ${SanitizedCppName}SystemComponent::Deactivate() + { + ${SanitizedCppName}RequestBus::Handler::BusDisconnect(); + } +} diff --git a/Templates/MinimalProject/Template/Code/Source/${Name}SystemComponent.h b/Templates/MinimalProject/Template/Code/Source/${Name}SystemComponent.h new file mode 100644 index 0000000000..10a500aba2 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/Source/${Name}SystemComponent.h @@ -0,0 +1,53 @@ +// {BEGIN_LICENSE} +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + // {END_LICENSE} + +#pragma once + +#include + +#include <${Name}/${Name}Bus.h> + +namespace ${SanitizedCppName} +{ + class ${SanitizedCppName}SystemComponent + : public AZ::Component + , protected ${SanitizedCppName}RequestBus::Handler + { + public: + AZ_COMPONENT(${SanitizedCppName}SystemComponent, "${SysCompClassId}"); + + static void Reflect(AZ::ReflectContext* context); + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); + + ${SanitizedCppName}SystemComponent(); + ~${SanitizedCppName}SystemComponent(); + + protected: + //////////////////////////////////////////////////////////////////////// + // ${SanitizedCppName}RequestBus interface implementation + + //////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + // AZ::Component interface implementation + void Init() override; + void Activate() override; + void Deactivate() override; + //////////////////////////////////////////////////////////////////////// + }; +} diff --git a/Templates/MinimalProject/Template/Code/enabled_gems.cmake b/Templates/MinimalProject/Template/Code/enabled_gems.cmake new file mode 100644 index 0000000000..72500a8ada --- /dev/null +++ b/Templates/MinimalProject/Template/Code/enabled_gems.cmake @@ -0,0 +1,17 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + +set(ENABLED_GEMS + ${Name} + Atom_AtomBridge + CameraFramework + ImGui +) diff --git a/Templates/MinimalProject/Template/Code/gem.json b/Templates/MinimalProject/Template/Code/gem.json new file mode 100644 index 0000000000..5b8fb3fde0 --- /dev/null +++ b/Templates/MinimalProject/Template/Code/gem.json @@ -0,0 +1,14 @@ +{ + "gem_name": "${Name}", + "origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", + "license": "What license ${Name} uses goes here: i.e. https://opensource.org/licenses/MIT", + "display_name": "${Name}", + "summary": "A short description of ${Name}.", + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "${Name}" + ], + "icon_path": "preview.png" +} diff --git a/Templates/MinimalProject/Template/Config/shader_global_build_options.json b/Templates/MinimalProject/Template/Config/shader_global_build_options.json new file mode 100644 index 0000000000..08e4d7f502 --- /dev/null +++ b/Templates/MinimalProject/Template/Config/shader_global_build_options.json @@ -0,0 +1,11 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "GlobalBuildOptions", + "ClassData": { + "ShaderCompilerArguments" : { + "DefaultMatrixOrder" : "Row", + "AzslcAdditionalFreeArguments" : "--strip-unused-srgs" + } + } +} \ No newline at end of file diff --git a/Templates/MinimalProject/Template/EngineFinder.cmake b/Templates/MinimalProject/Template/EngineFinder.cmake new file mode 100644 index 0000000000..f058f6e037 --- /dev/null +++ b/Templates/MinimalProject/Template/EngineFinder.cmake @@ -0,0 +1,73 @@ +# {BEGIN_LICENSE} +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# +# {END_LICENSE} +# This file is copied during engine registration. Edits to this file will be lost next +# time a registration happens. + +include_guard() + +# Read the engine name from the project_json file +file(READ ${CMAKE_CURRENT_LIST_DIR}/project.json project_json) +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/project.json) + +string(JSON LY_ENGINE_NAME_TO_USE ERROR_VARIABLE json_error GET ${project_json} engine) +if(json_error) + message(FATAL_ERROR "Unable to read key 'engine' from 'project.json', error: ${json_error}") +endif() + +if(DEFINED ENV{USERPROFILE} AND EXISTS $ENV{USERPROFILE}) + set(manifest_path $ENV{USERPROFILE}/.o3de/o3de_manifest.json) # Windows +else() + set(manifest_path $ENV{HOME}/.o3de/o3de_manifest.json) # Unix +endif() + +# Read the ~/.o3de/o3de_manifest.json file and look through the 'engines_path' object. +# Find a key that matches LY_ENGINE_NAME_TO_USE and use that as the engine path. +if(EXISTS ${manifest_path}) + file(READ ${manifest_path} manifest_json) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${manifest_path}) + + string(JSON engines_path_count ERROR_VARIABLE json_error LENGTH ${manifest_json} engines_path) + if(json_error) + message(FATAL_ERROR "Unable to read key 'engines_path' from '${manifest_path}', error: ${json_error}") + endif() + + string(JSON engines_path_type ERROR_VARIABLE json_error TYPE ${manifest_json} engines_path) + if(json_error OR NOT ${engines_path_type} STREQUAL "OBJECT") + message(FATAL_ERROR "Type of 'engines_path' in '${manifest_path}' is not a JSON Object, error: ${json_error}") + endif() + + math(EXPR engines_path_count "${engines_path_count}-1") + foreach(engine_path_index RANGE ${engines_path_count}) + string(JSON engine_name ERROR_VARIABLE json_error MEMBER ${manifest_json} engines_path ${engine_path_index}) + if(json_error) + message(FATAL_ERROR "Unable to read 'engines_path/${engine_path_index}' from '${manifest_path}', error: ${json_error}") + endif() + + if(LY_ENGINE_NAME_TO_USE STREQUAL engine_name) + string(JSON engine_path ERROR_VARIABLE json_error GET ${manifest_json} engines_path ${engine_name}) + if(json_error) + message(FATAL_ERROR "Unable to read value from 'engines_path/${engine_name}', error: ${json_error}") + endif() + + if(engine_path) + list(APPEND CMAKE_MODULE_PATH "${engine_path}/cmake") + break() + endif() + endif() + endforeach() +else() + # If the user is passing CMAKE_MODULE_PATH we assume thats where we will find the engine + if(NOT CMAKE_MODULE_PATH) + message(FATAL_ERROR "Engine registration is required before configuring a project. Please register an engine by running 'scripts/o3de register --this-engine'") + endif() +endif() diff --git a/Templates/MinimalProject/Template/Platform/Android/android_project.cmake b/Templates/MinimalProject/Template/Platform/Android/android_project.cmake new file mode 100644 index 0000000000..e102985372 --- /dev/null +++ b/Templates/MinimalProject/Template/Platform/Android/android_project.cmake @@ -0,0 +1,11 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + diff --git a/Templates/MinimalProject/Template/Platform/Android/android_project.json b/Templates/MinimalProject/Template/Platform/Android/android_project.json new file mode 100644 index 0000000000..99500f02ba --- /dev/null +++ b/Templates/MinimalProject/Template/Platform/Android/android_project.json @@ -0,0 +1,9 @@ +{ + "Tags": ["Android"], + "android_settings" : { + "package_name" : "com.lumberyard.${Name}", + "version_number" : 1, + "version_name" : "1.0.0.0", + "orientation" : "landscape" + } +} \ No newline at end of file diff --git a/Templates/MinimalProject/Template/Platform/Linux/linux_project.cmake b/Templates/MinimalProject/Template/Platform/Linux/linux_project.cmake new file mode 100644 index 0000000000..e102985372 --- /dev/null +++ b/Templates/MinimalProject/Template/Platform/Linux/linux_project.cmake @@ -0,0 +1,11 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + diff --git a/Templates/MinimalProject/Template/Platform/Linux/linux_project.json b/Templates/MinimalProject/Template/Platform/Linux/linux_project.json new file mode 100644 index 0000000000..d08fbf53ba --- /dev/null +++ b/Templates/MinimalProject/Template/Platform/Linux/linux_project.json @@ -0,0 +1,3 @@ +{ + "Tags": ["Linux"] +} \ No newline at end of file diff --git a/Templates/MinimalProject/Template/Platform/Mac/mac_project.cmake b/Templates/MinimalProject/Template/Platform/Mac/mac_project.cmake new file mode 100644 index 0000000000..e102985372 --- /dev/null +++ b/Templates/MinimalProject/Template/Platform/Mac/mac_project.cmake @@ -0,0 +1,11 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + diff --git a/Templates/MinimalProject/Template/Platform/Mac/mac_project.json b/Templates/MinimalProject/Template/Platform/Mac/mac_project.json new file mode 100644 index 0000000000..d42b6f8186 --- /dev/null +++ b/Templates/MinimalProject/Template/Platform/Mac/mac_project.json @@ -0,0 +1,3 @@ +{ + "Tags": ["Mac"] +} \ No newline at end of file diff --git a/Templates/MinimalProject/Template/Platform/Windows/windows_project.cmake b/Templates/MinimalProject/Template/Platform/Windows/windows_project.cmake new file mode 100644 index 0000000000..e102985372 --- /dev/null +++ b/Templates/MinimalProject/Template/Platform/Windows/windows_project.cmake @@ -0,0 +1,11 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + diff --git a/Templates/MinimalProject/Template/Platform/Windows/windows_project.json b/Templates/MinimalProject/Template/Platform/Windows/windows_project.json new file mode 100644 index 0000000000..a052f1e05a --- /dev/null +++ b/Templates/MinimalProject/Template/Platform/Windows/windows_project.json @@ -0,0 +1,3 @@ +{ + "Tags": ["Windows"] +} \ No newline at end of file diff --git a/Templates/MinimalProject/Template/Platform/iOS/ios_project.cmake b/Templates/MinimalProject/Template/Platform/iOS/ios_project.cmake new file mode 100644 index 0000000000..e102985372 --- /dev/null +++ b/Templates/MinimalProject/Template/Platform/iOS/ios_project.cmake @@ -0,0 +1,11 @@ +# {BEGIN_LICENSE} +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# {END_LICENSE} + diff --git a/Templates/MinimalProject/Template/Platform/iOS/ios_project.json b/Templates/MinimalProject/Template/Platform/iOS/ios_project.json new file mode 100644 index 0000000000..b2dab56d05 --- /dev/null +++ b/Templates/MinimalProject/Template/Platform/iOS/ios_project.json @@ -0,0 +1,3 @@ +{ + "Tags": ["iOS"] +} \ No newline at end of file diff --git a/Templates/MinimalProject/Template/Registry/assets_scan_folders.setreg b/Templates/MinimalProject/Template/Registry/assets_scan_folders.setreg new file mode 100644 index 0000000000..a42f65efb4 --- /dev/null +++ b/Templates/MinimalProject/Template/Registry/assets_scan_folders.setreg @@ -0,0 +1,14 @@ +{ + "Amazon": + { + "${Name}.Assets": + { + "SourcePaths": + [ + "Assets", + "ShaderLib", + "Shaders" + ] + } + } +} \ No newline at end of file diff --git a/Templates/MinimalProject/Template/Resources/CryEngineLogoLauncher.bmp b/Templates/MinimalProject/Template/Resources/CryEngineLogoLauncher.bmp new file mode 100644 index 0000000000..fe0adc54a4 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/CryEngineLogoLauncher.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf6d56fe4c367d39bd78500dd34332fcad57ad41241768b52781dbdb60ddd972 +size 347568 diff --git a/Templates/MinimalProject/Template/Resources/GameSDK.ico b/Templates/MinimalProject/Template/Resources/GameSDK.ico new file mode 100644 index 0000000000..cb935cd926 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/GameSDK.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61efd8df621780af995fc1250918df5e00364ff00f849bef67702cd4b0a152e1 +size 65537 diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/Contents.json b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/Contents.json new file mode 100644 index 0000000000..da4a164c91 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/Contents.json b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..bfa8bcf478 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icon_16_2x.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icon_32_2x.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon_128 _2x.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icon_256 _2x.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_512_2x.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128 _2x.png b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128 _2x.png new file mode 100644 index 0000000000..5970ea34ba --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128 _2x.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e38257b6917cdf5d73e90e6009f10c8736d62b20c4e785085305075c7e6320e2 +size 32037 diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128.png b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128.png new file mode 100644 index 0000000000..9e30e09547 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9f41a37d2347a617e93bd97adaf6d4c161c471ca3ef7e04b98c65ddda52396dc +size 27833 diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16.png b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16.png new file mode 100644 index 0000000000..aeb29abd0a --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b07984494059bf827bc485cbea06d12e0283811face1a18799495f9ba7ae8af1 +size 20779 diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16_2x.png b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16_2x.png new file mode 100644 index 0000000000..445a389d61 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16_2x.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e645142d284de40aafb7a4a858f3df92b6a5ba9b03fa5f1a2d3cb25211597926 +size 21857 diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256 _2x.png b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256 _2x.png new file mode 100644 index 0000000000..0904cf7ce8 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256 _2x.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07631f41b8dea80713d2463f81a713a9a93798975b6fb50afbeeb13d26c57fa2 +size 48899 diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256.png b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256.png new file mode 100644 index 0000000000..5970ea34ba --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e38257b6917cdf5d73e90e6009f10c8736d62b20c4e785085305075c7e6320e2 +size 32037 diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32.png b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32.png new file mode 100644 index 0000000000..445a389d61 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e645142d284de40aafb7a4a858f3df92b6a5ba9b03fa5f1a2d3cb25211597926 +size 21857 diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32_2x.png b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32_2x.png new file mode 100644 index 0000000000..1fad9bda96 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32_2x.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad83faf98b49f4e37112baedeae726f4f8d71bcdd1961d9cdad31f043f8ca666 +size 24003 diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512.png b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512.png new file mode 100644 index 0000000000..e1517dddb6 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:68529a6c11d5ffa7ecd9d5bbb11ceea28e6852bd45946b525af09602c9a1e1bf +size 48899 diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512_2x.png b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512_2x.png new file mode 100644 index 0000000000..b425cb685f --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512_2x.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a70003840b418848b2ce6c18ed7cbbfcd6fcf76598a6601dca8b98d9b6c1a2f +size 114706 diff --git a/Templates/MinimalProject/Template/Resources/Platform/Mac/Info.plist b/Templates/MinimalProject/Template/Resources/Platform/Mac/Info.plist new file mode 100644 index 0000000000..6d056ba799 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/Mac/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleInfoDictionaryVersion + + CFBundleDisplayName + ${Name} + CFBundleExecutable + ${Name}.GameLauncher + CFBundleIdentifier + com.amazon.${Name} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + 03DE + CFBundleVersion + 1.0.0 + LSApplicationCategoryType + public.app-category.puzzle-games + + diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/Contents.json b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/Contents.json b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 0000000000..f836f07ee7 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,169 @@ +{ + "images" : [ + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "2436h", + "filename" : "iPhoneLaunchImage1125x2436.png", + "minimum-system-version" : "11.0", + "orientation" : "portrait", + "scale" : "3x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "2436h", + "filename" : "iPhoneLaunchImage2436x1125.png", + "minimum-system-version" : "11.0", + "orientation" : "landscape", + "scale" : "3x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "736h", + "filename" : "iPhoneLaunchImage1242x2208.png", + "minimum-system-version" : "8.0", + "orientation" : "portrait", + "scale" : "3x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "736h", + "filename" : "iPhoneLaunchImage2208x1242.png", + "minimum-system-version" : "8.0", + "orientation" : "landscape", + "scale" : "3x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "667h", + "filename" : "iPhoneLaunchImage750x1334.png", + "minimum-system-version" : "8.0", + "orientation" : "portrait", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "filename" : "iPhoneLaunchImage640x960.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "retina4", + "filename" : "iPhoneLaunchImage640x1136.png", + "minimum-system-version" : "7.0", + "orientation" : "portrait", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "filename" : "iPadLaunchImage768x1024.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "filename" : "iPadLaunchImage1024x768.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "filename" : "iPadLaunchImage1536x2048.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "filename" : "iPadLaunchImage2048x1536.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "to-status-bar", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "to-status-bar", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "to-status-bar", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "to-status-bar", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1024x768.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1024x768.png new file mode 100644 index 0000000000..1249ef3703 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1024x768.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:31afa7ed44c5d9844c8d6ce08beccac482c3f43590869a3d190d06e2df377ccc +size 137472 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1536x2048.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1536x2048.png new file mode 100644 index 0000000000..cdb6d5a82a --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1536x2048.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0aac8ef9899442820bec0df8bf6434a46cc787d57c5d6d38a04727b8dc310048 +size 338281 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage2048x1536.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage2048x1536.png new file mode 100644 index 0000000000..954d3084c8 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage2048x1536.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c07495891f15b138ba09f142777b0f43217bf8be05cbb74ba938319f3425980c +size 321125 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage768x1024.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage768x1024.png new file mode 100644 index 0000000000..021319fbc3 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage768x1024.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d6bf6acb92421a453a36fc143ab6cefda14d631ea5e6dbf95c6e252a445fcbac +size 144797 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x1136.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x1136.png new file mode 100644 index 0000000000..a15fd777fa --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x1136.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e9ad650fda925b1c076a67d1ef70315fe4f14db888c9fd36ee4eba1d18c1e7d1 +size 166749 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x960.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x960.png new file mode 100644 index 0000000000..2855f4069d --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x960.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16f6e9d7bd15fc528d934c252213de8792812e708b1810191c5f1767f7165852 +size 142331 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/Contents.json b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..09621469c3 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "iPhoneNotificationIcon40x40.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "iPhoneNotificationIcon60x60.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "iPhoneSettingsIcon58x58.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "iPhoneSettingsIcon87x87.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "iPhoneSpotlightIcon80x80.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "iPhoneSpotlightIcon120x120.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "iPhoneAppIcon120x120.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "iPhoneAppIcon180x180.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "iPadNotificationIcon20x20.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "iPadNotificationIcon40x40.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "iPadSettingsIcon29x29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "iPadSettingsIcon58x58.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "iPadSpotlightIcon40x40.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "iPadSpotlightIcon80x80.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "iPadAppIcon76x76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "iPadAppIcon152x152.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "iPadProAppIcon167x167.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "iOSAppStoreIcon1024x1024.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon152x152.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon152x152.png new file mode 100644 index 0000000000..b0dd493c11 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon152x152.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4901093fa6190bf37291b0fb6de23fba1be8ebbd742775a8565a4106722fbb6 +size 31942 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon76x76.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon76x76.png new file mode 100644 index 0000000000..21aa62e96b --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon76x76.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4ae97c4f44910121a61686862c8342ce598db4cdf9d46b29e96d3cb9e43bd06 +size 22158 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadProAppIcon167x167.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadProAppIcon167x167.png new file mode 100644 index 0000000000..6b696a84b2 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadProAppIcon167x167.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:061e2d0ce8dc852dd298c80f2aed5fee8ea4b87511c00662aa2d00922c0ba3c2 +size 30162 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon29x29.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon29x29.png new file mode 100644 index 0000000000..f3dfa05839 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon29x29.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0fb4b4b77620d99dae7473b7bd8affe14630419835bd5719167ed200e657fa4f +size 17504 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon58x58.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon58x58.png new file mode 100644 index 0000000000..5325b805fd --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon58x58.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8aa9b1194f3244025578225a6a87cbc2dd12c70955ff615c8af640ea7f1334f1 +size 19619 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon40x40.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon40x40.png new file mode 100644 index 0000000000..98d8455838 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon40x40.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0c25ffb1af8160b3202977de8c32aaa235e22c643ffd8004e4546c96868ef3b9 +size 18317 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon80x80.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon80x80.png new file mode 100644 index 0000000000..7482f6c892 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon80x80.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2db961b8f922a552d8ad374fdb56029efd4049a6cde10399b3d961242c82ce53 +size 22571 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon120x120.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon120x120.png new file mode 100644 index 0000000000..da987b86f9 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon120x120.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f39d897a57d4da0a70ede7c91339660b28e9d8c57b3e7d749807b13baa4b85f3 +size 28559 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon180x180.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon180x180.png new file mode 100644 index 0000000000..205e025c36 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon180x180.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:263b75d58328499eef1f8fa2e64c30706f546badcc0c4464a043b231da93cd0d +size 34969 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon58x58.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon58x58.png new file mode 100644 index 0000000000..0deb4f4f35 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon58x58.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33522ad8a8e826b22dd9ad214f56e63e24bf55c00bd8c845925d848b855dfb48 +size 19619 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon87x87.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon87x87.png new file mode 100644 index 0000000000..78591751d7 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon87x87.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f405c9f3d908d038aea26049e533b0d10955adfac370c7b3b80209997ea706d0 +size 24407 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon120x120.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon120x120.png new file mode 100644 index 0000000000..034dcb9fed --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon120x120.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d110f6e151799a2327bcdf5ef94d6fc82b114783a8cc973a8915896679ba4a80 +size 28559 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon80x80.png b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon80x80.png new file mode 100644 index 0000000000..f0fa89149c --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon80x80.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db8f00568fad4e49b05249aaa7a48c9fbf85c8b7a78489c83dc9b8161778bcef +size 22571 diff --git a/Templates/MinimalProject/Template/Resources/Platform/iOS/Info.plist b/Templates/MinimalProject/Template/Resources/Platform/iOS/Info.plist new file mode 100644 index 0000000000..2233733ad8 --- /dev/null +++ b/Templates/MinimalProject/Template/Resources/Platform/iOS/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${Name} + CFBundleExecutable + ${Name}.GameLauncher + CFBundleIdentifier + com.amazon.lumberyard.${Name} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${Name} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + UIRequiredDeviceCapabilities + + arm64 + metal + + UIRequiresFullScreen + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationLandscapeLeft + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationLandscapeLeft + + + diff --git a/Templates/MinimalProject/Template/ShaderLib/README.md b/Templates/MinimalProject/Template/ShaderLib/README.md new file mode 100644 index 0000000000..034550163d --- /dev/null +++ b/Templates/MinimalProject/Template/ShaderLib/README.md @@ -0,0 +1,5 @@ +# Customizing Shader Resource Groups + +Please read: +*\/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/README.md* +for details on how to customize scenesrg.srgi and viewsrg.srgi. diff --git a/Templates/MinimalProject/Template/ShaderLib/scenesrg.srgi b/Templates/MinimalProject/Template/ShaderLib/scenesrg.srgi new file mode 100644 index 0000000000..0a8cec5963 --- /dev/null +++ b/Templates/MinimalProject/Template/ShaderLib/scenesrg.srgi @@ -0,0 +1,31 @@ +// {BEGIN_LICENSE} +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// {END_LICENSE} + +#pragma once + +// Please read README.md for an explanation on why scenesrg.srgi and viewsrg.srgi are +// located in this folder (And how you can optionally customize your own scenesrg.srgi +// and viewsrg.srgi in your game project). + +#include + +partial ShaderResourceGroup SceneSrg : SRG_PerScene +{ +/* Intentionally Empty. Helps define the SrgSemantic for SceneSrg once.*/ +}; + +#define AZ_COLLECTING_PARTIAL_SRGS +#include +#include +#undef AZ_COLLECTING_PARTIAL_SRGS diff --git a/Templates/MinimalProject/Template/ShaderLib/viewsrg.srgi b/Templates/MinimalProject/Template/ShaderLib/viewsrg.srgi new file mode 100644 index 0000000000..bc566590ff --- /dev/null +++ b/Templates/MinimalProject/Template/ShaderLib/viewsrg.srgi @@ -0,0 +1,30 @@ +// {BEGIN_LICENSE} +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// {END_LICENSE} + +#pragma once + +// Please read README.md for an explanation on why scenesrg.srgi and viewsrg.srgi are +// located in this folder (And how you can optionally customize your own scenesrg.srgi +// and viewsrg.srgi in your game project). + +#include + +partial ShaderResourceGroup ViewSrg : SRG_PerView +{ +/* Intentionally Empty. Helps define the SrgSemantic for ViewSrg once.*/ +}; + +#define AZ_COLLECTING_PARTIAL_SRGS +#include +#undef AZ_COLLECTING_PARTIAL_SRGS diff --git a/Templates/MinimalProject/Template/Shaders/CommonVS.azsli b/Templates/MinimalProject/Template/Shaders/CommonVS.azsli new file mode 100644 index 0000000000..fc557b9b06 --- /dev/null +++ b/Templates/MinimalProject/Template/Shaders/CommonVS.azsli @@ -0,0 +1,56 @@ +// {BEGIN_LICENSE} +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// {END_LICENSE} + +#pragma once + +#include +#include +#include + +struct VertexInput +{ + float3 m_position : POSITION; + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float2 m_uv : UV0; +}; + +struct VertexOutput +{ + float4 m_position : SV_Position; + float3 m_normal : NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float2 m_uv : UV0; + float3 m_view : VIEW; +}; + +VertexOutput CommonVS(VertexInput input) +{ + float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); + float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose(); + + VertexOutput output; + float3 worldPosition = mul(objectToWorld, float4(input.m_position, 1)).xyz; + output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); + + output.m_uv = input.m_uv; + + output.m_view = worldPosition - ViewSrg::m_worldPosition; + + ConstructTBN(input.m_normal, input.m_tangent, input.m_bitangent, objectToWorld, objectToWorldIT, output.m_normal, output.m_tangent, output.m_bitangent); + + return output; +} diff --git a/Templates/MinimalProject/Template/Shaders/ShaderResourceGroups/SceneSrg.azsli b/Templates/MinimalProject/Template/Shaders/ShaderResourceGroups/SceneSrg.azsli new file mode 100644 index 0000000000..4c962fbbcd --- /dev/null +++ b/Templates/MinimalProject/Template/Shaders/ShaderResourceGroups/SceneSrg.azsli @@ -0,0 +1,24 @@ +// {BEGIN_LICENSE} +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// {END_LICENSE} + +#ifndef AZ_COLLECTING_PARTIAL_SRGS +#error Do not include this file directly. Include the main .srgi file instead. +#endif + +partial ShaderResourceGroup SceneSrg +{ + float m_time; + float m_deltaTime; +} + diff --git a/Gems/AtomContent/Sponza/LyProjectRootStub b/Templates/MinimalProject/Template/autoexec.cfg similarity index 100% rename from Gems/AtomContent/Sponza/LyProjectRootStub rename to Templates/MinimalProject/Template/autoexec.cfg diff --git a/Templates/MinimalProject/Template/game.cfg b/Templates/MinimalProject/Template/game.cfg new file mode 100644 index 0000000000..1da374a93b --- /dev/null +++ b/Templates/MinimalProject/Template/game.cfg @@ -0,0 +1,3 @@ +-- Enable warnings when asset loads take longer than the given millisecond threshold +cl_assetLoadWarningEnable=true +cl_assetLoadWarningMsThreshold=100 diff --git a/Templates/MinimalProject/Template/preview.png b/Templates/MinimalProject/Template/preview.png new file mode 100644 index 0000000000..a3e13481c9 --- /dev/null +++ b/Templates/MinimalProject/Template/preview.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a5881b8d6cfbc4ceefb14ab96844484fe19407ee030824768f9fcce2f729d35 +size 2949 diff --git a/Templates/MinimalProject/Template/project.json b/Templates/MinimalProject/Template/project.json new file mode 100644 index 0000000000..7f6b5d3b78 --- /dev/null +++ b/Templates/MinimalProject/Template/project.json @@ -0,0 +1,15 @@ +{ + "project_name": "${Name}", + "origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", + "license": "What license ${Name} uses goes here: i.e. https://opensource.org/licenses/MIT", + "display_name": "${Name}", + "summary": "A short description of ${Name}.", + "canonical_tags": [ + "Project" + ], + "user_tags": [ + "${Name}" + ], + "icon_path": "preview.png", + "engine": "o3de" +} diff --git a/Templates/MinimalProject/template.json b/Templates/MinimalProject/template.json new file mode 100644 index 0000000000..88214b26fa --- /dev/null +++ b/Templates/MinimalProject/template.json @@ -0,0 +1,656 @@ +{ + "template_name": "MinimalProject", + "origin": "The primary repo for MinimalProject goes here: i.e. http://www.mydomain.com", + "license": "What license MinimalProject uses goes here: i.e. https://opensource.org/licenses/MIT", + "display_name": "MinimalProject", + "summary": "A short description of MinimalProject.", + "canonical_tags": [], + "user_tags": [ + "MinimalProject" + ], + "icon_path": "preview.png", + "copyFiles": [ + { + "file": ".gitignore", + "origin": ".gitignore", + "isTemplated": false, + "isOptional": false + }, + { + "file": "CMakeLists.txt", + "origin": "CMakeLists.txt", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/${NameLower}_files.cmake", + "origin": "Code/${NameLower}_files.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/${NameLower}_shared_files.cmake", + "origin": "Code/${NameLower}_shared_files.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/CMakeLists.txt", + "origin": "Code/CMakeLists.txt", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Include/${Name}/${Name}Bus.h", + "origin": "Code/Include/${Name}/${Name}Bus.h", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/Android/${NameLower}_android_files.cmake", + "origin": "Code/Platform/Android/${NameLower}_android_files.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/Android/${NameLower}_shared_android_files.cmake", + "origin": "Code/Platform/Android/${NameLower}_shared_android_files.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/Android/PAL_android.cmake", + "origin": "Code/Platform/Android/PAL_android.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/Linux/${NameLower}_linux_files.cmake", + "origin": "Code/Platform/Linux/${NameLower}_linux_files.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake", + "origin": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/Linux/PAL_linux.cmake", + "origin": "Code/Platform/Linux/PAL_linux.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/Mac/${NameLower}_mac_files.cmake", + "origin": "Code/Platform/Mac/${NameLower}_mac_files.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake", + "origin": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/Mac/PAL_mac.cmake", + "origin": "Code/Platform/Mac/PAL_mac.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake", + "origin": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/Windows/${NameLower}_windows_files.cmake", + "origin": "Code/Platform/Windows/${NameLower}_windows_files.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/Windows/PAL_windows.cmake", + "origin": "Code/Platform/Windows/PAL_windows.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/iOS/${NameLower}_ios_files.cmake", + "origin": "Code/Platform/iOS/${NameLower}_ios_files.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/iOS/${NameLower}_shared_ios_files.cmake", + "origin": "Code/Platform/iOS/${NameLower}_shared_ios_files.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Platform/iOS/PAL_ios.cmake", + "origin": "Code/Platform/iOS/PAL_ios.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Source/${Name}Module.cpp", + "origin": "Code/Source/${Name}Module.cpp", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Source/${Name}SystemComponent.cpp", + "origin": "Code/Source/${Name}SystemComponent.cpp", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/Source/${Name}SystemComponent.h", + "origin": "Code/Source/${Name}SystemComponent.h", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/enabled_gems.cmake", + "origin": "Code/enabled_gems.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Code/gem.json", + "origin": "Code/gem.json", + "isTemplated": true, + "isOptional": true + }, + { + "file": "Config/shader_global_build_options.json", + "origin": "Config/shader_global_build_options.json", + "isTemplated": false, + "isOptional": false + }, + { + "file": "EngineFinder.cmake", + "origin": "EngineFinder.cmake", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Platform/Android/android_project.cmake", + "origin": "Platform/Android/android_project.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Platform/Android/android_project.json", + "origin": "Platform/Android/android_project.json", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Platform/Linux/linux_project.cmake", + "origin": "Platform/Linux/linux_project.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Platform/Linux/linux_project.json", + "origin": "Platform/Linux/linux_project.json", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Platform/Mac/mac_project.cmake", + "origin": "Platform/Mac/mac_project.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Platform/Mac/mac_project.json", + "origin": "Platform/Mac/mac_project.json", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Platform/Windows/windows_project.cmake", + "origin": "Platform/Windows/windows_project.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Platform/Windows/windows_project.json", + "origin": "Platform/Windows/windows_project.json", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Platform/iOS/ios_project.cmake", + "origin": "Platform/iOS/ios_project.cmake", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Platform/iOS/ios_project.json", + "origin": "Platform/iOS/ios_project.json", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Registry/assets_scan_folders.setreg", + "origin": "Registry/assets_scan_folders.setreg", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Resources/CryEngineLogoLauncher.bmp", + "origin": "Resources/CryEngineLogoLauncher.bmp", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/GameSDK.ico", + "origin": "Resources/GameSDK.ico", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/Contents.json", + "origin": "Resources/Platform/Mac/Images.xcassets/Contents.json", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/Contents.json", + "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/Contents.json", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128 _2x.png", + "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128 _2x.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128.png", + "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16.png", + "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16_2x.png", + "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16_2x.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256 _2x.png", + "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256 _2x.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256.png", + "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32.png", + "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32_2x.png", + "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32_2x.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512.png", + "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512_2x.png", + "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512_2x.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/Mac/Info.plist", + "origin": "Resources/Platform/Mac/Info.plist", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/Contents.json", + "origin": "Resources/Platform/iOS/Images.xcassets/Contents.json", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/Contents.json", + "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/Contents.json", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1024x768.png", + "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1024x768.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1536x2048.png", + "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1536x2048.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage2048x1536.png", + "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage2048x1536.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage768x1024.png", + "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage768x1024.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x1136.png", + "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x1136.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x960.png", + "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x960.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/Contents.json", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/Contents.json", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon152x152.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon152x152.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon76x76.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon76x76.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadProAppIcon167x167.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadProAppIcon167x167.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon29x29.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon29x29.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon58x58.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon58x58.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon40x40.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon40x40.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon80x80.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon80x80.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon120x120.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon120x120.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon180x180.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon180x180.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon58x58.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon58x58.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon87x87.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon87x87.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon120x120.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon120x120.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon80x80.png", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon80x80.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "Resources/Platform/iOS/Info.plist", + "origin": "Resources/Platform/iOS/Info.plist", + "isTemplated": true, + "isOptional": false + }, + { + "file": "ShaderLib/README.md", + "origin": "ShaderLib/README.md", + "isTemplated": false, + "isOptional": true + }, + { + "file": "ShaderLib/scenesrg.srgi", + "origin": "ShaderLib/scenesrg.srgi", + "isTemplated": true, + "isOptional": false + }, + { + "file": "ShaderLib/viewsrg.srgi", + "origin": "ShaderLib/viewsrg.srgi", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Shaders/CommonVS.azsli", + "origin": "Shaders/CommonVS.azsli", + "isTemplated": true, + "isOptional": false + }, + { + "file": "Shaders/ShaderResourceGroups/SceneSrg.azsli", + "origin": "Shaders/ShaderResourceGroups/SceneSrg.azsli", + "isTemplated": true, + "isOptional": false + }, + { + "file": "autoexec.cfg", + "origin": "autoexec.cfg", + "isTemplated": false, + "isOptional": false + }, + { + "file": "game.cfg", + "origin": "game.cfg", + "isTemplated": false, + "isOptional": false + }, + { + "file": "preview.png", + "origin": "preview.png", + "isTemplated": false, + "isOptional": false + }, + { + "file": "project.json", + "origin": "project.json", + "isTemplated": true, + "isOptional": false + } + ], + "createDirectories": [ + { + "dir": "Assets", + "origin": "Assets" + }, + { + "dir": "Code", + "origin": "Code" + }, + { + "dir": "Code/Include", + "origin": "Code/Include" + }, + { + "dir": "Code/Include/${Name}", + "origin": "Code/Include/${Name}" + }, + { + "dir": "Code/Platform", + "origin": "Code/Platform" + }, + { + "dir": "Code/Platform/Android", + "origin": "Code/Platform/Android" + }, + { + "dir": "Code/Platform/Linux", + "origin": "Code/Platform/Linux" + }, + { + "dir": "Code/Platform/Mac", + "origin": "Code/Platform/Mac" + }, + { + "dir": "Code/Platform/Windows", + "origin": "Code/Platform/Windows" + }, + { + "dir": "Code/Platform/iOS", + "origin": "Code/Platform/iOS" + }, + { + "dir": "Code/Source", + "origin": "Code/Source" + }, + { + "dir": "Config", + "origin": "Config" + }, + { + "dir": "Platform", + "origin": "Platform" + }, + { + "dir": "Platform/Android", + "origin": "Platform/Android" + }, + { + "dir": "Platform/Linux", + "origin": "Platform/Linux" + }, + { + "dir": "Platform/Mac", + "origin": "Platform/Mac" + }, + { + "dir": "Platform/Windows", + "origin": "Platform/Windows" + }, + { + "dir": "Platform/iOS", + "origin": "Platform/iOS" + }, + { + "dir": "Registry", + "origin": "Registry" + }, + { + "dir": "Resources", + "origin": "Resources" + }, + { + "dir": "Resources/Platform", + "origin": "Resources/Platform" + }, + { + "dir": "Resources/Platform/Mac", + "origin": "Resources/Platform/Mac" + }, + { + "dir": "Resources/Platform/Mac/Images.xcassets", + "origin": "Resources/Platform/Mac/Images.xcassets" + }, + { + "dir": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset", + "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset" + }, + { + "dir": "Resources/Platform/iOS", + "origin": "Resources/Platform/iOS" + }, + { + "dir": "Resources/Platform/iOS/Images.xcassets", + "origin": "Resources/Platform/iOS/Images.xcassets" + }, + { + "dir": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage", + "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage" + }, + { + "dir": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset", + "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset" + }, + { + "dir": "ShaderLib", + "origin": "ShaderLib" + }, + { + "dir": "Shaders", + "origin": "Shaders" + }, + { + "dir": "Shaders/ShaderResourceGroups", + "origin": "Shaders/ShaderResourceGroups" + } + ] +} diff --git a/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py b/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py index ec4b43b023..48afeb8219 100755 --- a/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py +++ b/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py @@ -14,11 +14,15 @@ Utility class to resolve Lumberyard directory paths & file mappings. import os import pathlib import warnings +import json +import logging from abc import ABCMeta, abstractmethod +from weakref import KeyedRef import ly_test_tools._internal.pytest_plugin from ly_test_tools.environment.file_system import find_ancestor_file +logger = logging.getLogger(__name__) def _find_engine_root(initial_path): # type: (str) -> str @@ -50,11 +54,41 @@ def _find_project_json(engine_root, project): Find the project.json file for this project. :return: Full path to the project.json file """ - # First check relative to defined build directory, for external projects which configure through SDK settings - project_json = find_ancestor_file(target_file_name='project.json', - start_path=ly_test_tools._internal.pytest_plugin.build_directory) - if not project_json: # check internally for a project bundled with the engine - project_json = os.path.join(engine_root, project, 'project.json') + project_json = None + + # Check the o3de_manifest.json and for the "projects" key + manifest_json = os.path.join(os.path.expanduser('~'), '.o3de', 'o3de_manifest.json') + if os.path.isfile(manifest_json): + # Read the o3de_manifest.json + with open(manifest_json, "r") as manifest_file: + json_data = json.load(manifest_file) + # Look at the "projects" key for registered project paths + try: + for projects_path in json_data["projects"]: + check_project_json = os.path.join(projects_path, 'project.json') + # Check for the project.json file inside of the project directory + if os.path.isfile(check_project_json): + # Check if the "project_name" key matches our project + with open(check_project_json, "r") as project_json_file: + project_json_data = json.load(project_json_file) + if project == project_json_data["project_name"]: + project_json = check_project_json + break + except KeyError as err: + logger.warning(f"Project key could not be found due to error: {err}") + + # Check relative to defined build directory, for external projects which configure through SDK settings + if not project_json: + project_json = find_ancestor_file(target_file_name='project.json', + start_path=ly_test_tools._internal.pytest_plugin.build_directory) + # Check internally for a project bundled with the engine + if not project_json: + check_project_json = os.path.join(engine_root, project, 'project.json') + if os.path.isfile(check_project_json): + project_json = check_project_json + + if not project_json: + raise OSError(f"Unable to find the project directory for project: ${project}") return project_json diff --git a/Tools/LyTestTools/tests/unit/test_abstract_resource_locator.py b/Tools/LyTestTools/tests/unit/test_abstract_resource_locator.py index 12286b3dd7..d8e4e5a14a 100755 --- a/Tools/LyTestTools/tests/unit/test_abstract_resource_locator.py +++ b/Tools/LyTestTools/tests/unit/test_abstract_resource_locator.py @@ -24,6 +24,9 @@ mock_engine_root = "mock_engine_root" mock_dev_path = "mock_dev_path" mock_build_directory = 'mock_build_directory' mock_project = 'mock_project' +mock_manifest_json_file = {'projects': [mock_project]} +mock_project_json_file = {'project_name': mock_project} +mock_project_json = os.path.join(mock_project, 'project.json') class TestFindEngineRoot(object): @@ -47,11 +50,24 @@ class TestFindEngineRoot(object): with pytest.raises(OSError): abstract_resource_locator._find_engine_root(mock_initial_path) +@mock.patch('builtins.open', mock.MagicMock()) +class TestFindProjectJson(object): + + @mock.patch('os.path.isfile', mock.MagicMock(return_value=True)) + @mock.patch('os.path.basename', mock.MagicMock(return_value=mock_project)) + @mock.patch('json.load', mock.MagicMock(side_effect=[mock_manifest_json_file, mock_project_json_file])) + def test_FindProjectJson_ManifestJson_ReturnsProjectJson(self): + project = abstract_resource_locator._find_project_json(mock_engine_root, mock_project) + + assert project == mock_project_json + @mock.patch('ly_test_tools._internal.managers.abstract_resource_locator.os.path.abspath', mock.MagicMock(return_value=mock_initial_path)) @mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_engine_root', mock.MagicMock(return_value=mock_engine_root)) +@mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_project_json', + mock.MagicMock(return_value=os.path.join(mock_project, 'project.json'))) class TestAbstractResourceLocator(object): def test_Init_HasEngineRoot_SetsAttrs(self): @@ -93,12 +109,11 @@ class TestAbstractResourceLocator(object): assert mock_abstract_resource_locator.build_directory() == mock_build_directory - def test_Project_IsCalled_ReturnsProjectPath(self): + def test_Project_IsCalled_ReturnsProjectDir(self): mock_abstract_resource_locator = abstract_resource_locator.AbstractResourceLocator( mock_build_directory, mock_project) - expected_path = os.path.join(mock_abstract_resource_locator.engine_root(), mock_project) - assert mock_abstract_resource_locator.project() == expected_path + assert mock_abstract_resource_locator.project() == os.path.dirname(mock_project_json) def test_AssetProcessor_IsCalled_ReturnsAssetProcessorPath(self): mock_abstract_resource_locator = abstract_resource_locator.AbstractResourceLocator( @@ -168,8 +183,7 @@ class TestAbstractResourceLocator(object): def test_AutoexecFile_IsCalled_ReturnsAutoexecFilePath(self): mock_abstract_resource_locator = abstract_resource_locator.AbstractResourceLocator( mock_build_directory, mock_project) - expected_path = os.path.join(mock_abstract_resource_locator.engine_root(), - mock_abstract_resource_locator._project, + expected_path = os.path.join(mock_abstract_resource_locator._project, 'autoexec.cfg') assert mock_abstract_resource_locator.autoexec_file() == expected_path diff --git a/Tools/LyTestTools/tests/unit/test_builtin_helpers.py b/Tools/LyTestTools/tests/unit/test_builtin_helpers.py index a4ebf5acec..23a5a10bf3 100755 --- a/Tools/LyTestTools/tests/unit/test_builtin_helpers.py +++ b/Tools/LyTestTools/tests/unit/test_builtin_helpers.py @@ -68,6 +68,8 @@ class TestBuiltinHelpers(object): assert type(under_test) == expected_workspace + @mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_project_json', + mock.MagicMock(return_value='mock_project')) @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager', mock.MagicMock(return_value=MockedWorkspaceManager)) @mock.patch('ly_test_tools.builtin.helpers.MAC', True) diff --git a/Tools/LyTestTools/tests/unit/test_manager_platforms_mac.py b/Tools/LyTestTools/tests/unit/test_manager_platforms_mac.py index bbd8fbf9ae..0acf6457d9 100755 --- a/Tools/LyTestTools/tests/unit/test_manager_platforms_mac.py +++ b/Tools/LyTestTools/tests/unit/test_manager_platforms_mac.py @@ -14,6 +14,7 @@ Unit tests for ly_test_tools._internal.managers.platforms.mac import unittest.mock as mock import os import pytest +import ly_test_tools from ly_test_tools._internal.managers.platforms.mac import ( _MacResourceLocator, MacWorkspaceManager, @@ -22,11 +23,6 @@ from ly_test_tools import MAC pytestmark = pytest.mark.SUITE_smoke -if not MAC: - pytestmark = pytest.mark.skipif( - not MAC, - reason="test_manager_platforms_mac.py only runs on Mac") - mock_engine_root = 'mock_engine_root' mock_dev_path = 'mock_dev_path' mock_build_directory = 'mock_build_directory' @@ -34,16 +30,16 @@ mock_project = 'mock_project' mock_tmp_path = 'mock_tmp_path' mock_output_path = 'mock_output_path' -mac_resource_locator = _MacResourceLocator( - build_directory=mock_build_directory, - project=mock_project) - @mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_engine_root', - mock.MagicMock(return_value=(mock_engine_root, mock_dev_path))) + mock.MagicMock(return_value=mock_engine_root)) +@mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_project_json', + mock.MagicMock(return_value=mock_project)) class TestMacResourceLocator(object): def test_PlatformConfigFile_HasPath_ReturnsPath(self): + mac_resource_locator = ly_test_tools._internal.managers.platforms.mac._MacResourceLocator(mock_build_directory, + mock_project) expected = os.path.join( mac_resource_locator.engine_root(), CONFIG_FILE) @@ -51,6 +47,8 @@ class TestMacResourceLocator(object): assert mac_resource_locator.platform_config_file() == expected def test_PlatformCache_HasPath_ReturnsPath(self): + mac_resource_locator = ly_test_tools._internal.managers.platforms.mac._MacResourceLocator(mock_build_directory, + mock_project) expected = os.path.join( mac_resource_locator.project_cache(), CACHE_DIR) @@ -58,6 +56,8 @@ class TestMacResourceLocator(object): assert mac_resource_locator.platform_cache() == expected def test_ProjectLog_HasPath_ReturnsPath(self): + mac_resource_locator = ly_test_tools._internal.managers.platforms.mac._MacResourceLocator(mock_build_directory, + mock_project) expected = os.path.join( mac_resource_locator.project(), 'user', @@ -66,6 +66,8 @@ class TestMacResourceLocator(object): assert mac_resource_locator.project_log() == expected def test_ProjectScreenshots_HasPath_ReturnsPath(self): + mac_resource_locator = ly_test_tools._internal.managers.platforms.mac._MacResourceLocator(mock_build_directory, + mock_project) expected = os.path.join( mac_resource_locator.project(), 'user', @@ -74,6 +76,8 @@ class TestMacResourceLocator(object): assert mac_resource_locator.project_screenshots() == expected def test_EditorLog_HasPath_ReturnsPath(self): + mac_resource_locator = ly_test_tools._internal.managers.platforms.mac._MacResourceLocator(mock_build_directory, + mock_project) expected = os.path.join( mac_resource_locator.project_log(), 'editor.log') @@ -82,7 +86,9 @@ class TestMacResourceLocator(object): @mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_engine_root', - mock.MagicMock(return_value=(mock_engine_root, mock_dev_path))) + mock.MagicMock(return_value=mock_engine_root)) +@mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_project_json', + mock.MagicMock(return_value=mock_project)) class TestMacWorkspaceManager(object): def test_Init_SetDummyParams_ReturnsMacWorkspaceManager(self): diff --git a/Tools/LyTestTools/tests/unit/test_manager_platforms_windows.py b/Tools/LyTestTools/tests/unit/test_manager_platforms_windows.py index aaf34367e7..93ca9e3c07 100755 --- a/Tools/LyTestTools/tests/unit/test_manager_platforms_windows.py +++ b/Tools/LyTestTools/tests/unit/test_manager_platforms_windows.py @@ -14,6 +14,7 @@ Unit tests for ly_test_tools._internal.managers.platforms.windows import unittest.mock as mock import os import pytest +import ly_test_tools from ly_test_tools._internal.managers.platforms.windows import ( _WindowsResourceLocator, WindowsWorkspaceManager, @@ -34,22 +35,16 @@ mock_project = 'mock_project' mock_tmp_path = 'mock_tmp_path' mock_output_path = 'mock_output_path' -windows_resource_locator = _WindowsResourceLocator( - build_directory=mock_build_directory, - project=mock_project) - -windows_workspace_manager = WindowsWorkspaceManager( - build_directory=mock_build_directory, - project=mock_project, - tmp_path=mock_tmp_path, - output_path=mock_output_path) - @mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_engine_root', - mock.MagicMock(return_value=(mock_engine_root, mock_dev_path))) + mock.MagicMock(return_value=mock_engine_root)) +@mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_project_json', mock.MagicMock( + return_value=mock_project)) class TestWindowsResourceLocator(object): def test_PlatformConfigFile_HasPath_ReturnsPath(self): + windows_resource_locator = ly_test_tools._internal.managers.platforms.windows._WindowsResourceLocator( + mock_build_directory, mock_project) expected = os.path.join( windows_resource_locator.engine_root(), CONFIG_FILE) @@ -57,12 +52,16 @@ class TestWindowsResourceLocator(object): assert windows_resource_locator.platform_config_file() == expected def test_PlatformCache_HasPath_ReturnsPath(self): + windows_resource_locator = ly_test_tools._internal.managers.platforms.windows._WindowsResourceLocator( + mock_build_directory, mock_project) expected = os.path.join( windows_resource_locator.project_cache(), CACHE_DIR) assert windows_resource_locator.platform_cache() == expected def test_ProjectLog_HasPath_ReturnsPath(self): + windows_resource_locator = ly_test_tools._internal.managers.platforms.windows._WindowsResourceLocator( + mock_build_directory, mock_project) expected = os.path.join( windows_resource_locator.project(), 'user', @@ -71,6 +70,8 @@ class TestWindowsResourceLocator(object): assert windows_resource_locator.project_log() == expected def test_ProjectScreenshots_HasPath_ReturnsPath(self): + windows_resource_locator = ly_test_tools._internal.managers.platforms.windows._WindowsResourceLocator( + mock_build_directory, mock_project) expected = os.path.join( windows_resource_locator.project(), 'user', @@ -79,6 +80,8 @@ class TestWindowsResourceLocator(object): assert windows_resource_locator.project_screenshots() == expected def test_EditorLog_HasPath_ReturnsPath(self): + windows_resource_locator = ly_test_tools._internal.managers.platforms.windows._WindowsResourceLocator( + mock_build_directory, mock_project) expected = os.path.join( windows_resource_locator.project_log(), 'editor.log') @@ -87,17 +90,21 @@ class TestWindowsResourceLocator(object): @mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_engine_root', - mock.MagicMock(return_value=(mock_engine_root, mock_dev_path))) + mock.MagicMock(return_value=mock_engine_root)) +@mock.patch('ly_test_tools._internal.managers.abstract_resource_locator._find_project_json', mock.MagicMock( + return_value=mock_project)) class TestWindowsWorkspaceManager(object): @mock.patch('ly_test_tools.environment.reg_cleaner.create_ly_keys') def test_SetRegistryKeys_NewWorkspaceManager_KeyCreateCalled(self, mock_create_keys): + windows_workspace_manager = ly_test_tools._internal.managers.platforms.windows.WindowsWorkspaceManager() windows_workspace_manager.set_registry_keys() mock_create_keys.assert_called_once() @mock.patch('ly_test_tools.environment.reg_cleaner.clean_ly_keys') def test_ClearSettings_NewWorkspaceManager_KeyClearCalled(self, mock_clear_keys): + windows_workspace_manager = ly_test_tools._internal.managers.platforms.windows.WindowsWorkspaceManager() windows_workspace_manager.clear_settings() mock_clear_keys.assert_called_with(exception_list=r"SOFTWARE\Amazon\Lumberyard\Identity") diff --git a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake index 9f63185ab3..a0b2185190 100644 --- a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake +++ b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake @@ -25,7 +25,7 @@ ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-android TARGETS fre ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-android TARGETS tiff PACKAGE_HASH a9b30a1980946390c2fad0ed94562476a1d7ba8c1f36934ae140a89c54a8efd0) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-android TARGETS AWSNativeSDK PACKAGE_HASH e2192157534cc8c4e22769545d88dff03ec6c1031599716ef63de3ebbb8c9a44) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-android TARGETS Lua PACKAGE_HASH 1f638e94a17a87fe9e588ea456d5893876094b4db191234380e4c4eb9e06c300) -ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-android TARGETS PhysX PACKAGE_HASH 9c494576c2d4ff04dee5a9e092fcd9d5af4b2845f15ffdfcaabb0dbc5b88a7a9) +ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-android TARGETS PhysX PACKAGE_HASH b8cb6aa46b2a21671f6cb1f6a78713a3ba88824d0447560ff5ce6c01014b9f43) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-android TARGETS mikkelsen PACKAGE_HASH 075e8e4940884971063b5a9963014e2e517246fa269c07c7dc55b8cf2cd99705) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-android TARGETS googletest PACKAGE_HASH 95671be75287a61c9533452835c3647e9c1b30f81b34b43bcb0ec1997cc23894) ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-android TARGETS GoogleBenchmark PACKAGE_HASH 20b46e572211a69d7d94ddad1c89ec37bb958711d6ad4025368ac89ea83078fb) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 3220271b42..303380a27a 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -37,14 +37,14 @@ ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-linux ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-linux TARGETS tiff PACKAGE_HASH ae92b4d3b189c42ef644abc5cac865d1fb2eb7cb5622ec17e35642b00d1a0a76) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-linux TARGETS AWSNativeSDK PACKAGE_HASH b4db38de49d35a5f7500aed7f4aee5ec511dd3b584ee06fe9097885690191a5d) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-linux TARGETS Lua PACKAGE_HASH 1adc812abe3dd0dbb2ca9756f81d8f0e0ba45779ac85bf1d8455b25c531a38b0) -ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-linux TARGETS PhysX PACKAGE_HASH e3ca36106a8dbf1524709f8bb82d520920ebd3ff3a92672d382efff406c75ee3) +ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-linux TARGETS PhysX PACKAGE_HASH a110249cbef4f266b0002c4ee9a71f59f373040cefbe6b82f1e1510c811edde6) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-linux TARGETS etc2comp PACKAGE_HASH 9283aa5db5bb7fb90a0ddb7a9f3895317c8ebe8044943124bbb3673a41407430) ly_associate_package(PACKAGE_NAME mcpp-2.7.2_az.1-rev1-linux TARGETS mcpp PACKAGE_HASH 0aa713f3f2c156cb2f17d9b800aed8acf9df5ab167c48b679853ecb040da9a67) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-linux TARGETS mikkelsen PACKAGE_HASH 5973b1e71a64633588eecdb5b5c06ca0081f7be97230f6ef64365cbda315b9c8) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-linux TARGETS googletest PACKAGE_HASH 7b7ad330f369450c316a4c4592d17fbb4c14c731c95bd8f37757203e8c2bbc1b) ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-linux TARGETS GoogleBenchmark PACKAGE_HASH 4038878f337fc7e0274f0230f71851b385b2e0327c495fc3dd3d1c18a807928d) ly_associate_package(PACKAGE_NAME unwind-1.2.1-linux TARGETS unwind PACKAGE_HASH 3453265fb056e25432f611a61546a25f60388e315515ad39007b5925dd054a77) -ly_associate_package(PACKAGE_NAME qt-5.15.2-rev3-linux TARGETS Qt PACKAGE_HASH b7d9932647f4b138b3f0b124d70debd250d2a8a6dca52b04dcbe82c6369d48ca) +ly_associate_package(PACKAGE_NAME qt-5.15.2-rev4-linux TARGETS Qt PACKAGE_HASH 1122e0ec19b01cb02a11fcf34dbf884bc9049ba5ff04fb692bfb09d4e5ee1e6b) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-linux TARGETS libsamplerate PACKAGE_HASH 41643c31bc6b7d037f895f89d8d8d6369e906b92eff42b0fe05ee6a100f06261) ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev2-linux TARGETS OpenSSL PACKAGE_HASH b779426d1e9c5ddf71160d5ae2e639c3b956e0fb5e9fcaf9ce97c4526024e3bc) ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev2-linux TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 235606f98512c076a1ba84a8402ad24ac21945998abcea264e8e204678efc0ba) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index 3908d21ecf..d8ab19e649 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -39,12 +39,12 @@ ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-mac TARGETS AWSNativeSDK PACKAGE_HASH 21920372e90355407578b45ac19580df1463a39a25a867bcd0ffd8b385c8254a) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev6-mac TARGETS Lua PACKAGE_HASH b9079fd35634774c9269028447562c6b712dbc83b9c64975c095fd423ff04c08) -ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-mac TARGETS PhysX PACKAGE_HASH 149f5e9b44bd27291b1c4772f5e89a1e0efa88eef73c7e0b188935ed4d0c4a70) +ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-mac TARGETS PhysX PACKAGE_HASH 5e092a11d5c0a50c4dd99bb681a04b566a4f6f29aa08443d9bffc8dc12c27c8e) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-mac TARGETS etc2comp PACKAGE_HASH 1966ab101c89db7ecf30984917e0a48c0d02ee0e4d65b798743842b9469c0818) ly_associate_package(PACKAGE_NAME mcpp-2.7.2_az.1-rev1-mac TARGETS mcpp PACKAGE_HASH 48a9c5197bf72843fb9ac44825501ee16bbe3e72e086a32b8c9c05bf47db12ab) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-mac TARGETS mikkelsen PACKAGE_HASH 83af99ca8bee123684ad254263add556f0cf49486c0b3e32e6d303535714e505) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-mac TARGETS googletest PACKAGE_HASH cbf020d5ef976c5db8b6e894c6c63151ade85ed98e7c502729dd20172acae5a8) ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-mac TARGETS GoogleBenchmark PACKAGE_HASH ad25de0146769c91e179953d845de2bec8ed4a691f973f47e3eb37639381f665) ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev1-mac TARGETS OpenSSL PACKAGE_HASH 28adc1c0616ac0482b2a9d7b4a3a3635a1020e87b163f8aba687c501cf35f96c) -ly_associate_package(PACKAGE_NAME qt-5.15.2-rev3-mac TARGETS Qt PACKAGE_HASH 4723ac43b19d4633c3fa4b9642f27c992d30cdc689f769f82869786f1c22a728) +ly_associate_package(PACKAGE_NAME qt-5.15.2-rev4-mac TARGETS Qt PACKAGE_HASH 08790d03a0e6ad808ad64cf25c3d75abd69a343f3d224fc39927e5c6e8738b98) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-mac TARGETS libsamplerate PACKAGE_HASH b912af40c0ac197af9c43d85004395ba92a6a859a24b7eacd920fed5854a97fe) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 19e71f726c..c0b243ee2c 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -14,7 +14,7 @@ ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) -ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev9-multiplatform TARGETS assimplib PACKAGE_HASH 448530277b51b145ca43b96becd0266e29ae210fc9e2b45f5afe85f301a040e7) +ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev10-multiplatform TARGETS assimplib PACKAGE_HASH d0fb822a6a359f1bebbb720a8502a289540af08baa887c8bc978f0fbbee07385) ly_associate_package(PACKAGE_NAME squish-ccr-20150601-rev3-multiplatform TARGETS squish-ccr PACKAGE_HASH c878c6c0c705e78403c397d03f5aa7bc87e5978298710e14d09c9daf951a83b3) ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) @@ -41,7 +41,7 @@ ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-windows ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-windows TARGETS tiff PACKAGE_HASH ab60d1398e4e1e375ec0f1a00cdb1d812a07c0096d827db575ce52dd6d714207) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-windows TARGETS AWSNativeSDK PACKAGE_HASH 929873d4252c464620a9d288e41bd5d47c0bd22750aeb3a1caa68a3da8247c48) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-windows TARGETS Lua PACKAGE_HASH 136faccf1f73891e3fa3b95f908523187792e56f5b92c63c6a6d7e72d1158d40) -ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-windows TARGETS PhysX PACKAGE_HASH 198bed89d1aae7caaf5dadba24cee56235fe41725d004b64040d4e50d0f3aa1a) +ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-windows TARGETS PhysX PACKAGE_HASH 0c5ffbd9fa588e5cf7643721a7cfe74d0fe448bf82252d39b3a96d06dfca2298) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-windows TARGETS etc2comp PACKAGE_HASH fc9ae937b2ec0d42d5e7d0e9e8c80e5e4d257673fb33bc9b7d6db76002117123) ly_associate_package(PACKAGE_NAME mcpp-2.7.2_az.1-rev1-windows TARGETS mcpp PACKAGE_HASH 511672598fa319bfb8db87f965b59abff1620bb7c1dcf7669e039a8acd8d3ff8) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-windows TARGETS mikkelsen PACKAGE_HASH 872c4d245a1c86139aa929f2b465b63ea4ea55b04ced50309135dd4597457a4e) @@ -50,7 +50,7 @@ ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-windows ly_associate_package(PACKAGE_NAME d3dx12-headers-rev1-windows TARGETS d3dx12 PACKAGE_HASH 088c637159fba4a3e4c0cf08fb4921906fd4cca498939bd239db7c54b5b2f804) ly_associate_package(PACKAGE_NAME pyside2-qt-5.15.1-rev2-windows TARGETS pyside2 PACKAGE_HASH c90f3efcc7c10e79b22a33467855ad861f9dbd2e909df27a5cba9db9fa3edd0f) ly_associate_package(PACKAGE_NAME openimageio-2.1.16.0-rev2-windows TARGETS OpenImageIO PACKAGE_HASH 85a2a6cf35cbc4c967c56ca8074babf0955c5b490c90c6e6fd23c78db99fc282) -ly_associate_package(PACKAGE_NAME qt-5.15.2-rev2-windows TARGETS Qt PACKAGE_HASH 29966f22ec253dc9904e88ad48fe6b6a669302b2dc7049f2e2bbd4949e79e595) +ly_associate_package(PACKAGE_NAME qt-5.15.2-rev4-windows TARGETS Qt PACKAGE_HASH a4634caaf48192cad5c5f408504746e53d338856148285057274f6a0ccdc071d) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-windows TARGETS libsamplerate PACKAGE_HASH dcf3c11a96f212a52e2c9241abde5c364ee90b0f32fe6eeb6dcdca01d491829f) ly_associate_package(PACKAGE_NAME OpenMesh-8.1-rev1-windows TARGETS OpenMesh PACKAGE_HASH 1c1df639358526c368e790dfce40c45cbdfcfb1c9a041b9d7054a8949d88ee77) ly_associate_package(PACKAGE_NAME civetweb-1.8-rev1-windows TARGETS civetweb PACKAGE_HASH 36d0e58a59bcdb4dd70493fb1b177aa0354c945b06c30416348fd326cf323dd4) diff --git a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake index e742f0c463..649780b28e 100644 --- a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake +++ b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake @@ -26,7 +26,7 @@ ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetyp ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-ios TARGETS AWSNativeSDK PACKAGE_HASH 1246219a213ccfff76b526011febf521586d44dbc1753e474f8fb5fd861654a4) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-ios TARGETS Lua PACKAGE_HASH c2d3c4e67046c293049292317a7d60fdb8f23effeea7136aefaef667163e5ffe) -ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev2-ios TARGETS PhysX PACKAGE_HASH 27e68bd90915dbd0bd5f26cae714e9a137f6b1aa8a8e0bf354a4a9176aa553d5) +ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-ios TARGETS PhysX PACKAGE_HASH b1bbc1fc068d2c6e1eb18eecd4e8b776adc516833e8da3dcb1970cef2a8f0cbd) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-ios TARGETS mikkelsen PACKAGE_HASH 976aaa3ccd8582346132a10af253822ccc5d5bcc9ea5ba44d27848f65ee88a8a) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-ios TARGETS googletest PACKAGE_HASH 2f121ad9784c0ab73dfaa58e1fee05440a82a07cc556bec162eeb407688111a7) ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-ios TARGETS GoogleBenchmark PACKAGE_HASH c2ffaed2b658892b1bcf81dee4b44cd1cb09fc78d55584ef5cb8ab87f2d8d1ae) diff --git a/cmake/CommandExecution.cmake b/cmake/CommandExecution.cmake index b37664c048..3ed084bb42 100644 --- a/cmake/CommandExecution.cmake +++ b/cmake/CommandExecution.cmake @@ -87,4 +87,4 @@ endif() if(LY_TIMESTAMP_REFERENCE) # Touch the timestamp file file(TOUCH ${LY_TIMESTAMP_FILE}) -endif() \ No newline at end of file +endif() diff --git a/cmake/EngineJson.cmake b/cmake/EngineJson.cmake index c3ab29d09e..7922cd1a1b 100644 --- a/cmake/EngineJson.cmake +++ b/cmake/EngineJson.cmake @@ -22,7 +22,7 @@ set(LY_EXTERNAL_SUBDIRS "" CACHE STRING "List of subdirectories to recurse into # Restricted folders(contains an additional restricted.json), etc... # \arg:output_external_subdirs name of output variable to store external subdirectories into function(read_engine_external_subdirs output_external_subdirs) - file(READ ${LY_ROOT_FOLDER}/engine.json engine_json_data) + ly_file_read(${LY_ROOT_FOLDER}/engine.json engine_json_data) string(JSON external_subdirs_count ERROR_VARIABLE engine_json_error LENGTH ${engine_json_data} "external_subdirectories") if(engine_json_error) diff --git a/cmake/FileUtil.cmake b/cmake/FileUtil.cmake index 96923537ed..e530fe133c 100644 --- a/cmake/FileUtil.cmake +++ b/cmake/FileUtil.cmake @@ -118,4 +118,13 @@ override_pak_root=${LY_OVERRIDE_PAK_FOLDER_ROOT} endfunction() - +#! ly_file_read: wrap to file(READ) that adds the file to configuration tracking +# +# file(READ) does not add file tracking. So changes to the file being read will not cause a cmake regeneration +# +function(ly_file_read path content) + unset(file_content) + file(READ ${path} file_content) + set(${content} ${file_content} PARENT_SCOPE) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${path}) +endfunction() diff --git a/cmake/Findo3de.cmake b/cmake/Findo3de.cmake index 0b4d0b75e7..f9eedf686c 100644 --- a/cmake/Findo3de.cmake +++ b/cmake/Findo3de.cmake @@ -22,6 +22,8 @@ o3de_current_file_path(current_path) # Make sure we are matching LY_ENGINE_NAME_TO_USE with the current engine file(READ ${current_path}/../engine.json engine_json) +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${current_path}/../engine.json) + string(JSON this_engine_name ERROR_VARIABLE json_error GET ${engine_json} engine_name) if(json_error) message(FATAL_ERROR "Unable to read key 'engine_name' from '${current_path}/../engine.json', error: ${json_error}") diff --git a/cmake/Gems.cmake b/cmake/Gems.cmake index 169210d991..b9c47fd54d 100644 --- a/cmake/Gems.cmake +++ b/cmake/Gems.cmake @@ -84,7 +84,7 @@ function(ly_create_alias) # now add the final alias: add_library(${ly_create_alias_NAMESPACE}::${ly_create_alias_NAME} ALIAS ${ly_create_alias_NAME}) - # Store off the arguments needed used ly_create_alias into a DIRECTORY property + # Store off the arguments used by ly_create_alias into a DIRECTORY property # This will be used to re-create the calls in the generated CMakeLists.txt in the INSTALL step # Replace the CMake list separator with a space to replicate the space separated TARGETS arguments @@ -136,8 +136,8 @@ function(ly_enable_gems) if(NOT was_able_to_load_the_file) message(FATAL_ERROR "could not load the GEM_FILE ${ly_enable_gems_GEM_FILE}") endif() - if(NOT ENABLED_GEMS) - message(FATAL_ERROR "GEM_FILE ${ly_enable_gems_GEM_FILE} did not set the value of ENABLED_GEMS.\n" + if(NOT DEFINED ENABLED_GEMS) + message(WARNING "GEM_FILE ${ly_enable_gems_GEM_FILE} did not set the value of ENABLED_GEMS.\n" "Gem Files should contain set(ENABLED_GEMS ... )") endif() set(ly_enable_gems_GEMS ${ENABLED_GEMS}) @@ -148,9 +148,19 @@ function(ly_enable_gems) foreach(target_name ${ly_enable_gems_TARGETS}) foreach(variant_name ${ly_enable_gems_VARIANTS}) set_property(GLOBAL APPEND PROPERTY LY_DELAYED_ENABLE_GEMS "${ly_enable_gems_PROJECT_NAME},${target_name},${variant_name}") + define_property(GLOBAL PROPERTY LY_DELAYED_ENABLE_GEMS_"${ly_enable_gems_PROJECT_NAME},${target_name},${variant_name}" + BRIEF_DOCS "List of gem names to evaluate variants against" FULL_DOCS "Names of gems that will be paired with the variant name + to determine if it is valid target that should be added as an application dynamic load dependency") set_property(GLOBAL APPEND PROPERTY LY_DELAYED_ENABLE_GEMS_"${ly_enable_gems_PROJECT_NAME},${target_name},${variant_name}" ${ly_enable_gems_GEMS}) endforeach() endforeach() + + # Store off the arguments used by ly_enable_gems into a DIRECTORY property + # This will be used to re-create the ly_enable_gems call in the generated CMakeLists.txt at the INSTALL step + + # Replace the CMake list separator with a space to replicate the space separated TARGETS arguments + string(REPLACE ";" " " enable_gems_args "${ly_enable_gems_PROJECT_NAME},${ly_enable_gems_GEMS},${ly_enable_gems_GEM_FILE},${ly_enable_gems_VARIANTS},${ly_enable_gems_TARGETS}") + set_property(DIRECTORY APPEND PROPERTY LY_ENABLE_GEMS_ARGUMENTS "${enable_gems_args}") endfunction() # call this before runtime dependencies are used to add any relevant targets @@ -176,6 +186,20 @@ function(ly_enable_gems_delayed) get_property(gem_dependencies GLOBAL PROPERTY LY_DELAYED_ENABLE_GEMS_"${project_target_variant}") if (NOT gem_dependencies) + get_property(gem_dependencies_defined GLOBAL PROPERTY LY_DELAYED_ENABLE_GEMS_"${project_target_variant}" DEFINED) + if (gem_dependencies_defined) + # special case, if the LY_DELAYED_ENABLE_GEMS_"${project_target_variant}" property is DEFINED + # but empty, add an entry to the LY_DELAYED_LOAD_DEPENDENCIES to have the + # cmake_dependencies.*.setreg file for the (project, target) tuple to be regenerated + # This is needed if the ENABLED_GEMS list for a project goes from >0 to 0. In this case + # the cmake_dependencies would have a stale list of gems to load unless it is regenerated + get_property(delayed_load_target_set GLOBAL PROPERTY LY_DELAYED_LOAD_"${project},${target}" SET) + if(NOT delayed_load_target_set) + set_property(GLOBAL APPEND PROPERTY LY_DELAYED_LOAD_DEPENDENCIES "${project},${target}") + set_property(GLOBAL APPEND PROPERTY LY_DELAYED_LOAD_"${project},${target}" "") + endif() + endif() + # Continue to the next iteration loop regardless as there are no gem dependencies continue() endif() diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index d7f88f12ec..81c36a9c56 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -289,8 +289,6 @@ function(ly_add_target) foreach(prop IN ITEMS AUTOMOC AUTORCC) if(${ly_add_target_${prop}}) set_property(TARGET ${ly_add_target_NAME} PROPERTY ${prop} ON) - # Flag this target as depending on Qt - set_property(GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${ly_add_target_NAME} ON) endif() endforeach() if(${ly_add_target_AUTOUIC}) @@ -332,14 +330,6 @@ function(ly_add_target) VERBATIM ) - detect_qt_dependency(${ly_add_target_NAME} QT_DEPENDENCY) - if(QT_DEPENDENCY) - if(NOT COMMAND ly_qt_deploy) - message(FATAL_ERROR "Could not find function \"ly_qt_deploy\", this function should be defined in cmake/3rdParty/Platform/${PAL_PLATFORM_NAME}/Qt_${PAL_PLATFORM_NAME_LOWERCASE}.cmake") - endif() - - ly_qt_deploy(TARGET ${ly_add_target_NAME}) - endif() endif() if(ly_add_target_AUTOGEN_RULES) @@ -430,60 +420,6 @@ function(ly_delayed_target_link_libraries) endfunction() -#! detect_qt_dependency: Determine if a target will link directly to a Qt library -# -# qt deployment introspects a shared library or executable for its direct -# dependencies on Qt libraries. In CMake, this will be true if a target, or any -# of its link libraries which are static libraries, recursively, links to Qt. -function(detect_qt_dependency TARGET_NAME OUTPUT_VARIABLE) - - if(TARGET ${TARGET_NAME}) - get_target_property(alias ${TARGET_NAME} ALIASED_TARGET) - if(alias) - set(TARGET_NAME ${alias}) - endif() - endif() - - get_property(cached_is_qt_dependency GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${TARGET_NAME}) - if(cached_is_qt_dependency) - set(${OUTPUT_VARIABLE} ${cached_is_qt_dependency} PARENT_SCOPE) - return() - endif() - - if(${TARGET_NAME} MATCHES "^3rdParty::Qt::.*") - set_property(GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${TARGET_NAME} ON) - set(${OUTPUT_VARIABLE} ON PARENT_SCOPE) - return() - endif() - - get_property(delayed_link GLOBAL PROPERTY LY_DELAYED_LINK_${TARGET_NAME}) - set(exclude_library_types SHARED_LIBRARY MODULE_LIBRARY) - foreach(library IN LISTS delayed_link) - - if(TARGET ${library}) - get_target_property(child_target_type ${library} TYPE) - - # If the dependency to Qt has to go through a shared/module library, - # it is not a direct dependency - if (child_target_type IN_LIST exclude_library_types) - continue() - endif() - endif() - - detect_qt_dependency(${library} child_depends_on_qt) - if(child_depends_on_qt) - set_property(GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${TARGET_NAME} ON) - set(${OUTPUT_VARIABLE} ON PARENT_SCOPE) - return() - endif() - - endforeach() - - set_property(GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${TARGET_NAME} OFF) - set(${OUTPUT_VARIABLE} OFF PARENT_SCOPE) - -endfunction() - #! ly_parse_third_party_dependencies: Validates any 3rdParty library dependencies through the find_package command # # \arg:ly_THIRD_PARTY_LIBRARIES name of the target libraries to validate existance of through the find_package command. diff --git a/cmake/O3DEJson.cmake b/cmake/O3DEJson.cmake index ab5f95bc8c..500bd9a78c 100644 --- a/cmake/O3DEJson.cmake +++ b/cmake/O3DEJson.cmake @@ -30,7 +30,7 @@ endfunction() #! read_json_array # Reads the a json array field into a cmake list variable function(o3de_read_json_array read_output_array input_json_path array_key) - file(READ ${input_json_path} manifest_json_data) + ly_file_read(${input_json_path} manifest_json_data) string(JSON array_count ERROR_VARIABLE manifest_json_error LENGTH ${manifest_json_data} ${array_key}) if(manifest_json_error) @@ -53,7 +53,7 @@ function(o3de_read_json_array read_output_array input_json_path array_key) endfunction() function(o3de_read_json_key output_value input_json_path key) - file(READ ${input_json_path} manifest_json_data) + ly_file_read(${input_json_path} manifest_json_data) string(JSON value ERROR_VARIABLE manifest_json_error GET ${manifest_json_data} ${key}) if(manifest_json_error) message(FATAL_ERROR "Error reading field at key ${key} in file \"${input_json_path}\" : ${manifest_json_error}") diff --git a/cmake/PAL.cmake b/cmake/PAL.cmake index dca54e4731..4fe729f85a 100644 --- a/cmake/PAL.cmake +++ b/cmake/PAL.cmake @@ -30,7 +30,7 @@ endforeach() # \arg:restricted returns the restricted association element from an o3de json, otherwise engine 'o3de' is assumed # \arg:o3de_json_file name of the o3de json file function(o3de_restricted_id o3de_json_file restricted) - file(READ ${o3de_json_file} json_data) + ly_file_read(${o3de_json_file} json_data) string(JSON restricted_entry ERROR_VARIABLE json_error GET ${json_data} "restricted_name") if(json_error) message(WARNING "Unable to read restricted from '${o3de_json_file}', error: ${json_error}") @@ -46,7 +46,7 @@ endfunction() # \arg:restricted_name name of the restricted function(o3de_find_restricted_folder restricted_name restricted_path) # Read the restricted path from engine.json if one EXISTS - file(READ ${LY_ROOT_FOLDER}/engine.json engine_json_data) + ly_file_read(${LY_ROOT_FOLDER}/engine.json engine_json_data) string(JSON restricted_subdirs_count ERROR_VARIABLE engine_json_error LENGTH ${engine_json_data} "restricted") if(restricted_subdirs_count GREATER 0) string(JSON restricted_subdir ERROR_VARIABLE engine_json_error GET ${engine_json_data} "restricted" "0") @@ -66,7 +66,7 @@ function(o3de_find_restricted_folder restricted_name restricted_path) # Examine the o3de manifest file for the list of restricted directories set(o3de_manifest_path ${home_directory}/.o3de/o3de_manifest.json) if(EXISTS ${o3de_manifest_path}) - file(READ ${o3de_manifest_path} o3de_manifest_json_data) + ly_file_read(${o3de_manifest_path} o3de_manifest_json_data) string(JSON restricted_subdirs_count ERROR_VARIABLE engine_json_error LENGTH ${o3de_manifest_json_data} "restricted") if(restricted_subdirs_count GREATER 0) math(EXPR restricted_subdirs_range "${restricted_subdirs_count}-1") @@ -79,7 +79,7 @@ function(o3de_find_restricted_folder restricted_name restricted_path) # Iterate over the restricted directories from the manifest file foreach(restricted_entry ${restricted_subdirs}) set(restricted_json_file ${restricted_entry}/restricted.json) - file(READ ${restricted_json_file} restricted_json) + ly_file_read(${restricted_json_file} restricted_json) string(JSON this_restricted_name ERROR_VARIABLE json_error GET ${restricted_json} "restricted_name") if(json_error) message(WARNING "Unable to read restricted_name from '${restricted_json_file}', error: ${json_error}") diff --git a/cmake/Packaging.cmake b/cmake/Packaging.cmake index 6c077ac617..2f001cf7ee 100644 --- a/cmake/Packaging.cmake +++ b/cmake/Packaging.cmake @@ -26,7 +26,9 @@ set(CPACK_DESIRED_CMAKE_VERSION 3.20.2) # when the platform specific settings are applied below. additionally, any variable with # the "CPACK_" prefix will automatically be cached for use in any phase of cpack namely # pre/post build -set(CPACK_PACKAGE_VENDOR "${PROJECT_NAME}") +set(CPACK_PACKAGE_NAME "${PROJECT_NAME}") +set(CPACK_PACKAGE_FULL_NAME "Open3D Engine") +set(CPACK_PACKAGE_VENDOR "TBD") set(CPACK_PACKAGE_VERSION "${LY_VERSION_STRING}") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Installation Tool") @@ -39,7 +41,7 @@ set(DEFAULT_LICENSE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt") set(CPACK_RESOURCE_FILE_LICENSE ${DEFAULT_LICENSE_FILE}) set(CPACK_LICENSE_URL ${LY_INSTALLER_LICENSE_URL}) -set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_VENDOR}/${CPACK_PACKAGE_VERSION}") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}/${CPACK_PACKAGE_VERSION}") # neither of the SOURCE_DIR variables equate to anything during execution of pre/post build scripts set(CPACK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cmake) diff --git a/cmake/Platform/Android/RuntimeDependencies_android.cmake b/cmake/Platform/Android/RuntimeDependencies_android.cmake index 8b50ec465d..add036a8b8 100644 --- a/cmake/Platform/Android/RuntimeDependencies_android.cmake +++ b/cmake/Platform/Android/RuntimeDependencies_android.cmake @@ -9,4 +9,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +set(LY_RUNTIME_DEPENDENCIES_TEMPLATE ${LY_ROOT_FOLDER}/cmake/Platform/Common/runtime_dependencies_common.cmake.in) include(cmake/Platform/Common/RuntimeDependencies_common.cmake) \ No newline at end of file diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 933d64149b..edce52288f 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -13,8 +13,8 @@ set(CMAKE_INSTALL_MESSAGE NEVER) # Simplify messages to reduce output noise ly_set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Core) -file(RELATIVE_PATH runtime_output_directory ${CMAKE_BINARY_DIR} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -file(RELATIVE_PATH library_output_directory ${CMAKE_BINARY_DIR} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) +cmake_path(RELATIVE_PATH CMAKE_RUNTIME_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE runtime_output_directory) +cmake_path(RELATIVE_PATH CMAKE_LIBRARY_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE library_output_directory) # Anywhere CMAKE_INSTALL_PREFIX is used, it has to be escaped so it is baked into the cmake_install.cmake script instead # of baking the path. This is needed so `cmake --install --prefix ` works regardless of the CMAKE_INSTALL_PREFIX # used to generate the solution. @@ -22,11 +22,34 @@ file(RELATIVE_PATH library_output_directory ${CMAKE_BINARY_DIR} ${CMAKE_LIBRARY_ set(install_output_folder "\${CMAKE_INSTALL_PREFIX}/${runtime_output_directory}/${PAL_PLATFORM_NAME}/$") +function(ly_get_engine_relative_source_dir absolute_target_source_dir output_source_dir) + # Get a relative target source directory to the LY root folder if possible + # Otherwise use the final component name + cmake_path(IS_PREFIX LY_ROOT_FOLDER ${absolute_target_source_dir} is_target_prefix_of_engine_root) + if(is_target_prefix_of_engine_root) + cmake_path(RELATIVE_PATH absolute_target_source_dir BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE relative_target_source_dir) + else() + # In this case the target source directory is outside of the engine root of the target source directory and concatenate the first + # is used first 8 characters of the absolute path SHA256 hash to make a unique relative directory + # that can be used to install the generated CMakeLists.txt + # of a SHA256 hash + string(SHA256 target_source_hash ${absolute_target_source_dir}) + string(SUBSTRING ${target_source_hash} 0 8 target_source_hash) + cmake_path(GET absolute_target_source_dir FILENAME target_source_dirname) + cmake_path(SET relative_target_source_dir "${target_source_dirname}-${target_source_hash}") + endif() + + set(${output_source_dir} ${relative_target_source_dir} PARENT_SCOPE) +endfunction() + #! ly_setup_target: Setup the data needed to re-create the cmake target commands for a single target -function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME) +function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_target_source_dir) # De-alias target name ly_de_alias_target(${ALIAS_TARGET_NAME} TARGET_NAME) + # Get the target source directory relative to the LY root folder + ly_get_engine_relative_source_dir(${absolute_target_source_dir} relative_target_source_dir) + # get the component ID. if the property isn't set for the target, it will auto fallback to use CMAKE_INSTALL_DEFAULT_COMPONENT_NAME get_property(install_component TARGET ${TARGET_NAME} PROPERTY INSTALL_COMPONENT) @@ -42,8 +65,22 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME) string(GENEX_STRIP ${include_directory} include_genex_expr) if(include_genex_expr STREQUAL include_directory) # only for cases where there are no generation expressions unset(current_public_headers) + + cmake_path(NORMAL_PATH include_directory) + string(REGEX REPLACE "/$" "" include_directory "${include_directory}") + cmake_path(IS_PREFIX LY_ROOT_FOLDER ${absolute_target_source_dir} NORMALIZE include_directory_child_of_o3de_root) + if(NOT include_directory_child_of_o3de_root) + # Include directory is outside of the O3DE root folder ${LY_ROOT_FOLDER}. + # For the INSTALL step, the O3DE root folder must be a prefix of all include directories. + continue() + endif() + + cmake_path(RELATIVE_PATH include_directory BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE rel_include_dir) + cmake_path(APPEND include_location "${rel_include_dir}" ".." OUTPUT_VARIABLE destination_dir) + cmake_path(NORMAL_PATH destination_dir) + install(DIRECTORY ${include_directory} - DESTINATION ${include_location}/${target_source_dir} + DESTINATION ${destination_dir} COMPONENT ${install_component} FILES_MATCHING PATTERN *.h @@ -55,16 +92,16 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME) endif() # Get the output folders, archive is always the same, but runtime/library can be in subfolders defined per target - file(RELATIVE_PATH archive_output_directory ${CMAKE_BINARY_DIR} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) + cmake_path(RELATIVE_PATH CMAKE_ARCHIVE_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE archive_output_directory) get_target_property(target_runtime_output_directory ${TARGET_NAME} RUNTIME_OUTPUT_DIRECTORY) if(target_runtime_output_directory) - file(RELATIVE_PATH target_runtime_output_subdirectory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${target_runtime_output_directory}) + cmake_path(RELATIVE_PATH target_runtime_output_directory BASE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_runtime_output_subdirectory) endif() get_target_property(target_library_output_directory ${TARGET_NAME} LIBRARY_OUTPUT_DIRECTORY) if(target_library_output_directory) - file(RELATIVE_PATH target_library_output_subdirectory ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${target_library_output_directory}) + cmake_path(RELATIVE_PATH target_library_output_directory BASE_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_library_output_subdirectory) endif() install( @@ -115,8 +152,10 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME) foreach(include ${include_directories}) string(GENEX_STRIP ${include} include_genex_expr) if(include_genex_expr STREQUAL include) # only for cases where there are no generation expressions - file(RELATIVE_PATH relative_include ${absolute_target_source_dir} ${include}) - string(APPEND INCLUDE_DIRECTORIES_PLACEHOLDER "\${LY_ROOT_FOLDER}/include/${target_source_dir}/${relative_include}\n") + cmake_path(RELATIVE_PATH include BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE target_include) + cmake_path(NORMAL_PATH target_include) + # Escape the LY_ROOT_FOLDER variable so that it isn't resolved during the install step + string(APPEND INCLUDE_DIRECTORIES_PLACEHOLDER "\${LY_ROOT_FOLDER}/${target_include}\n") endif() endforeach() endif() @@ -193,48 +232,39 @@ set_property(TARGET ${TARGET_NAME} endif() endif() - if(IS_ABSOLUTE ${target_source_dir}) - # This normally applies the target_source_dir is outside of the engine root - # such as when invoking ly_setup_subdirectory from the project - # Therefore the final directory component of the target source directory is used first 8 characters - # of a SHA256 hash - string(SHA256 target_source_hash ${target_source_dir}) - string(SUBSTRING ${target_source_hash} 0 8 target_source_hash) - get_filename_component(target_source_folder_name ${target_source_dir} NAME) - set(target_source_dir "${target_source_folder_name}-${target_source_hash}") - endif() - - set(target_install_source_dir ${CMAKE_CURRENT_BINARY_DIR}/install/${target_source_dir}) + set(target_install_source_dir ${CMAKE_CURRENT_BINARY_DIR}/install/${relative_target_source_dir}) file(GENERATE OUTPUT "${target_install_source_dir}/${NAME_PLACEHOLDER}_$.cmake" CONTENT "${target_file_contents}") install(FILES "${target_install_source_dir}/${NAME_PLACEHOLDER}_$.cmake" - DESTINATION ${target_source_dir} + DESTINATION ${relative_target_source_dir} COMPONENT ${install_component} ) # Since a CMakeLists.txt could contain multiple targets, we generate it in a folder per target - file(READ ${LY_ROOT_FOLDER}/cmake/install/InstalledTarget.in target_cmakelists_template) + ly_file_read(${LY_ROOT_FOLDER}/cmake/install/InstalledTarget.in target_cmakelists_template) string(CONFIGURE ${target_cmakelists_template} output_cmakelists_data @ONLY) set(${OUTPUT_CONFIGURED_TARGET} ${output_cmakelists_data} PARENT_SCOPE) endfunction() + #! ly_setup_subdirectories: setups all targets on a per directory basis function(ly_setup_subdirectories) get_property(all_subdirectories GLOBAL PROPERTY LY_ALL_TARGET_DIRECTORIES) - foreach(target IN LISTS all_subdirectories) - ly_setup_subdirectory(${target}) + foreach(target_subdirectory IN LISTS all_subdirectories) + ly_setup_subdirectory(${target_subdirectory}) endforeach() endfunction() -#! ly_setup_subdirectory: setup all targets in the subdirectory +#! ly_setup_subdirectory: setup all targets in the subdirectory function(ly_setup_subdirectory absolute_target_source_dir) + # Get the target source directory relative to the LY roo folder + ly_get_engine_relative_source_dir(${absolute_target_source_dir} relative_target_source_dir) # The builtin BUILDSYSTEM_TARGETS property isn't being used here as that returns the de-alised # TARGET and we need the alias namespace for recreating the CMakeLists.txt in the install layout get_property(ALIAS_TARGETS_NAME DIRECTORY ${absolute_target_source_dir} PROPERTY LY_DIRECTORY_TARGETS) - file(RELATIVE_PATH target_source_dir ${LY_ROOT_FOLDER} ${absolute_target_source_dir}) foreach(ALIAS_TARGET_NAME IN LISTS ALIAS_TARGETS_NAME) - ly_setup_target(configured_target ${ALIAS_TARGET_NAME}) + ly_setup_target(configured_target ${ALIAS_TARGET_NAME} ${absolute_target_source_dir}) string(APPEND all_configured_targets "${configured_target}") endforeach() @@ -257,34 +287,54 @@ function(ly_setup_subdirectory absolute_target_source_dir) string(APPEND CREATE_ALIASES_PLACEHOLDER ${create_alias_command}) endforeach() - file(READ ${LY_ROOT_FOLDER}/cmake/install/Copyright.in cmake_copyright_comment) - if(IS_ABSOLUTE ${target_source_dir}) - # This normally applies the target_source_dir is outside of the engine root - # such as when invoking ly_setup_subdirectory from the project - # Therefore the final directory component of the target source directory is used first 8 characters - # of a SHA256 hash - string(SHA256 target_source_hash ${target_source_dir}) - string(SUBSTRING ${target_source_hash} 0 8 target_source_hash) - get_filename_component(target_source_folder_name ${target_source_dir} NAME) - set(target_source_dir "${target_source_folder_name}-${target_source_hash}") - endif() + # Reproduce the ly_enable_gems() calls made in the the SOURCE_DIR for this target into the CMakeLists.txt that + # is about to be generated + string(JOIN "\n" enable_gems_template + " ly_enable_gems(@enable_gem_PROJECT_NAME@ @enable_gem_GEM@ @enable_gem_GEM_FILE@ @enable_gem_VARIANTS@ @enable_gem_TARGETS@)" + "endif()" + "" + ) + get_property(enable_gems_commands_arg_list DIRECTORY ${absolute_target_source_dir} PROPERTY LY_ENABLE_GEMS_ARGUMENTS) + foreach(enable_gems_single_command_arg_list ${enable_gems_commands_arg_list}) + # Split the ly_enable_gems arguments back out based on commas + string(REPLACE "," ";" ly_enable_gems_single_command_arg_list "${enable_gems_single_command_arg_list}") + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_PROJECT_NAME) + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_GEM) + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_GEM_FILE) + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_GEM) + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_VARIANTS) + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_TARGETS) + foreach(enable_gem_arg_kw IN ITEMS PROJECT_NAME GEM GEM_FILE GEM VARIANTS TARGETS) + list(POP_FRONT enable_gems_single_command_arg_list enable_gem_${enable_gem_arg_kw}) + if(enable_gem_${enable_gem_arg_kw}) + # if the argument exist append to argument keyword to the front + string(PREPEND enable_gem_${enable_gem_arg_kw} "${enable_gem_arg_kw} ") + endif() + endforeach() + + string(CONFIGURE "${enable_gems_template}" enable_gems_command @ONLY) + string(APPEND ENABLE_GEMS_PLACEHOLDER ${enable_gems_command}) + endforeach() + + ly_file_read(${LY_ROOT_FOLDER}/cmake/install/Copyright.in cmake_copyright_comment) # Initialize the target install source directory to path underneath the current binary directory - set(target_install_source_dir ${CMAKE_CURRENT_BINARY_DIR}/install/${target_source_dir}) + set(target_install_source_dir ${CMAKE_CURRENT_BINARY_DIR}/install/${relative_target_source_dir}) # Write out all the aggregated ly_add_target function calls and the final ly_create_alias() calls to the target CMakeLists.txt file(WRITE ${target_install_source_dir}/CMakeLists.txt "${cmake_copyright_comment}" "${all_configured_targets}" "\n" "${CREATE_ALIASES_PLACEHOLDER}" + "${ENABLE_GEMS_PLACEHOLDER}" ) # get the component ID. if the property isn't set for the directory, it will auto fallback to use CMAKE_INSTALL_DEFAULT_COMPONENT_NAME get_property(install_component DIRECTORY ${absolute_target_source_dir} PROPERTY INSTALL_COMPONENT) install(FILES "${target_install_source_dir}/CMakeLists.txt" - DESTINATION ${target_source_dir} + DESTINATION ${relative_target_source_dir} COMPONENT ${install_component} ) @@ -314,7 +364,7 @@ function(ly_setup_cmake_install) # Transform the LY_EXTERNAL_SUBDIRS list into a json array set(indent " ") foreach(external_subdir ${LY_EXTERNAL_SUBDIRS}) - file(RELATIVE_PATH engine_rel_external_subdir ${LY_ROOT_FOLDER} ${external_subdir}) + cmake_path(RELATIVE_PATH external_subdir BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE engine_rel_external_subdir) list(APPEND relative_external_subdirs "\"${engine_rel_external_subdir}\"") endforeach() list(JOIN relative_external_subdirs ",\n${indent}" LY_INSTALL_EXTERNAL_SUBDIRS) @@ -354,8 +404,8 @@ function(ly_setup_cmake_install) # Add to the FIND_PACKAGES_PLACEHOLDER all directories in which ly_add_target were called in get_property(all_subdirectories GLOBAL PROPERTY LY_ALL_TARGET_DIRECTORIES) foreach(target_subdirectory IN LISTS all_subdirectories) - file(RELATIVE_PATH target_source_dir_relative ${LY_ROOT_FOLDER} ${target_subdirectory}) - string(APPEND FIND_PACKAGES_PLACEHOLDER " add_subdirectory(${target_source_dir_relative})\n") + cmake_path(RELATIVE_PATH target_subdirectory BASE_DIRECTORY ${LY_ROOT_FOLDER} OUTPUT_VARIABLE relative_target_subdirectory) + string(APPEND FIND_PACKAGES_PLACEHOLDER " add_subdirectory(${relative_target_subdirectory})\n") endforeach() configure_file(${LY_ROOT_FOLDER}/cmake/install/Findo3de.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/cmake/Findo3de.cmake @ONLY) @@ -389,16 +439,7 @@ function(ly_setup_runtime_dependencies) # Common functions used by the bellow code install(CODE -"function(ly_deploy_qt_install target_output) - execute_process(COMMAND \"${WINDEPLOYQT_EXECUTABLE}\" --verbose 0 --no-compiler-runtime \"\${target_output}\" ERROR_VARIABLE deploy_error RESULT_VARIABLE deploy_result) - if (NOT \${deploy_result} EQUAL 0) - if(NOT deploy_error MATCHES \"does not seem to be a Qt executable\" ) - message(SEND_ERROR \"Deploying qt for \${target_output} returned \${deploy_result}: \${deploy_error}\") - endif() - endif() -endfunction() - -function(ly_copy source_file target_directory) +"function(ly_copy source_file target_directory) file(COPY \"\${source_file}\" DESTINATION \"\${target_directory}\" FILE_PERMISSIONS ${LY_COPY_PERMISSIONS}) endfunction()" ) @@ -416,19 +457,7 @@ endfunction()" get_target_property(target_runtime_output_directory ${target} RUNTIME_OUTPUT_DIRECTORY) if(target_runtime_output_directory) - file(RELATIVE_PATH target_runtime_output_subdirectory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${target_runtime_output_directory}) - endif() - - # Qt - get_property(has_qt_dependency GLOBAL PROPERTY LY_DETECT_QT_DEPENDENCY_${target}) - if(has_qt_dependency) - # Qt deploy needs to be done after the binary is copied to the output, so we do a install(CODE) which effectively - # puts it as a postbuild step of the "install" target. Binaries are copied at that point. - if(NOT EXISTS ${WINDEPLOYQT_EXECUTABLE}) - message(FATAL_ERROR "Qt deploy executable not found: ${WINDEPLOYQT_EXECUTABLE}") - endif() - set(target_output "${install_output_folder}/${target_runtime_output_subdirectory}/$") - list(APPEND runtime_commands "ly_deploy_qt_install(\"${target_output}\")\n") + cmake_path(RELATIVE_PATH target_runtime_output_directory BASE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_runtime_output_subdirectory) endif() # runtime dependencies that need to be copied to the output diff --git a/cmake/Platform/Common/RuntimeDependencies_common.cmake b/cmake/Platform/Common/RuntimeDependencies_common.cmake index 4ae914744f..d00dd71f1e 100644 --- a/cmake/Platform/Common/RuntimeDependencies_common.cmake +++ b/cmake/Platform/Common/RuntimeDependencies_common.cmake @@ -35,6 +35,8 @@ function(ly_get_runtime_dependencies ly_RUNTIME_DEPENDENCIES ly_TARGET) return() # Nothing to do endif() + ly_de_alias_target(${ly_TARGET} ly_TARGET) + # To optimize the search, we are going to cache the dependencies for the targets we already walked through. # To do so, we will create a variable named LY_RUNTIME_DEPENDENCIES_${ly_TARGET} which will contain a list # of all the dependencies @@ -96,15 +98,7 @@ function(ly_get_runtime_dependencies ly_RUNTIME_DEPENDENCIES ly_TARGET) # Add the imported locations get_target_property(is_imported ${ly_TARGET} IMPORTED) if(is_imported) - # Skip Qt if this is a 3rdParty - # Qt is deployed using qt_deploy, no need to copy the dependencies set(skip_imported FALSE) - string(REGEX MATCH "3rdParty::([^:,]*)" target_package ${ly_TARGET}) - if(target_package) - if(${CMAKE_MATCH_1} STREQUAL "Qt") - set(skip_imported TRUE) - endif() - endif() if(target_type MATCHES "(STATIC_LIBRARY)") # No need to copy these dependencies since the outputs are not used at runtime set(skip_imported TRUE) @@ -118,10 +112,35 @@ function(ly_get_runtime_dependencies ly_RUNTIME_DEPENDENCIES ly_TARGET) else() set(imported_property IMPORTED_LOCATION) endif() - get_target_property(target_locations ${ly_TARGET} ${imported_property}) + unset(target_locations) + get_target_property(target_locations ${ly_TARGET} ${imported_property}) if(target_locations) list(APPEND all_runtime_dependencies ${target_locations}) + else() + # Check if the property exists for configurations + unset(target_locations) + foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) + string(TOUPPER ${conf} UCONF) + unset(current_target_locations) + get_target_property(current_target_locations ${ly_TARGET} ${imported_property}_${UCONF}) + if(current_target_locations) + string(APPEND target_locations $<$:${current_target_locations}>) + else() + # try to use the mapping + get_target_property(mapped_conf ${ly_TARGET} MAP_IMPORTED_CONFIG_${UCONF}) + if(mapped_conf) + unset(current_target_locations) + get_target_property(current_target_locations ${ly_TARGET} ${imported_property}_${mapped_conf}) + if(current_target_locations) + string(APPEND target_locations $<$:${current_target_locations}>) + endif() + endif() + endif() + endforeach() + if(target_locations) + list(APPEND all_runtime_dependencies ${target_locations}) + endif() endif() endif() @@ -228,34 +247,23 @@ function(ly_delayed_generate_runtime_dependencies) endif() unset(runtime_dependencies) - set(runtime_commands " -function(ly_copy source_file target_directory) - get_filename_component(target_filename \"\${source_file}\" NAME) - if(NOT \"\${source_file}\" STREQUAL \"\${target_directory}/\${target_filename}\") - if(NOT EXISTS \"\${target_directory}\") - file(MAKE_DIRECTORY \"\${target_directory}\") - endif() - if(\"\${source_file}\" IS_NEWER_THAN \"\${target_directory}/\${target_filename}\") - file(LOCK \"\${target_directory}/\${target_filename}.lock\" GUARD FUNCTION TIMEOUT 30) - file(COPY \"\${source_file}\" DESTINATION \"\${target_directory}\" FILE_PERMISSIONS ${LY_COPY_PERMISSIONS}) - endif() - endif() -endfunction() - \n") + unset(LY_COPY_COMMANDS) ly_get_runtime_dependencies(runtime_dependencies ${target}) foreach(runtime_dependency ${runtime_dependencies}) unset(runtime_command) ly_get_runtime_dependency_command(runtime_command ${runtime_dependency}) - string(APPEND runtime_commands ${runtime_command}) + string(APPEND LY_COPY_COMMANDS ${runtime_command}) endforeach() - + # Generate the output file set(target_file_dir "$") - string(CONFIGURE "${runtime_commands}" generated_commands @ONLY) + file(READ ${LY_RUNTIME_DEPENDENCIES_TEMPLATE} template_file) + string(CONFIGURE "${LY_COPY_COMMANDS}" LY_COPY_COMMANDS @ONLY) + string(CONFIGURE "${template_file}" configured_template_file @ONLY) file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/runtime_dependencies/$/${target}.cmake - CONTENT "${generated_commands}" + CONTENT "${configured_template_file}" ) endforeach() diff --git a/cmake/Platform/Common/runtime_dependencies_common.cmake.in b/cmake/Platform/Common/runtime_dependencies_common.cmake.in new file mode 100644 index 0000000000..c245d185d7 --- /dev/null +++ b/cmake/Platform/Common/runtime_dependencies_common.cmake.in @@ -0,0 +1,28 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +cmake_policy(SET CMP0012 NEW) # new policy for the if that evaluates a boolean out of "if(NOT ${same_location})" + +function(ly_copy source_file target_directory) + get_filename_component(target_filename "${source_file}" NAME) + cmake_path(COMPARE "${source_file}" EQUAL "${target_directory}/${target_filename}" same_location) + if(NOT ${same_location}) + if(NOT EXISTS "${target_directory}") + file(MAKE_DIRECTORY "${target_directory}") + endif() + if("${source_file}" IS_NEWER_THAN "${target_directory}/${target_filename}") + file(COPY "${source_file}" DESTINATION "${target_directory}" FILE_PERMISSIONS @LY_COPY_PERMISSIONS@ FOLLOW_SYMLINK_CHAIN) + endif() + endif() +endfunction() + +file(LOCK "${CMAKE_BINARY_DIR}/runtimedependencies.lock" TIMEOUT 300) +@LY_COPY_COMMANDS@ diff --git a/cmake/Platform/Linux/RuntimeDependencies_linux.cmake b/cmake/Platform/Linux/RuntimeDependencies_linux.cmake index 8b50ec465d..add036a8b8 100644 --- a/cmake/Platform/Linux/RuntimeDependencies_linux.cmake +++ b/cmake/Platform/Linux/RuntimeDependencies_linux.cmake @@ -9,4 +9,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +set(LY_RUNTIME_DEPENDENCIES_TEMPLATE ${LY_ROOT_FOLDER}/cmake/Platform/Common/runtime_dependencies_common.cmake.in) include(cmake/Platform/Common/RuntimeDependencies_common.cmake) \ No newline at end of file diff --git a/cmake/Platform/Linux/platform_linux_files.cmake b/cmake/Platform/Linux/platform_linux_files.cmake index 8b6bdf1361..0a9a244ef0 100644 --- a/cmake/Platform/Linux/platform_linux_files.cmake +++ b/cmake/Platform/Linux/platform_linux_files.cmake @@ -19,6 +19,5 @@ set(FILES LYWrappers_linux.cmake PAL_linux.cmake PALDetection_linux.cmake - windeployqt_wrapper.cmake RPathChange.cmake ) diff --git a/cmake/Platform/Linux/windeployqt_wrapper.cmake b/cmake/Platform/Linux/windeployqt_wrapper.cmake deleted file mode 100644 index 320b49aa7a..0000000000 --- a/cmake/Platform/Linux/windeployqt_wrapper.cmake +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/cmake -P - -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -# We use windeployqt on Linux to copy the necessary Qt libraries and files to -# the build directory. After these files are copied, we need to adjust their -# rpath to point to Qt from the build tree. - -# This script is invoked through the CommandExecution.cmake script. The invoked -# commandline is something like: -# cmake -P CommandExecution.cmake EXEC_COMMAND cmake -E env ... cmake -P windeployqt_wrapper.cmake args -# ^ 1 ^ 2 ^ 3 -# cmake #1 invokes cmake #2 which invokes cmake #3. But cmake #1 also sees 2 -P -# arguments, so cmake #1 also invokes windeployqt_wrapper.cmake after -# CommandExecution.cmake finishes. We don't want to run this script 2x, so -# detect this case and exit early - -# Find the first -P argument -foreach(argi RANGE 1 ${CMAKE_ARGC}) - if("${CMAKE_ARGV${argi}}" STREQUAL "-P") - math(EXPR script_argi "${argi} + 1") - set(script_file "${CMAKE_ARGV${script_argi}}") - break() - endif() -endforeach() - -if(NOT script_file STREQUAL "${CMAKE_CURRENT_LIST_FILE}") - return() -endif() - -set(runtime_directory ${CMAKE_ARGV3}) - -foreach(argi RANGE 4 ${CMAKE_ARGC}) - list(APPEND command_arguments "${CMAKE_ARGV${argi}}") -endforeach() -execute_process(COMMAND ${command_arguments} RESULT_VARIABLE command_result OUTPUT_VARIABLE command_output ERROR_VARIABLE command_err) - -if(command_result) - message(FATAL_ERROR "windeployqt returned a non-zero exit status. stdout: ${command_output} stderr: ${command_err}") -endif() - -# Process the output to find the list of files that were updated - -# Transform the output to a list -string(REGEX REPLACE ";" "\\\\;" command_output "${command_output}") -string(REGEX REPLACE "\n" ";" command_output "${command_output}") - -foreach(line IN LISTS command_output) - # windeployqt has output that looks like this if it updated a file: - # > Checking /path/to/src/file.so, /path/to/dst/file.so - # > Updating file.so - # If the file was not modified, it will look like this: - # > Checking /path/to/src/file.so, /path/to/dst/file.so - # > file.so is up to date - if(line MATCHES "^Checking .*") - set(curfile "${line}") - continue() - endif() - - if(line MATCHES "^Updating .*") - # curline has 3 parts, 1) "Checking ", 2) source_file, 3) updated_target_file. We - # just need part 3. But we also want to handle the unfortunate - # possibility of spaces in the filename. - - string(REGEX REPLACE "^Checking " "" curfile "${curfile}") - string(REPLACE ", " ";" curfile "${curfile}") - list(LENGTH curfile curfile_parts_count) - if(NOT curfile_parts_count EQUAL 2) - message(SEND_ERROR "Unable to parse output of windeployqt output line ${curfile}") - continue() - endif() - list(GET curfile 1 updated_file) - - file(RELATIVE_PATH relative_file "${runtime_directory}" "${updated_file}") - - get_filename_component(basename "${relative_file}" NAME) - if(basename MATCHES "^libQt5Core\\.so.*") - # We don't need to patch QtCore - continue() - endif() - - # READ_ELF has a CAPTURE_ERROR argument, but that is only set on - # platforms that don't support cmake's elf parser. On linux, no error - # will be set, even when the input is not an ELF formatted file. We - # want to skip any non-executable files, so check for the ELF tag at - # the head of the file. - file(READ "${updated_file}" elf_tag LIMIT 4 HEX) - if(NOT elf_tag STREQUAL 7f454c46) # Binary \0x7f followed by ELF - continue() - endif() - - # READ_ELF is an undocumented command that allows us to introspect the - # current rpath set in the file - file(READ_ELF "${updated_file}" RUNPATH plugin_runpath) - - get_filename_component(dirname "${relative_file}" DIRECTORY) - if(dirname) - file(RELATIVE_PATH parent_dirs "${updated_file}" "${runtime_directory}") - string(REGEX REPLACE "/../$" "" parent_dirs "${parent_dirs}") - set(new_runpath "\$ORIGIN/${parent_dirs}") - else() - set(new_runpath "\$ORIGIN") - endif() - - # RPATH_CHANGE is an undocumented command that allows for replacing an - # existing rpath entry with a new value, as long as the new value's - # strlen is <= the current rpath - file(RPATH_CHANGE FILE "${updated_file}" OLD_RPATH "${plugin_runpath}" NEW_RPATH "${new_runpath}") - - unset(curfile) - endif() -endforeach() diff --git a/cmake/Platform/Mac/RuntimeDependencies_mac.cmake b/cmake/Platform/Mac/RuntimeDependencies_mac.cmake index 8b50ec465d..383a3d5985 100644 --- a/cmake/Platform/Mac/RuntimeDependencies_mac.cmake +++ b/cmake/Platform/Mac/RuntimeDependencies_mac.cmake @@ -9,4 +9,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +set(LY_BUILD_FIXUP_BUNDLE TRUE CACHE BOOL "Fix bundles on build (deploys frameworks and calls fixup_bundle)") + +set(LY_RUNTIME_DEPENDENCIES_TEMPLATE ${LY_ROOT_FOLDER}/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in) include(cmake/Platform/Common/RuntimeDependencies_common.cmake) \ No newline at end of file diff --git a/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in b/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in new file mode 100644 index 0000000000..6ad428c08d --- /dev/null +++ b/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in @@ -0,0 +1,146 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +function(gp_resolve_item_override context item exepath dirs resolved_item_var resolved_var) + # Qt frameworks could resolve the binary to eg qt/lib/QtCore.framework/Headers/QtCore instead of qt/lib/QtCore.framework/Versions/5/QtCore + # This is because GetPrerequisites.cmake gp_resolve_item function searches for the first file that matches the "frameworks name" + if(${${resolved_var}} AND ${item} MATCHES "/(Qt[^\\.]+\\.framework)/(.*)") + set(qt_framework ${CMAKE_MATCH_1}) + set(qt_framework_subpath ${CMAKE_MATCH_2}) + string(REGEX REPLACE "(.*)/(Qt[^\\.]+\\.framework)/(.*)" "\\1/\\2/${qt_framework_subpath}" new_resolved_item "${${resolved_item_var}}") + set(${resolved_item_var} ${new_resolved_item} PARENT_SCOPE) + endif() +endfunction() + +include(BundleUtilities) + +cmake_policy(SET CMP0012 NEW) # new policy for the if that evaluates a boolean out of the LY_BUILD_FIXUP_BUNDLE expansion + +set(anything_new FALSE) +set(plugin_libs) +set(plugin_dirs) + +function(ly_copy source_file target_directory) + + get_filename_component(target_filename "${source_file}" NAME) + + # If source_file is a Framework and target_directory is a bundle + if("${source_file}" MATCHES "\\.[Ff]ramework[^\\.]" AND "${target_directory}" MATCHES "\\.app/Contents/MacOS") + + if(NOT @LY_BUILD_FIXUP_BUNDLE@) + return() + endif() + + # fixup origin to copy the whole Framework folder and change destination to Contents/Frameworks + string(REGEX REPLACE "(.*\\.[Ff]ramework).*" "\\1" source_file "${source_file}") + get_filename_component(source_file_folder "${source_file}" DIRECTORY) + + set(local_plugin_dirs ${plugin_dirs}) + list(APPEND local_plugin_dirs "${source_file_folder}") + set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE) + return() + + elseif("${source_file}" MATCHES "qt/plugins" AND "${target_directory}" MATCHES "\\.app/Contents/MacOS") + + if(NOT @LY_BUILD_FIXUP_BUNDLE@) + return() + endif() + + # fixup the destination so it ends up in Contents/Plugins + string(REGEX REPLACE "(.*\\.app/Contents)/MacOS" "\\1/plugins" target_directory "${target_directory}") + + set(local_plugin_dirs ${plugin_dirs}) + list(APPEND local_plugin_dirs "${target_directory}") + set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE) + set(local_plugin_libs ${plugin_libs}) + list(APPEND local_plugin_libs "${target_directory}/${target_filename}") + set(plugin_libs ${local_plugin_libs} PARENT_SCOPE) + + elseif("${source_file}" MATCHES "qt/translations" AND "${target_directory}" MATCHES "\\.app/Contents/MacOS") + + return() # skip, is this used? + + elseif("${source_file}" MATCHES ".dylib") + + set(local_plugin_dirs ${plugin_dirs}) + list(APPEND local_plugin_dirs "${target_directory}") + set(plugin_dirs ${local_plugin_dirs} PARENT_SCOPE) + + endif() + + cmake_path(COMPARE "${source_file}" EQUAL "${target_directory}/${target_filename}" same_location) + if(NOT ${same_location}) + if(NOT EXISTS "${target_directory}") + file(MAKE_DIRECTORY "${target_directory}") + endif() + if(NOT EXISTS "${target_directory}/${target_filename}" OR "${source_file}" IS_NEWER_THAN "${target_directory}/${target_filename}") + message(STATUS "Copying \"${source_file}\" to \"${target_directory}\"...") + file(COPY "${source_file}" DESTINATION "${target_directory}" FILE_PERMISSIONS @LY_COPY_PERMISSIONS@ FOLLOW_SYMLINK_CHAIN) + file(TOUCH ${target_directory}/${target_filename}) + set(anything_new TRUE PARENT_SCOPE) + endif() + endif() +endfunction() + +@LY_COPY_COMMANDS@ + +if(NOT @LY_BUILD_FIXUP_BUNDLE@) + return() +endif() + +if(@target_file_dir@ MATCHES ".app/Contents/MacOS") + string(REGEX REPLACE "(.*\\.app)/Contents/MacOS.*" "\\1" bundle_path "@target_file_dir@") + set(fixup_timestamp_file "${bundle_path}.fixup.stamp") + if(NOT anything_new) + if(NOT EXISTS "${fixup_timestamp_file}" OR "${bundle_path}" IS_NEWER_THAN "${fixup_timestamp_file}") + set(anything_new TRUE) + endif() + endif() + if(anything_new) + # LYN-4505: Patch dxc, is configured in the wrong folder in 3p + if(EXISTS ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7) + # we copy to not invalidate the copy check from above + file(COPY ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/lib/libdxcompiler.3.7.dylib + DESTINATION ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin + ) + endif() + # Python.framework being copied by fixup_bundle + #if(EXISTS ${bundle_path}/Contents/Frameworks/Python.framework) + # # LYN-4502: Patch python bundle, it contains some windows executables, some files that fixup_bundle doesnt like and has + # # duplicated binaries between Versions/3.7 and Versions/Current. + # file(GLOB exe_files + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/distutils/command/*.exe + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pip/_vendor/distlib/*.exe + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/setuptools/*.exe + # ) + # foreach(exe_file ${exe_files}) + # file(REMOVE ${exe_file}) + # endforeach() + # file(REMOVE_RECURSE + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/test + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/scipy/io/tests + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/Resources + # ${bundle_path}/Contents/Frameworks/Python.framework/Python + # ${bundle_path}/Contents/Frameworks/Python.framework/Resources/Python.app + # ${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7/Python + # ) + # file(REMOVE_RECURSE ${bundle_path}/Contents/Frameworks/Python.framework/Versions/Current) + # execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink 3.7 Current + # WORKING_DIRECTORY ${bundle_path}/Contents/Frameworks/Python.framework/Versions/ + # ) + #endif() + list(REMOVE_DUPLICATES plugin_libs) + list(REMOVE_DUPLICATES plugin_dirs) + fixup_bundle("${bundle_path}" "${plugin_libs}" "${plugin_dirs}") + file(TOUCH "${bundle_path}") + file(TOUCH "${fixup_timestamp_file}") + endif() +endif() diff --git a/cmake/Platform/Windows/Packaging/Bootstrapper.wxs b/cmake/Platform/Windows/Packaging/Bootstrapper.wxs index fd8aa68b77..c7146b1b7f 100644 --- a/cmake/Platform/Windows/Packaging/Bootstrapper.wxs +++ b/cmake/Platform/Windows/Packaging/Bootstrapper.wxs @@ -5,7 +5,7 @@ - - [WixBundleName] Setup - [WixBundleName] + [WixBundleName] Release [WixBundleVersion] Setup Version [WixBundleVersion] Are you sure you want to cancel? - Welcome + Welcome to @CPACK_PACKAGE_FULL_NAME@! Setup will install [WixBundleName] on your computer. Click install to continue, options to set the install directory or Close to exit. - [WixBundleName] <a href="#">license terms</a>. - I &agree to the license terms and conditions + By installing, you agree to the @WIX_THEME_EULA_ACCEPTANCE_TEXT@ &Options &Install &Close @@ -34,7 +32,7 @@ Setup will install [WixBundleName] on your computer. Click install to continue, &Close - Setup Progress + Installing @CPACK_PACKAGE_FULL_NAME@... Processing: Initializing... &Cancel @@ -53,7 +51,9 @@ Setup will install [WixBundleName] on your computer. Click install to continue, Uninstall Failed Repair Failed -One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. +One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information, see the log file. + +<a href="#">View Log File</a> &Close diff --git a/cmake/Platform/Windows/Packaging/BootstrapperTheme.xml.in b/cmake/Platform/Windows/Packaging/BootstrapperTheme.xml.in index 61b338cc13..f9a177b646 100644 --- a/cmake/Platform/Windows/Packaging/BootstrapperTheme.xml.in +++ b/cmake/Platform/Windows/Packaging/BootstrapperTheme.xml.in @@ -1,87 +1,101 @@ - #(loc.WindowTitle) + #(loc.WindowTitle) - Segoe UI - Segoe UI - Segoe UI - Segoe UI + + Open Sans + + Open Sans + + Open Sans + + Open Sans - - #(loc.Title) + - @WIX_THEME_INSTALL_LICENSE_ELEMENT@ + #(loc.InstallHeader) - #(loc.InstallAcceptCheckbox) - - - +@WIX_THEME_INSTALL_LICENSE_ELEMENTS@ + + + + + - #(loc.OptionsHeader) + #(loc.OptionsHeader) - #(loc.OptionsLocationLabel) - - + #(loc.OptionsLocationLabel) + + - - + + + - #(loc.ModifyHeader) + #(loc.ModifyHeader) - - - + + + + - #(loc.ProgressHeader) + #(loc.ProgressHeader) - #(loc.ProgressLabel) - #(loc.OverallProgressPackageText) - + #(loc.ProgressLabel) + #(loc.OverallProgressPackageText) + - + + - #(loc.SuccessHeader) - #(loc.SuccessInstallHeader) - #(loc.SuccessRepairHeader) - #(loc.SuccessUninstallHeader) - - - + #(loc.SuccessHeader) + #(loc.SuccessInstallHeader) + #(loc.SuccessRepairHeader) + #(loc.SuccessUninstallHeader) + + + + - #(loc.FailureHeader) - #(loc.FailureInstallHeader) - #(loc.FailureUninstallHeader) - #(loc.FailureRepairHeader) + + #(loc.FailureHeader) + #(loc.FailureInstallHeader) + #(loc.FailureUninstallHeader) + #(loc.FailureRepairHeader) - #(loc.FailureHyperlinkLogText) - + #(loc.FailureHyperlinkLogText) + - + + - #(loc.HelpHeader) - #(loc.HelpText) - + #(loc.HelpHeader) + + #(loc.HelpText) + + + diff --git a/cmake/Platform/Windows/Packaging/product_logo.png b/cmake/Platform/Windows/Packaging/product_logo.png index ac9c06f8f1..1941b2ff8a 100644 --- a/cmake/Platform/Windows/Packaging/product_logo.png +++ b/cmake/Platform/Windows/Packaging/product_logo.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c804a6be619b9f35cad46eab30b94def7a4ac7142a92cb3f7c78a659381d834 +oid sha256:e7aaee03713eccd1ca4f909288ae16c9c563b2ac8d32a9e246bbb2eb941b47c7 size 11074 diff --git a/cmake/Platform/Windows/Packaging/warning.png b/cmake/Platform/Windows/Packaging/warning.png new file mode 100644 index 0000000000..75a5fd75a7 --- /dev/null +++ b/cmake/Platform/Windows/Packaging/warning.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d727994fd1819f7ff01d56e2d2f59c1fe2ed1e839156e70e3d2dec93d54ca04 +size 566 diff --git a/cmake/Platform/Windows/Packaging_windows.cmake b/cmake/Platform/Windows/Packaging_windows.cmake index aec0edeee2..6dc806ff56 100644 --- a/cmake/Platform/Windows/Packaging_windows.cmake +++ b/cmake/Platform/Windows/Packaging_windows.cmake @@ -91,23 +91,35 @@ set(CPACK_WIX_EXTENSIONS set(_embed_artifacts "yes") +set(_hyperlink_license [[ + #(loc.InstallEulaAcceptance) +]]) + +set(_raw_text_license [[ + + #(loc.InstallEulaAcceptance) +]]) + if(LY_INSTALLER_DOWNLOAD_URL) + set(WIX_THEME_WARNING_IMAGE ${CPACK_SOURCE_DIR}/Platform/Windows/Packaging/warning.png) + if(LY_INSTALLER_LICENSE_URL) - set(WIX_THEME_INSTALL_LICENSE_ELEMENT - "#(loc.InstallLicenseLinkText)" - ) + set(WIX_THEME_INSTALL_LICENSE_ELEMENTS ${_hyperlink_license}) + set(WIX_THEME_EULA_ACCEPTANCE_TEXT "<a href=\"#\">Terms of Use</a>") else() - set(WIX_THEME_INSTALL_LICENSE_ELEMENT - "" - ) + set(WIX_THEME_INSTALL_LICENSE_ELEMENTS ${_raw_text_license}) + set(WIX_THEME_EULA_ACCEPTANCE_TEXT "Terms of Use above") endif() + # theme ux file configure_file( "${CPACK_SOURCE_DIR}/Platform/Windows/Packaging/BootstrapperTheme.xml.in" "${CPACK_BINARY_DIR}/BootstrapperTheme.xml" @ONLY ) + + # theme localization file configure_file( "${CPACK_SOURCE_DIR}/Platform/Windows/Packaging/BootstrapperTheme.wxl.in" "${CPACK_BINARY_DIR}/BootstrapperTheme.wxl" diff --git a/cmake/Platform/Windows/RuntimeDependencies_windows.cmake b/cmake/Platform/Windows/RuntimeDependencies_windows.cmake index 8b50ec465d..add036a8b8 100644 --- a/cmake/Platform/Windows/RuntimeDependencies_windows.cmake +++ b/cmake/Platform/Windows/RuntimeDependencies_windows.cmake @@ -9,4 +9,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +set(LY_RUNTIME_DEPENDENCIES_TEMPLATE ${LY_ROOT_FOLDER}/cmake/Platform/Common/runtime_dependencies_common.cmake.in) include(cmake/Platform/Common/RuntimeDependencies_common.cmake) \ No newline at end of file diff --git a/cmake/TestImpactFramework/LYTestImpactFramework.cmake b/cmake/TestImpactFramework/LYTestImpactFramework.cmake index 661a066477..9789ce187f 100644 --- a/cmake/TestImpactFramework/LYTestImpactFramework.cmake +++ b/cmake/TestImpactFramework/LYTestImpactFramework.cmake @@ -384,7 +384,7 @@ function(ly_test_impact_write_config_file CONFIG_TEMPLATE_FILE PERSISTENT_DATA_D set(tiaf_bin "$") # Substitute config file template with above vars - file(READ "${CONFIG_TEMPLATE_FILE}" config_file) + ly_file_read("${CONFIG_TEMPLATE_FILE}" config_file) string(CONFIGURE ${config_file} config_file) # Write out entire config contents to a file in the build directory of the test impact framework console target diff --git a/engine.json b/engine.json index 09bb3f5ff6..8449e763a9 100644 --- a/engine.json +++ b/engine.json @@ -53,7 +53,6 @@ "Gems/MultiplayerCompression", "Gems/NvCloth", "Gems/PBSreferenceMaterials", - "Gems/PhysicsEntities", "Gems/PhysX", "Gems/PhysXDebug", "Gems/PhysXSamples", @@ -92,7 +91,9 @@ "AutomatedTesting" ], "templates": [ + "Templates/AssetGem", "Templates/DefaultGem", - "Templates/DefaultProject" + "Templates/DefaultProject", + "Templates/MinimalProject" ] } diff --git a/scripts/o3de/o3de/engine_template.py b/scripts/o3de/o3de/engine_template.py index 06e34cc449..384b8a3c0f 100755 --- a/scripts/o3de/o3de/engine_template.py +++ b/scripts/o3de/o3de/engine_template.py @@ -14,6 +14,7 @@ This file contains all the code that has to do with creating and instantiate eng import argparse import logging import os +import pathlib import shutil import sys import json @@ -79,7 +80,22 @@ restricted_platforms = { } template_file_name = 'template.json' -this_script_parent = os.path.dirname(os.path.realpath(__file__)) +this_script_parent = pathlib.Path(os.path.dirname(os.path.realpath(__file__))) + +def _replace_license_text(source_data: str): + while '{BEGIN_LICENSE}' in source_data: + start = source_data.find('{BEGIN_LICENSE}') + if start != -1: + line_start = source_data.rfind('\n', 0, start) + if line_start == -1: + line_start = 0 + end = source_data.find('{END_LICENSE}') + if end != -1: + end = source_data.find('\n', end) + if end != -1: + source_data = source_data[:line_start] + source_data[end + 1:] + return source_data + def _transform(s_data: str, replacements: list, @@ -92,7 +108,7 @@ def _transform(s_data: str, :return: the potentially transformed data """ # copy the s_data into t_data, then apply all transformations only on t_data - t_data = s_data + t_data = str(s_data) for replacement in replacements: t_data = t_data.replace(replacement[0], replacement[1]) @@ -100,30 +116,13 @@ def _transform(s_data: str, while '${Random_Uuid}' in t_data: t_data = t_data.replace('${Random_Uuid}', str(uuid.uuid4()), 1) - ################################################################## - # For some reason the re.sub call here gets into some kind of infinite - # loop and never returns on some files consistently. - # Until I figure out why we can use the string replacement method - # if not keep_license_text: - # t_data = re.sub(r"^(//|'''|#)\s*{BEGIN_LICENSE}((.|\n)*){END_LICENSE}\n", "", t_data, flags=re.DOTALL) - if not keep_license_text: - while '{BEGIN_LICENSE}' in t_data: - start = t_data.find('{BEGIN_LICENSE}') - if start != -1: - line_start = t_data.rfind('\n', 0, start) - if line_start == -1: - line_start = 0 - end = t_data.find('{END_LICENSE}') - end = t_data.find('\n', end) - if end != -1: - t_data = t_data[:line_start] + t_data[end + 1:] - ################################################################### + t_data = _replace_license_text(t_data) return t_data -def _transform_copy(source_file: str, - destination_file: str, +def _transform_copy(source_file: pathlib.Path, + destination_file: pathlib.Path, replacements: list, keep_license_text: bool = False) -> None: """ @@ -158,18 +157,18 @@ def _transform_copy(source_file: str, def _execute_template_json(json_data: dict, - destination_path: str, - template_path: str, + destination_path: pathlib.Path, + template_path: pathlib.Path, replacements: list, keep_license_text: bool = False) -> None: # create dirs first # for each createDirectory entry, transform the folder name for create_directory in json_data['createDirectories']: # construct the new folder name - new_dir = f"{destination_path}/{create_directory['dir']}" + new_dir = destination_path / create_directory['dir'] # transform the folder name - new_dir = _transform(new_dir, replacements, keep_license_text) + new_dir = _transform(new_dir.as_posix(), replacements, keep_license_text) # create the folder os.makedirs(new_dir, exist_ok=True) @@ -178,7 +177,7 @@ def _execute_template_json(json_data: dict, # regular copy if not templated for copy_file in json_data['copyFiles']: # construct the input file name - in_file = f"{template_path}/Template/{copy_file['file']}" + in_file = template_path / 'Template' /copy_file['file'] # the file can be marked as optional, if it is and it does not exist skip if copy_file['isOptional'] and copy_file['isOptional'] == 'true': @@ -186,10 +185,10 @@ def _execute_template_json(json_data: dict, continue # construct the output file name - out_file = f"{destination_path}/{copy_file['file']}" + out_file = destination_path / copy_file['file'] # transform the output file name - out_file = _transform(out_file, replacements, keep_license_text) + out_file = _transform(out_file.as_posix(), replacements, keep_license_text) # if for some reason the output folder for this file was not created above do it now os.makedirs(os.path.dirname(out_file), exist_ok=True) @@ -205,35 +204,35 @@ def _execute_restricted_template_json(json_data: dict, restricted_platform: str, destination_name, template_name, - destination_path: str, - destination_restricted_path: str, - template_restricted_path: str, - destination_restricted_platform_relative_path: str, - template_restricted_platform_relative_path: str, + destination_path: pathlib.Path, + destination_restricted_path: pathlib.Path, + template_restricted_path: pathlib.Path, + destination_restricted_platform_relative_path: pathlib.Path, + template_restricted_platform_relative_path: pathlib.Path, replacements: list, keep_restricted_in_instance: bool = False, keep_license_text: bool = False) -> None: # if we are not keeping restricted in instance make restricted.json if not present if not keep_restricted_in_instance: - restricted_json = f"{destination_restricted_path}/restricted.json".replace('//', '/') + restricted_json = destination_restricted_path / 'restricted.json' os.makedirs(os.path.dirname(restricted_json), exist_ok=True) if not os.path.isfile(restricted_json): with open(restricted_json, 'w') as s: restricted_json_data = {} restricted_json_data.update({"restricted_name": destination_name}) - s.write(json.dumps(restricted_json_data, indent=4)) + s.write(json.dumps(restricted_json_data, indent=4) + '\n') # create dirs first # for each createDirectory entry, transform the folder name for create_directory in json_data['createDirectories']: # construct the new folder name - new_dir = f"{destination_restricted_path}/{restricted_platform}/{destination_restricted_platform_relative_path}/{destination_name}/{create_directory['dir']}".replace( - '//', '/') + new_dir = destination_restricted_path / restricted_platform / destination_restricted_platform_relative_path\ + / destination_name / create_directory['dir'] if keep_restricted_in_instance: - new_dir = f"{destination_path}/{create_directory['origin']}".replace('//', '/') + new_dir = destination_path / create_directory['origin'] # transform the folder name - new_dir = _transform(new_dir, replacements, keep_license_text) + new_dir = _transform(new_dir.as_posix(), replacements, keep_license_text) # create the folder os.makedirs(new_dir, exist_ok=True) @@ -242,8 +241,8 @@ def _execute_restricted_template_json(json_data: dict, # regular copy if not templated for copy_file in json_data['copyFiles']: # construct the input file name - in_file = f"{template_restricted_path}/{restricted_platform}/{template_restricted_platform_relative_path}/{template_name}/Template/{copy_file['file']}".replace( - '//', '/') + in_file = template_restricted_path / restricted_platform / template_restricted_platform_relative_path\ + / template_name / 'Template'/ copy_file['file'] # the file can be marked as optional, if it is and it does not exist skip if copy_file['isOptional'] and copy_file['isOptional'] == 'true': @@ -251,13 +250,13 @@ def _execute_restricted_template_json(json_data: dict, continue # construct the output file name - out_file = f"{destination_restricted_path}/{restricted_platform}/{destination_restricted_platform_relative_path}/{destination_name}/{copy_file['file']}".replace( - '//', '/') + out_file = destination_restricted_path / restricted_platform / destination_restricted_platform_relative_path\ + / destination_name / copy_file['file'] if keep_restricted_in_instance: - out_file = f"{destination_path}/{copy_file['origin']}".replace('//', '/') + out_file = destination_path / copy_file['origin'] # transform the output file name - out_file = _transform(out_file, replacements, keep_license_text) + out_file = _transform(out_file.as_posix(), replacements, keep_license_text) # if for some reason the output folder for this file was not created above do it now os.makedirs(os.path.dirname(out_file), exist_ok=True) @@ -272,12 +271,12 @@ def _execute_restricted_template_json(json_data: dict, def _instantiate_template(template_json_data: dict, destination_name: str, template_name: str, - destination_path: str, - template_path: str, - destination_restricted_path: str, - template_restricted_path: str, - destination_restricted_platform_relative_path: str, - template_restricted_platform_relative_path: str, + destination_path: pathlib.Path, + template_path: pathlib.Path, + destination_restricted_path: pathlib.Path, + template_restricted_path: pathlib.Path, + destination_restricted_platform_relative_path: pathlib.Path, + template_restricted_platform_relative_path: pathlib.Path, replacements: list, keep_restricted_in_instance: bool = False, keep_license_text: bool = False) -> int: @@ -316,9 +315,9 @@ def _instantiate_template(template_json_data: dict, for restricted_platform in os.listdir(template_restricted_path): if os.path.isfile(restricted_platform): continue - template_restricted_platform = f'{template_restricted_path}/{restricted_platform}' - template_restricted_platform_path_rel = f'{template_restricted_platform}/{template_restricted_platform_relative_path}/{template_name}' - platform_json = f'{template_restricted_platform_path_rel}/{template_file_name}'.replace('//', '/') + template_restricted_platform = template_restricted_path / restricted_platform + template_restricted_platform_path_rel = template_restricted_platform / template_restricted_platform_relative_path / template_name + platform_json = template_restricted_platform_path_rel / template_file_name if os.path.isfile(platform_json): if not validation.valid_o3de_template_json(platform_json): @@ -349,17 +348,18 @@ def _instantiate_template(template_json_data: dict, return 0 -def create_template(source_path: str, - template_path: str, - source_restricted_path: str = None, +def create_template(source_path: pathlib.Path, + template_path: pathlib.Path, + source_restricted_path: pathlib.Path = None, source_restricted_name: str = None, - template_restricted_path: str = None, + template_restricted_path: pathlib.Path = None, template_restricted_name: str = None, - source_restricted_platform_relative_path: str = None, - template_restricted_platform_relative_path: str = None, + source_restricted_platform_relative_path: pathlib.Path = None, + template_restricted_platform_relative_path: pathlib.Path = None, keep_restricted_in_template: bool = False, keep_license_text: bool = False, - replace: list = None) -> int: + replace: list = None, + force: bool = False) -> int: """ Create a template from a source directory using replacement @@ -382,6 +382,7 @@ def create_template(source_path: str, Templated files can have license blocks starting with {BEGIN_LICENSE} and ending with {END_LICENSE}, this controls if you want to keep the license text from the template in the new instance. It is false by default because most people will not want license text in their instances. + :param force Overrides existing files even if they exist :return: 0 for success or non 0 failure code """ @@ -389,24 +390,23 @@ def create_template(source_path: str, if not source_path: logger.error('Src path cannot be empty.') return 1 - source_path = source_path.replace('\\', '/') if not os.path.isdir(source_path): logger.error(f'Src path {source_path} is not a folder.') return 1 # source_name is now the last component of the source_path source_name = os.path.basename(source_path) + sanitized_source_name = utils.sanitize_identifier_for_cpp(source_name) # if no template path, error if not template_path: logger.info(f'Template path empty. Using source name {source_name}') template_path = source_name - template_path = template_path.replace('\\', '/') if not os.path.isabs(template_path): default_templates_folder = manifest.get_registered(default_folder='templates') - template_path = f'{default_templates_folder}/{template_path}' + template_path = default_templates_folder/ template_path logger.info(f'Template path not a full path. Using default templates folder {template_path}') - if os.path.isdir(template_path): + if not force and os.path.isdir(template_path): logger.error(f'Template path {template_path} already exists.') return 1 @@ -423,9 +423,8 @@ def create_template(source_path: str, # source_restricted_path if source_restricted_path: - source_restricted_path = source_restricted_path.replace('\\', '/') if not os.path.isabs(source_restricted_path): - engine_json = f'{manifest.get_this_engine_path()}/engine.json' + engine_json = manifest.get_this_engine_path() / 'engine.json' if not validation.valid_o3de_engine_json(engine_json): logger.error(f"Engine json {engine_json} is not valid.") return 1 @@ -441,7 +440,7 @@ def create_template(source_path: str, logger.error(f"Engine json {engine_json} restricted not found.") return 1 engine_restricted_folder = manifest.get_registered(restricted_name=engine_restricted) - new_source_restricted_path = f'{engine_restricted_folder}/{source_restricted_path}' + new_source_restricted_path = engine_restricted_folder / source_restricted_path logger.info(f'Source restricted path {source_restricted_path} not a full path. We must assume this engines' f' restricted folder {new_source_restricted_path}') if not os.path.isdir(source_restricted_path): @@ -456,10 +455,9 @@ def create_template(source_path: str, # template_restricted_path if template_restricted_path: - template_restricted_path = template_restricted_path.replace('\\', '/') if not os.path.isabs(template_restricted_path): default_templates_restricted_folder = manifest.get_registered(restricted_name='templates') - new_template_restricted_path = f'{default_templates_restricted_folder}/{template_restricted_path}' + new_template_restricted_path = default_templates_restricted_folder / template_restricted_path logger.info(f'Template restricted path {template_restricted_path} not a full path. We must assume the' f' default templates restricted folder {new_template_restricted_path}') template_restricted_path = new_template_restricted_path @@ -467,7 +465,7 @@ def create_template(source_path: str, if os.path.isdir(template_restricted_path): # see if this is already a restricted path, if it is get the "restricted_name" from the restricted json # so we can set "restricted_name" to it for this template - restricted_json = f'{template_restricted_path}/restricted.json' + restricted_json = template_restricted_path / 'restricted.json' if os.path.isfile(restricted_json): if not validation.valid_o3de_restricted_json(restricted_json): logger.error(f'{restricted_json} is not valid.') @@ -484,18 +482,14 @@ def create_template(source_path: str, logger.error(f'Failed to read restricted_name from {restricted_json}') return 1 else: - os.makedirs(template_restricted_path) + os.makedirs(template_restricted_path, exist_ok=True) # source restricted relative - if source_restricted_platform_relative_path: - source_restricted_platform_relative_path = source_restricted_platform_relative_path.replace('\\', '/') - else: + if not source_restricted_platform_relative_path: source_restricted_platform_relative_path = '' # template restricted relative - if template_restricted_platform_relative_path: - template_restricted_platform_relative_path = template_restricted_platform_relative_path.replace('\\', '/') - else: + if not template_restricted_platform_relative_path: template_restricted_platform_relative_path = '' logger.info(f'Processing Src: {source_path}') @@ -513,8 +507,9 @@ def create_template(source_path: str, replacements.append((source_name.lower(), '${NameLower}')) replacements.append((source_name.upper(), '${NameUpper}')) replacements.append((source_name, '${Name}')) + replacements.append((sanitized_source_name, '${SanitizedCppName}')) - def _transform_into_template(s_data: object) -> (bool, object): + def _transform_into_template(s_data: object) -> (bool, str): """ Internal function to transform any data into templated data :param s_data: the input data, this could be file data or file name data @@ -522,18 +517,18 @@ def create_template(source_path: str, t_data: potentially transformed data 0 for success or non 0 failure code """ # copy the src data to the transformed data, then operate only on transformed data - t_data = s_data + t_data = str(s_data) # run all the replacements for replacement in replacements: t_data = t_data.replace(replacement[0], replacement[1]) if not keep_license_text: - t_data = re.sub(r"(//|'''|#)\s*{BEGIN_LICENSE}((.|\n)*){END_LICENSE}\n", "", t_data, flags=re.DOTALL) + t_data = _replace_license_text(t_data) # See if this file has the ModuleClassId try: - pattern = r'.*AZ_RTTI\(\$\{Name\}Module, \"(?P\{.*-.*-.*-.*-.*\})\", AZ::Module' + pattern = r'.*AZ_RTTI\(\$\{SanitizedCppName\}Module, \"(?P\{.*-.*-.*-.*-.*\})\",' module_class_id = re.search(pattern, t_data).group('ModuleClassId') replacements.append((module_class_id, '${ModuleClassId}')) t_data = t_data.replace(module_class_id, '${ModuleClassId}') @@ -542,7 +537,7 @@ def create_template(source_path: str, # See if this file has the SysCompClassId try: - pattern = r'.*AZ_COMPONENT\(\$\{Name\}SystemComponent, \"(?P\{.*-.*-.*-.*-.*\})\"' + pattern = r'.*AZ_COMPONENT\(\$\{SanitizedCppName\}SystemComponent, \"(?P\{.*-.*-.*-.*-.*\})\"' sys_comp_class_id = re.search(pattern, t_data).group('SysCompClassId') replacements.append((sys_comp_class_id, '${SysCompClassId}')) t_data = t_data.replace(sys_comp_class_id, '${SysCompClassId}') @@ -551,7 +546,7 @@ def create_template(source_path: str, # See if this file has the EditorSysCompClassId try: - pattern = r'.*AZ_COMPONENT\(\$\{Name\}EditorSystemComponent, \"(?P\{.*-.*-.*-.*-.*\})\"' + pattern = r'.*AZ_COMPONENT\(\$\{SanitizedCppName\}EditorSystemComponent, \"(?P\{.*-.*-.*-.*-.*\})\"' editor_sys_comp_class_id = re.search(pattern, t_data).group('EditorSysCompClassId') replacements.append((editor_sys_comp_class_id, '${EditorSysCompClassId}')) t_data = t_data.replace(editor_sys_comp_class_id, '${EditorSysCompClassId}') @@ -595,10 +590,10 @@ def create_template(source_path: str, else: return False, t_data - def _transform_restricted_into_copyfiles_and_createdirs(source_path: str, + def _transform_restricted_into_copyfiles_and_createdirs(source_path: pathlib.Path, restricted_platform: str, - root_abs: str, - path_abs: str = None) -> None: + root_abs: pathlib.Path, + path_abs: pathlib.Path = None) -> None: """ Internal function recursively called to transform any paths files into copyfiles and create dirs relative to the root. This will transform and copy the files, and save the copyfiles and createdirs data, no not save it @@ -613,10 +608,13 @@ def create_template(source_path: str, for entry in entries: # create the absolute entry by joining the path_abs and the entry - entry_abs = f'{path_abs}/{entry}' + entry_abs = path_abs / entry # create the relative entry by removing the root_abs - entry_rel = entry_abs.replace(root_abs + '/', '') + try: + entry_rel = entry_abs.relative_to(root_abs) + except ValueError as err: + logger.warning(f'Unable to create relative path: {str(err)}') # report what file we are processing so we have a good idea if it breaks on what file it broke on logger.info(f'Processing file: {entry_abs}') @@ -628,8 +626,8 @@ def create_template(source_path: str, # C:/repo/Lumberyard/restricted/Jasper/TestDP/CMakeLists.txt -> # C:/repo/Lumberyard/TestDP/Platform/Jasper/CMakeLists.txt # - _, origin_entry_rel = _transform_into_template(entry_rel) - components = origin_entry_rel.split('/') + _, origin_entry_rel = _transform_into_template(entry_rel.as_posix()) + components = list(origin_entry_rel.parts) num_components = len(components) # see how far along the source path the restricted folder matches @@ -656,29 +654,24 @@ def create_template(source_path: str, after.append(components[num_components - 1]) before.append("Platform") - warn_if_not_platform = f'{source_path}/{"/".join(before)}' + warn_if_not_platform = source_path / pathlib.Path(*before) before.append(restricted_platform) before.extend(after) - origin_entry_rel = '/'.join(before) + origin_entry_rel = pathlib.Path(*before) if not os.path.isdir(warn_if_not_platform): logger.warning( f'{entry_abs} -> {origin_entry_rel}: Other Platforms not found in {warn_if_not_platform}') destination_entry_rel = origin_entry_rel - destination_entry_abs = f'{template_path}/Template/{origin_entry_rel}' - - # clean up any collapsed folders - origin_entry_rel = origin_entry_rel.replace('//', '/') - destination_entry_abs = destination_entry_abs.replace('//', '/') - destination_entry_rel = destination_entry_rel.replace('//', '/') + destination_entry_abs = template_path / 'Template' / origin_entry_rel # clean up any relative leading slashes - while origin_entry_rel.startswith('/'): - origin_entry_rel = origin_entry_rel[1:] - while destination_entry_rel.startswith('/'): - destination_entry_rel = destination_entry_rel[1:] + if origin_entry_rel.as_posix().startswith('/'): + origin_entry_rel = pathlib.Path(origin_entry_rel.as_posix().lstrip('/')) + if destination_entry_rel.as_posix().startswith('/'): + destination_entry_rel = pathlib.Path(destination_entry_rel.as_posix().lstrip('/')) # make sure the dst folder may or may not exist yet, make sure it does exist before we transform # data into it @@ -735,8 +728,8 @@ def create_template(source_path: str, _transform_restricted_into_copyfiles_and_createdirs(source_path, restricted_platform, root_abs, entry_abs) - def _transform_dir_into_copyfiles_and_createdirs(root_abs: str, - path_abs: str = None) -> None: + def _transform_dir_into_copyfiles_and_createdirs(root_abs: pathlib.Path, + path_abs: pathlib.Path = None) -> None: """ Internal function recursively called to transform any paths files into copyfiles and create dirs relative to the root. This will transform and copy the files, and save the copyfiles and createdirs data, no not save it @@ -751,10 +744,14 @@ def create_template(source_path: str, for entry in entries: # create the absolute entry by joining the path_abs and the entry - entry_abs = f'{path_abs}/{entry}' + entry_abs = path_abs / entry # create the relative entry by removing the root_abs - entry_rel = entry_abs.replace(root_abs + '/', '') + entry_rel = entry_abs + try: + entry_rel = entry_abs.relative_to(root_abs) + except ValueError as err: + logger.warning(f'Unable to create relative path: {str(err)}') # report what file we are processing so we have a good idea if it breaks on what file it broke on logger.info(f'Processing file: {entry_abs}') @@ -763,7 +760,7 @@ def create_template(source_path: str, # then at the end we can save the restricted ones separately found_platform = '' platform = False - if not keep_restricted_in_template and '/Platform' in entry_abs: + if not keep_restricted_in_template and 'Platform' in entry_abs.parts: platform = True try: # the name of the Platform should follow the '/Platform/' @@ -787,7 +784,7 @@ def create_template(source_path: str, # Now if we found a platform and still have a found_platform which is a restricted platform # then transform the entry relative name into a dst relative entry name and dst abs entry. # if not then create a normal relative and abs dst entry name - _, origin_entry_rel = _transform_into_template(entry_rel) + _, origin_entry_rel = _transform_into_template(entry_rel.as_posix()) if platform and found_platform in restricted_platforms: # if we don't have a template restricted path and we found restricted files... warn and skip # the file/dir @@ -795,21 +792,22 @@ def create_template(source_path: str, logger.warning("Restricted platform files found!!! {entry_rel}, {found_platform}") continue _, destination_entry_rel = _transform_into_template_restricted_filename(entry_rel, found_platform) - destination_entry_abs = f'{template_restricted_path}/{found_platform}/{template_restricted_platform_relative_path}/{template_name}/Template/{destination_entry_rel}' + destination_entry_abs = template_restricted_path / found_platform\ + / template_restricted_platform_relative_path / template_name / 'Template'\ + / destination_entry_rel else: destination_entry_rel = origin_entry_rel - destination_entry_abs = f'{template_path}/Template/{destination_entry_rel}' - - # clean up any collapsed folders - origin_entry_rel = origin_entry_rel.replace('//', '/') - destination_entry_abs = destination_entry_abs.replace('//', '/') - destination_entry_rel = destination_entry_rel.replace('//', '/') + destination_entry_abs = template_path / 'Template' / destination_entry_rel # clean up any relative leading slashes - while origin_entry_rel.startswith('/'): - origin_entry_rel = origin_entry_rel[1:] - while destination_entry_rel.startswith('/'): - destination_entry_rel = destination_entry_rel[1:] + if isinstance(origin_entry_rel, pathlib.Path): + origin_entry_rel = origin_entry_rel.as_posix() + if origin_entry_rel.startswith('/'): + origin_entry_rel = pathlib.Path(origin_entry_rel.lstrip('/')) + if isinstance(destination_entry_rel, pathlib.Path): + destination_entry_rel = destination_entry_rel.as_posix() + if destination_entry_rel.startswith('/'): + destination_entry_rel = pathlib.Path(destination_entry_rel.lstrip('/')) # make sure the dst folder may or may not exist yet, make sure it does exist before we transform # data into it @@ -905,8 +903,8 @@ def create_template(source_path: str, # run the transformation on each src restricted folder if source_restricted_path: for restricted_platform in os.listdir(source_restricted_path): - restricted_platform_src_path_abs = f'{source_restricted_path}/{restricted_platform}/{source_restricted_platform_relative_path}/{source_name}'.replace( - '//', '/') + restricted_platform_src_path_abs = source_restricted_path / restricted_platform\ + / source_restricted_platform_relative_path / source_name if os.path.isdir(restricted_platform_src_path_abs): _transform_restricted_into_copyfiles_and_createdirs(source_path, restricted_platform, restricted_platform_src_path_abs) @@ -934,17 +932,14 @@ def create_template(source_path: str, json_data.update({'copyFiles': copy_files}) json_data.update({'createDirectories': create_dirs}) - json_name = f'{template_path}/{template_file_name}' + json_name = template_path / template_file_name - # if the json file we are about to write already exists for some reason, delete it - if os.path.isfile(json_name): - os.unlink(json_name) - with open(json_name, 'w') as s: - s.write(json.dumps(json_data, indent=4)) + with json_name.open('w') as s: + s.write(json.dumps(json_data, indent=4) + '\n') # copy the default preview.png - preview_png_src = f'{this_script_parent}/resources/preview.png' - preview_png_dst = f'{template_path}/Template/preview.png' + preview_png_src = this_script_parent / 'resources' /' preview.png' + preview_png_dst = template_path / 'Template' / 'preview.png' if not os.path.isfile(preview_png_dst): shutil.copy(preview_png_src, preview_png_dst) @@ -955,8 +950,8 @@ def create_template(source_path: str, if template_restricted_path: # now write out each restricted platform template json separately for restricted_platform in restricted_platform_entries: - restricted_template_path = f'{template_restricted_path}/{restricted_platform}/{template_restricted_platform_relative_path}/{template_name}'.replace( - '//', '/') + restricted_template_path = template_restricted_path / restricted_platform\ + / template_restricted_platform_relative_path / template_name # sort restricted_platform_entries[restricted_platform]['copyFiles'].sort(key=lambda x: x['file']) @@ -976,34 +971,32 @@ def create_template(source_path: str, json_data.update({'copyFiles': restricted_platform_entries[restricted_platform]['copyFiles']}) json_data.update({'createDirectories': restricted_platform_entries[restricted_platform]['createDirs']}) - json_name = f'{restricted_template_path}/{template_file_name}' + json_name = restricted_template_path / template_file_name os.makedirs(os.path.dirname(json_name), exist_ok=True) - # if the json file we are about to write already exists for some reason, delete it - if os.path.isfile(json_name): - os.unlink(json_name) - with open(json_name, 'w') as s: - s.write(json.dumps(json_data, indent=4)) + with json_name.open('w') as s: + s.write(json.dumps(json_data, indent=4) + '\n') - preview_png_dst = f'{restricted_template_path}/Template/preview.png' + preview_png_dst = restricted_template_path / 'Template' /' preview.png' if not os.path.isfile(preview_png_dst): shutil.copy(preview_png_src, preview_png_dst) return 0 -def create_from_template(destination_path: str, - template_path: str = None, +def create_from_template(destination_path: pathlib.Path, + template_path: pathlib.Path = None, template_name: str = None, - destination_restricted_path: str = None, + destination_restricted_path: pathlib.Path = None, destination_restricted_name: str = None, - template_restricted_path: str = None, + template_restricted_path: pathlib.Path = None, template_restricted_name: str = None, - destination_restricted_platform_relative_path: str = None, - template_restricted_platform_relative_path: str = None, + destination_restricted_platform_relative_path: pathlib.Path = None, + template_restricted_platform_relative_path: pathlib.Path = None, keep_restricted_in_instance: bool = False, keep_license_text: bool = False, - replace: list = None) -> int: + replace: list = None, + force: bool = False) -> int: """ Generic template instantiation for non o3de object templates. This function makes NO assumptions! Assumptions are made only for specializations like create_project or create_gem etc... So this function @@ -1026,6 +1019,7 @@ def create_from_template(destination_path: str, :param replace: optional list of strings uses to make concrete names out of templated parameters. X->Y pairs Ex. ${Name},TestGem,${Player},TestGemPlayer This will cause all references to ${Name} be replaced by TestGem, and all ${Player} replaced by 'TestGemPlayer' + :param force Overrides existing files even if they exist :return: 0 for success or non 0 failure code """ if template_name and template_path: @@ -1057,7 +1051,7 @@ def create_from_template(destination_path: str, template_folder_name = os.path.basename(template_path) # the template.json should be in the template_path, make sure it's there a nd valid - template_json = f'{template_path}/template.json' + template_json = template_path / 'template.json' if not validation.valid_o3de_template_json(template_json): logger.error(f'Template json {template_path} is invalid.') return 1 @@ -1116,7 +1110,6 @@ def create_from_template(destination_path: str, # The user has supplied the --template-restricted-path, see if that matches the template specifies. # If it does then we do not have a problem. If it doesn't match then error out. If not specified # in the template then warn and use the --template-restricted-path - template_restricted_path = template_restricted_path.replace('\\', '/') try: template_json_restricted_name = template_json_data['restricted_name'] except KeyError as e: @@ -1148,11 +1141,9 @@ def create_from_template(destination_path: str, # If not supplied and not in the template set empty string. if template_restricted_platform_relative_path: # The user specified a --template-restricted-platform-relative-path - template_restricted_platform_relative_path = template_restricted_platform_relative_path.replace( - '\\', '/') try: - template_json_restricted_platform_relative_path = template_json_data[ - 'restricted_platform_relative_path'] + template_json_restricted_platform_relative_path = pathlib.Path( + template_json_data['restricted_platform_relative_path']) except KeyError as e: # the template json doesn't have a 'restricted_platform_relative_path' element warn and use it logger.info(f'The template does not specify a "restricted_platform_relative_path".' @@ -1161,19 +1152,20 @@ def create_from_template(destination_path: str, # the template has a 'restricted_platform_relative_path', if it matches we are fine, if not # something is wrong with either the --template-restricted-platform-relative or the template is. if template_restricted_platform_relative_path != template_json_restricted_platform_relative_path: - logger.error(f'The supplied --template-restricted-platform-relative-path does not match the' - f' templates "restricted_platform_relative_path". Either' - f' --template-restricted-platform-relative-path is incorrect or the templates' - f' "restricted_platform_relative_path" is wrong. Note that since this template' - f' specifies "restricted_platform_relative_path" it need not be supplied and' - f' {template_json_restricted_platform_relative_path} will be used.') + logger.error(f'The supplied --template-restricted-platform-relative-path' + f' "{template_restricted_platform_relative_path}" does not match the' + f' templates.json "restricted_platform_relative_path". Either' + f' --template-restricted-platform-relative-path is incorrect or the templates' + f' "restricted_platform_relative_path" is wrong. Note that since this template' + f' specifies "restricted_platform_relative_path" it need not be supplied and' + f' "{template_json_restricted_platform_relative_path}" will be used.') return 1 else: # The user has not supplied --template-restricted-platform-relative-path, try to read it from # the template json. try: - template_restricted_platform_relative_path = template_json_data[ - 'restricted_platform_relative_path'] + template_restricted_platform_relative_path = pathlib.Path( + template_json_data['restricted_platform_relative_path']) except KeyError as e: # The template json doesn't have a 'restricted_platform_relative_path' element, set empty string. template_restricted_platform_relative_path = '' @@ -1185,12 +1177,11 @@ def create_from_template(destination_path: str, if not destination_path: logger.error('Destination path cannot be empty.') return 1 - destination_path = destination_path.replace('\\', '/') - if os.path.isdir(destination_path): + if not force and os.path.isdir(destination_path): logger.error(f'Destination path {destination_path} already exists.') return 1 else: - os.makedirs(destination_path) + os.makedirs(destination_path, exist_ok=force) # destination name is now the last component of the destination_path destination_name = os.path.basename(destination_path) @@ -1206,23 +1197,20 @@ def create_from_template(destination_path: str, # destination restricted path elif destination_restricted_path: - destination_restricted_path = destination_restricted_path.replace('\\', '/') if os.path.isabs(destination_restricted_path): restricted_default_path = manifest.get_registered(default='restricted') - new_destination_restricted_path = f'{restricted_default_path}/{destination_restricted_path}' + new_destination_restricted_path = restricted_default_path / destination_restricted_path logger.info(f'{destination_restricted_path} is not a full path, making it relative' f' to default restricted path = {new_destination_restricted_path}') destination_restricted_path = new_destination_restricted_path elif template_restricted_path: - restricted_default_path = manifest.get_registered(default='restricted') + restricted_default_path = manifest.get_registered(restricted_name='restricted') logger.info(f'--destination-restricted-path is not specified, using default restricted path / destination name' f' = {restricted_default_path}') destination_restricted_path = restricted_default_path # destination restricted relative - if destination_restricted_platform_relative_path: - destination_restricted_platform_relative_path = destination_restricted_platform_relative_path.replace('\\', '/') - else: + if not destination_restricted_platform_relative_path: destination_restricted_platform_relative_path = '' # any user supplied replacements @@ -1265,34 +1253,35 @@ def create_from_template(destination_path: str, os.makedirs(destination_restricted_path, exist_ok=True) # read the restricted_name from the destination restricted.json - restricted_json = f"{destination_restricted_path}/restricted.json".replace('//', '/') + restricted_json = destination_restricted_path / restricted.json if not os.path.isfile(restricted_json): with open(restricted_json, 'w') as s: restricted_json_data = {} restricted_json_data.update({'restricted_name': destination_name}) - s.write(json.dumps(restricted_json_data, indent=4)) + s.write(json.dumps(restricted_json_data, indent=4) + '\n') logger.warning(f'Instantiation successful. NOTE: This is a generic instantiation of the template. If this' - f' was a template of an o3de object like a project, gem, template, etc. then you should have used' - f' specialization that knows how to link that object type via its project.json or gem.json, etc.' + f' was a template of an o3de object like a project, gem, template, etc. then the create-project' + f' or create-gem command can be used to register the object type via its project.json or gem.json, etc.' f' Create from template is meant only to instance a template of a non o3de object.') return 0 -def create_project(project_path: str, +def create_project(project_path: pathlib.Path, project_name: str = None, - template_path: str = None, + template_path: pathlib.Path = None, template_name: str = None, - project_restricted_path: str = None, + project_restricted_path: pathlib.Path = None, project_restricted_name: str = None, - template_restricted_path: str = None, + template_restricted_path: pathlib.Path = None, template_restricted_name: str = None, - project_restricted_platform_relative_path: str = None, - template_restricted_platform_relative_path: str = None, + project_restricted_platform_relative_path: pathlib.Path = None, + template_restricted_platform_relative_path: pathlib.Path = None, keep_restricted_in_project: bool = False, keep_license_text: bool = False, replace: list = None, + force: bool = False, system_component_class_id: str = None, editor_system_component_class_id: str = None, module_id: str = None) -> int: @@ -1318,6 +1307,7 @@ def create_project(project_path: str, :param replace: optional list of strings uses to make concrete names out of templated parameters. X->Y pairs Ex. ${Name},TestGem,${Player},TestGemPlayer This will cause all references to ${Name} be replaced by TestGem, and all ${Player} replaced by 'TestGemPlayer' + :param force Overrides existing files even if they exist :param system_component_class_id: optionally specify a uuid for the system component class, default is random uuid :param editor_system_component_class_id: optionally specify a uuid for the editor system component class, default is random uuid @@ -1354,7 +1344,7 @@ def create_project(project_path: str, template_folder_name = os.path.basename(template_path) # the template.json should be in the template_path, make sure it's there and valid - template_json = f'{template_path}/template.json' + template_json = template_path / 'template.json' if not validation.valid_o3de_template_json(template_json): logger.error(f'Template json {template_path} is not valid.') return 1 @@ -1413,7 +1403,6 @@ def create_project(project_path: str, # The user has supplied the --template-restricted-path, see if that matches the template specifies. # If it does then we do not have a problem. If it doesn't match then error out. If not specified # in the template then warn and use the --template-restricted-path - template_restricted_path = template_restricted_path.replace('\\', '/') try: template_json_restricted_name = template_json_data['restricted_name'] except KeyError as e: @@ -1445,10 +1434,9 @@ def create_project(project_path: str, # If not supplied and not in the template set empty string. if template_restricted_platform_relative_path: # The user specified a --template-restricted-platform-relative-path - template_restricted_platform_relative_path = template_restricted_platform_relative_path.replace('\\', '/') try: - template_json_restricted_platform_relative_path = template_json_data[ - 'restricted_platform_relative_path'] + template_json_restricted_platform_relative_path = pathlib.Path( + template_json_data['restricted_platform_relative_path']) except KeyError as e: # the template json doesn't have a 'restricted_platform_relative_path' element warn and use it logger.info(f'The template does not specify a "restricted_platform_relative_path".' @@ -1457,19 +1445,20 @@ def create_project(project_path: str, # the template has a 'restricted_platform_relative_path', if it matches we are fine, if not # something is wrong with either the --template-restricted-platform-relative or the template is. if template_restricted_platform_relative_path != template_json_restricted_platform_relative_path: - logger.error(f'The supplied --template-restricted-platform-relative-path does not match the' - f' templates "restricted_platform_relative_path". Either' + logger.error(f'The supplied --template-restricted-platform-relative-path' + f' "{template_restricted_platform_relative_path}" does not match the' + f' templates.json "restricted_platform_relative_path". Either' f' --template-restricted-platform-relative-path is incorrect or the templates' f' "restricted_platform_relative_path" is wrong. Note that since this template' f' specifies "restricted_platform_relative_path" it need not be supplied and' - f' {template_json_restricted_platform_relative_path} will be used.') + f' "{template_json_restricted_platform_relative_path}" will be used.') return 1 else: # The user has not supplied --template-restricted-platform-relative-path, try to read it from # the template json. try: - template_restricted_platform_relative_path = template_json_data[ - 'restricted_platform_relative_path'] + template_restricted_platform_relative_path = pathlib.Path( + template_json_data['restricted_platform_relative_path']) except KeyError as e: # The template json doesn't have a 'restricted_platform_relative_path' element, set empty string. template_restricted_platform_relative_path = '' @@ -1480,18 +1469,17 @@ def create_project(project_path: str, if not project_path: logger.error('Project path cannot be empty.') return 1 - project_path = project_path.replace('\\', '/') if not os.path.isabs(project_path): default_projects_folder = manifest.get_registered(default_folder='projects') - new_project_path = f'{default_projects_folder}/{project_path}' + new_project_path = default_projects_folder / project_path logger.info(f'Project Path {project_path} is not a full path, we must assume its relative' f' to default projects path = {new_project_path}') project_path = new_project_path - if os.path.isdir(project_path) and len(os.listdir(project_path)) > 0: + if not force and os.path.isdir(project_path) and len(os.listdir(project_path)) > 0: logger.error(f'Project path {project_path} already exists and is not empty.') return 1 elif not os.path.isdir(project_path): - os.makedirs(project_path) + os.makedirs(project_path, exist_ok=force) if not project_name: # project name is now the last component of the project_path @@ -1512,10 +1500,9 @@ def create_project(project_path: str, # project restricted path elif project_restricted_path: - project_restricted_path = project_restricted_path.replace('\\', '/') if not os.path.isabs(project_restricted_path): default_projects_restricted_folder = manifest.get_registered(restricted_name='projects') - new_project_restricted_path = f'{default_projects_restricted_folder}/{project_restricted_path}' + new_project_restricted_path = default_projects_restricted_folder/ project_restricted_path logger.info(f'Project restricted path {project_restricted_path} is not a full path, we must assume its' f' relative to default projects restricted path = {new_project_restricted_path}') project_restricted_path = new_project_restricted_path @@ -1526,9 +1513,7 @@ def create_project(project_path: str, project_restricted_path = project_restricted_default_path # project restricted relative path - if project_restricted_platform_relative_path: - project_restricted_platform_relative_path = project_restricted_platform_relative_path.replace('\\', '/') - else: + if not project_restricted_platform_relative_path: project_restricted_platform_relative_path = '' # any user supplied replacements @@ -1597,7 +1582,7 @@ def create_project(project_path: str, os.makedirs(project_restricted_path, exist_ok=True) # read the restricted_name from the projects restricted.json - restricted_json = f"{project_restricted_path}/restricted.json".replace('//', '/') + restricted_json = project_restricted_path / 'restricted.json' if os.path.isfile(restricted_json): if not validation.valid_o3de_restricted_json(restricted_json): logger.error(f'Restricted json {restricted_json} is not valid.') @@ -1606,7 +1591,7 @@ def create_project(project_path: str, with open(restricted_json, 'w') as s: restricted_json_data = {} restricted_json_data.update({'restricted_name': project_name}) - s.write(json.dumps(restricted_json_data, indent=4)) + s.write(json.dumps(restricted_json_data, indent=4) + '\n') with open(restricted_json, 'r') as s: try: @@ -1622,7 +1607,7 @@ def create_project(project_path: str, return 1 # set the "restricted_name": "restricted_name" element of the project.json - project_json = f"{project_path}/project.json".replace('//', '/') + project_json = project_path / 'project.json' if not validation.valid_o3de_project_json(project_json): logger.error(f'Project json {project_json} is not valid.') return 1 @@ -1638,15 +1623,15 @@ def create_project(project_path: str, os.unlink(project_json) with open(project_json, 'w') as s: try: - s.write(json.dumps(project_json_data, indent=4)) + s.write(json.dumps(project_json_data, indent=4) + '\n') except OSError as e: logger.error(f'Failed to write project json {project_json}.') return 1 for restricted_platform in restricted_platforms: - restricted_project = f'{project_restricted_path}/{restricted_platform}/{project_name}' + restricted_project = project_restricted_path / restricted_platform / project_name os.makedirs(restricted_project, exist_ok=True) - cmakelists_file_name = f'{restricted_project}/CMakeLists.txt' + cmakelists_file_name = restricted_project/ 'CMakeLists.txt' if not os.path.isfile(cmakelists_file_name): with open(cmakelists_file_name, 'w') as d: if keep_license_text: @@ -1675,10 +1660,14 @@ def create_project(project_path: str, return 1 project_json_data = manifest.get_project_json_data(project_path=project_path) + if not project_json_data: + # get_project_json_data already logs an error if the project.json is mising + return 1 + project_json_data.update({"engine": engine_name}) with open(project_json, 'w') as s: try: - s.write(json.dumps(project_json_data, indent=4)) + s.write(json.dumps(project_json_data, indent=4) + '\n') except OSError as e: logger.error(f'Failed to write project json at {project_path}.') return 1 @@ -1686,18 +1675,19 @@ def create_project(project_path: str, return 0 -def create_gem(gem_path: str, - template_path: str = None, +def create_gem(gem_path: pathlib.Path, + template_path: pathlib.Path = None, template_name: str = None, - gem_restricted_path: str = None, + gem_restricted_path: pathlib.Path = None, gem_restricted_name: str = None, - template_restricted_path: str = None, + template_restricted_path: pathlib.Path = None, template_restricted_name: str = None, - gem_restricted_platform_relative_path: str = None, - template_restricted_platform_relative_path: str = None, + gem_restricted_platform_relative_path: pathlib.Path = None, + template_restricted_platform_relative_path: pathlib.Path = None, keep_restricted_in_gem: bool = False, keep_license_text: bool = False, replace: list = None, + force: bool = False, system_component_class_id: str = None, editor_system_component_class_id: str = None, module_id: str = None) -> int: @@ -1722,6 +1712,7 @@ def create_gem(gem_path: str, :param replace: optional list of strings uses to make concrete names out of templated parameters. X->Y pairs Ex. ${Name},TestGem,${Player},TestGemPlayer This will cause all references to ${Name} be replaced by TestGem, and all ${Player} replaced by 'TestGemPlayer' + :param force Overrides existing files even if they exist :param system_component_class_id: optionally specify a uuid for the system component class, default is random uuid :param editor_system_component_class_id: optionally specify a uuid for the editor system component class, default is random uuid @@ -1754,7 +1745,7 @@ def create_gem(gem_path: str, template_folder_name = os.path.basename(template_path) # the template.json should be in the template_path, make sure it's there and valid - template_json = f'{template_path}/template.json' + template_json = template_path / 'template.json' if not validation.valid_o3de_template_json(template_json): logger.error(f'Template json {template_path} is not valid.') return 1 @@ -1812,7 +1803,6 @@ def create_gem(gem_path: str, # The user has supplied the --template-restricted-path, see if that matches the template specifies. # If it does then we do not have a problem. If it doesn't match then error out. If not specified # in the template then warn and use the --template-restricted-path - template_restricted_path = template_restricted_path.replace('\\', '/') try: template_json_restricted_name = template_json_data['restricted_name'] except KeyError as e: @@ -1843,10 +1833,9 @@ def create_gem(gem_path: str, # If not supplied and not in the template set empty string. if template_restricted_platform_relative_path: # The user specified a --template-restricted-platform-relative-path - template_restricted_platform_relative_path = template_restricted_platform_relative_path.replace('\\', '/') try: - template_json_restricted_platform_relative_path = template_json_data[ - 'restricted_platform_relative_path'] + template_json_restricted_platform_relative_path = pathlib.Path( + template_json_data['restricted_platform_relative_path']) except KeyError as e: # the template json doesn't have a 'restricted_platform_relative_path' element warn and use it logger.info(f'The template does not specify a "restricted_platform_relative_path".' @@ -1855,12 +1844,13 @@ def create_gem(gem_path: str, # the template has a 'restricted_platform_relative_path', if it matches we are fine, if not something is # wrong with either the --template-restricted-platform-relative or the template is if template_restricted_platform_relative_path != template_json_restricted_platform_relative_path: - logger.error(f'The supplied --template-restricted-platform-relative-path does not match the' - f' templates "restricted_platform_relative_path". Either' + logger.error(f'The supplied --template-restricted-platform-relative-path' + f' "{template_restricted_platform_relative_path}" does not match the' + f' templates.json "restricted_platform_relative_path". Either' f' --template-restricted-platform-relative-path is incorrect or the templates' f' "restricted_platform_relative_path" is wrong. Note that since this template' f' specifies "restricted_platform_relative_path" it need not be supplied and' - f' {template_json_restricted_platform_relative_path} will be used.') + f' "{template_json_restricted_platform_relative_path}" will be used.') return 1 else: # The user has not supplied --template-restricted-platform-relative-path, try to read it from @@ -1878,20 +1868,21 @@ def create_gem(gem_path: str, if not gem_path: logger.error('Gem path cannot be empty.') return 1 - gem_path = gem_path.replace('\\', '/') if not os.path.isabs(gem_path): default_gems_folder = manifest.get_registered(default_folder='gems') - new_gem_path = f'{default_gems_folder}/{gem_path}' + new_gem_path = default_gems_folder / gem_path logger.info(f'Gem Path {gem_path} is not a full path, we must assume its relative' f' to default gems path = {new_gem_path}') gem_path = new_gem_path - if os.path.isdir(gem_path): + if not force and os.path.isdir(gem_path): logger.error(f'Gem path {gem_path} already exists.') return 1 else: - os.makedirs(gem_path) + os.makedirs(gem_path, exist_ok=force) - # gem name is now the last component of the gem_path + # gem nam + # + # e is now the last component of the gem_path gem_name = os.path.basename(gem_path) if not utils.validate_identifier(gem_name): @@ -1909,10 +1900,9 @@ def create_gem(gem_path: str, # gem restricted path elif gem_restricted_path: - gem_restricted_path = gem_restricted_path.replace('\\', '/') if not os.path.isabs(gem_restricted_path): default_gems_restricted_folder = manifest.get_registered(restricted_name='gems') - new_gem_restricted_path = f'{default_gems_restricted_folder}/{gem_restricted_path}' + new_gem_restricted_path = default_gems_restricted_folder /gem_restricted_path logger.info(f'Gem restricted path {gem_restricted_path} is not a full path, we must assume its' f' relative to default gems restricted path = {new_gem_restricted_path}') gem_restricted_path = new_gem_restricted_path @@ -1923,9 +1913,7 @@ def create_gem(gem_path: str, gem_restricted_path = gem_restricted_default_path # gem restricted relative - if gem_restricted_platform_relative_path: - gem_restricted_platform_relative_path = gem_restricted_platform_relative_path.replace('\\', '/') - else: + if not gem_restricted_platform_relative_path: gem_restricted_platform_relative_path = '' # any user supplied replacements @@ -1995,7 +1983,7 @@ def create_gem(gem_path: str, os.makedirs(gem_restricted_path, exist_ok=True) # read the restricted_name from the gems restricted.json - restricted_json = f"{gem_restricted_path}/restricted.json".replace('//', '/') + restricted_json = gem_restricted_path / 'restricted.json' if os.path.isfile(restricted_json): if not validation.valid_o3de_restricted_json(restricted_json): logger.error(f'Restricted json {restricted_json} is not valid.') @@ -2004,7 +1992,7 @@ def create_gem(gem_path: str, with open(restricted_json, 'w') as s: restricted_json_data = {} restricted_json_data.update({'restricted_name': gem_name}) - s.write(json.dumps(restricted_json_data, indent=4)) + s.write(json.dumps(restricted_json_data, indent=4) + '\n') with open(restricted_json, 'r') as s: try: @@ -2020,7 +2008,7 @@ def create_gem(gem_path: str, return 1 # set the "restricted_name": "restricted_name" element of the gem.json - gem_json = f"{gem_path}/gem.json".replace('//', '/') + gem_json = gem_path / 'gem.json' if not validation.valid_o3de_gem_json(gem_json): logger.error(f'Gem json {gem_json} is not valid.') return 1 @@ -2036,15 +2024,15 @@ def create_gem(gem_path: str, os.unlink(gem_json) with open(gem_json, 'w') as s: try: - s.write(json.dumps(gem_json_data, indent=4)) + s.write(json.dumps(gem_json_data, indent=4) + '\n') except OSError as e: logger.error(f'Failed to write project json {gem_json}.') return 1 for restricted_platform in restricted_platforms: - restricted_gem = f'{gem_restricted_path}/{restricted_platform}/{gem_name}' + restricted_gem = gem_restricted_path / restricted_platform/ gem_name os.makedirs(restricted_gem, exist_ok=True) - cmakelists_file_name = f'{restricted_gem}/CMakeLists.txt' + cmakelists_file_name = restricted_gem / 'CMakeLists.txt' if not os.path.isfile(cmakelists_file_name): with open(cmakelists_file_name, 'w') as d: if keep_license_text: @@ -2077,7 +2065,8 @@ def _run_create_template(args: argparse) -> int: args.template_restricted_platform_relative_path, args.keep_restricted_in_template, args.keep_license_text, - args.replace) + args.replace, + args.force) def _run_create_from_template(args: argparse) -> int: @@ -2092,7 +2081,8 @@ def _run_create_from_template(args: argparse) -> int: args.template_restricted_platform_relative_path, args.keep_restricted_in_instance, args.keep_license_text, - args.replace) + args.replace, + args.force) def _run_create_project(args: argparse) -> int: @@ -2109,6 +2099,7 @@ def _run_create_project(args: argparse) -> int: args.keep_restricted_in_project, args.keep_license_text, args.replace, + args.force, args.system_component_class_id, args.editor_system_component_class_id, args.module_id) @@ -2127,6 +2118,7 @@ def _run_create_gem(args: argparse) -> int: args.keep_restricted_in_gem, args.keep_license_text, args.replace, + args.force, args.system_component_class_id, args.editor_system_component_class_id, args.module_id) @@ -2144,13 +2136,13 @@ def add_args(subparsers) -> None: """ # turn a directory into a template create_template_subparser = subparsers.add_parser('create-template') - create_template_subparser.add_argument('-sp', '--source-path', type=str, required=True, + create_template_subparser.add_argument('-sp', '--source-path', type=pathlib.Path, required=True, help='The path to the source that you want to make into a template') - create_template_subparser.add_argument('-tp', '--template-path', type=str, required=False, + create_template_subparser.add_argument('-tp', '--template-path', type=pathlib.Path, required=False, help='The path to the template to create, can be absolute or relative' ' to default templates path') group = create_template_subparser.add_mutually_exclusive_group(required=False) - group.add_argument('-srp', '--source-restricted-path', type=str, required=False, + group.add_argument('-srp', '--source-restricted-path', type=pathlib.Path, required=False, default=None, help='The path to the source restricted folder.') group.add_argument('-srn', '--source-restricted-name', type=str, required=False, @@ -2159,7 +2151,7 @@ def add_args(subparsers) -> None: ' the --source-restricted-path.') group = create_template_subparser.add_mutually_exclusive_group(required=False) - group.add_argument('-trp', '--template-restricted-path', type=str, required=False, + group.add_argument('-trp', '--template-restricted-path', type=pathlib.Path, required=False, default=None, help='The path to the templates restricted folder.') group.add_argument('-trn', '--template-restricted-name', type=str, required=False, @@ -2167,7 +2159,7 @@ def add_args(subparsers) -> None: help='The name of the templates restricted folder. If supplied this will resolve' ' the --template-restricted-path.') - create_template_subparser.add_argument('-srprp', '--source-restricted-platform-relative-path', type=str, + create_template_subparser.add_argument('-srprp', '--source-restricted-platform-relative-path', type=pathlib.Path, required=False, default=None, help='Any path to append to the --source-restricted-path/' @@ -2175,7 +2167,7 @@ def add_args(subparsers) -> None: ' --source-restricted-path C:/restricted' ' --source-restricted-platform-relative-path some/folder' ' => C:/restricted//some/folder/') - create_template_subparser.add_argument('-trprp', '--template-restricted-platform-relative-path', type=str, + create_template_subparser.add_argument('-trprp', '--template-restricted-platform-relative-path', type=pathlib.Path, required=False, default=None, help='Any path to append to the --template-restricted-path/' @@ -2202,18 +2194,20 @@ def add_args(subparsers) -> None: ' Note: is automatically ${Name}' ' Note: is automatically ${NameLower}' ' Note: is automatically ${NameUpper}') + create_template_subparser.add_argument('-f', '--force', action='store_true', default=False, + help='Copies to new template directory even if it exist.') create_template_subparser.set_defaults(func=_run_create_template) # create from template create_from_template_subparser = subparsers.add_parser('create-from-template') - create_from_template_subparser.add_argument('-dp', '--destination-path', type=str, required=True, + create_from_template_subparser.add_argument('-dp', '--destination-path', type=pathlib.Path, required=True, help='The path to where you want the template instantiated,' ' can be absolute or dev root relative.' 'Ex. C:/o3de/Test' 'Test = ') group = create_from_template_subparser.add_mutually_exclusive_group(required=True) - group.add_argument('-tp', '--template-path', type=str, required=False, + group.add_argument('-tp', '--template-path', type=pathlib.Path, required=False, help='The path to the template you want to instantiate, can be absolute' ' or dev root/Templates relative.' 'Ex. C:/o3de/Template/TestTemplate' @@ -2222,8 +2216,8 @@ def add_args(subparsers) -> None: help='The name to the registered template you want to instantiate. If supplied this will' ' resolve the --template-path.') - group = create_from_template_subparser.add_mutually_exclusive_group(required=True) - group.add_argument('-drp', '--destination-restricted-path', type=str, required=False, + group = create_from_template_subparser.add_mutually_exclusive_group(required=False) + group.add_argument('-drp', '--destination-restricted-path', type=pathlib.Path, required=False, default=None, help='The destination restricted path is where the restricted files' ' will be written to.') @@ -2233,7 +2227,7 @@ def add_args(subparsers) -> None: ' will be written to. If supplied this will resolve the --destination-restricted-path.') group = create_from_template_subparser.add_mutually_exclusive_group(required=False) - group.add_argument('-trp', '--template-restricted-path', type=str, required=False, + group.add_argument('-trp', '--template-restricted-path', type=pathlib.Path, required=False, default=None, help='The template restricted path to read from if any') group.add_argument('-trn', '--template-restricted-name', type=str, required=False, @@ -2241,17 +2235,17 @@ def add_args(subparsers) -> None: help='The name of the registered restricted path to read from if any. If supplied this will' ' resolve the --template-restricted-path.') - create_from_template_subparser.add_argument('-drprp', '--destination-restricted-platform-relative-path', type=str, + create_from_template_subparser.add_argument('-drprp', '--destination-restricted-platform-relative-path', type=pathlib.Path, required=False, - default='', + default=None, help='Any path to append to the --destination-restricted-path/' ' to where the restricted destination is.' ' --destination-restricted-path C:/instance' ' --destination-restricted-platform-relative-path some/folder' ' => C:/instance//some/folder/') - create_from_template_subparser.add_argument('-trprp', '--template-restricted-platform-relative-path', type=str, + create_from_template_subparser.add_argument('-trprp', '--template-restricted-platform-relative-path', type=pathlib.Path, required=False, - default='Templates', + default=None, help='Any path to append to the --template-restricted-path/' ' to where the restricted template is.' ' --template-restricted-path C:/restricted' @@ -2276,11 +2270,13 @@ def add_args(subparsers) -> None: ' Note: ${Name} is automatically ' ' Note: ${NameLower} is automatically ' ' Note: ${NameUpper} is automatically ') + create_from_template_subparser.add_argument('-f', '--force', action='store_true', default=False, + help='Copies over instantiated template directory even if it exist.') create_from_template_subparser.set_defaults(func=_run_create_from_template) # creation of a project from a template (like create from template but makes project assumptions) create_project_subparser = subparsers.add_parser('create-project') - create_project_subparser.add_argument('-pp', '--project-path', type=str, required=True, + create_project_subparser.add_argument('-pp', '--project-path', type=pathlib.Path, required=True, help='The location of the project you wish to create from the template,' ' can be an absolute path or dev root relative.' ' Ex. C:/o3de/TestProject' @@ -2292,7 +2288,7 @@ def add_args(subparsers) -> None: ' Ex. New_Project-123') group = create_project_subparser.add_mutually_exclusive_group(required=False) - group.add_argument('-tp', '--template-path', type=str, required=False, + group.add_argument('-tp', '--template-path', type=pathlib.Path, required=False, default=None, help='the path to the template you want to instance, can be absolute or' ' relative to default templates path') @@ -2302,7 +2298,7 @@ def add_args(subparsers) -> None: ' to DefaultProject. If supplied this will resolve the --template-path.') group = create_project_subparser.add_mutually_exclusive_group(required=False) - group.add_argument('-prp', '--project-restricted-path', type=str, required=False, + group.add_argument('-prp', '--project-restricted-path', type=pathlib.Path, required=False, default=None, help='path to the projects restricted folder, can be absolute or relative' ' to the restricted="projects"') @@ -2312,7 +2308,7 @@ def add_args(subparsers) -> None: ' the --project-restricted-path.') group = create_project_subparser.add_mutually_exclusive_group(required=False) - group.add_argument('-trp', '--template-restricted-path', type=str, required=False, + group.add_argument('-trp', '--template-restricted-path', type=pathlib.Path, required=False, default=None, help='The templates restricted path can be absolute or relative to' ' restricted="templates"') @@ -2321,7 +2317,7 @@ def add_args(subparsers) -> None: help='The name of the registered templates restricted path. If supplied this will resolve' ' the --template-restricted-path.') - create_project_subparser.add_argument('-prprp', '--project-restricted-platform-relative-path', type=str, + create_project_subparser.add_argument('-prprp', '--project-restricted-platform-relative-path', type=pathlib.Path, required=False, default=None, help='Any path to append to the --project-restricted-path/' @@ -2329,7 +2325,7 @@ def add_args(subparsers) -> None: ' --project-restricted-path C:/restricted' ' --project-restricted-platform-relative-path some/folder' ' => C:/restricted//some/folder/') - create_project_subparser.add_argument('-trprp', '--template-restricted-platform-relative-path', type=str, + create_project_subparser.add_argument('-trprp', '--template-restricted-platform-relative-path', type=pathlib.Path, required=False, default=None, help='Any path to append to the --template-restricted-path/' @@ -2358,25 +2354,27 @@ def add_args(subparsers) -> None: ' Note: ${Name} is automatically ' ' Note: ${NameLower} is automatically ' ' Note: ${NameUpper} is automatically ') - create_project_subparser.add_argument('--system-component-class-id', type=utils.validate_uuid4, required=False, + create_project_subparser.add_argument('--system-component-class-id', type=uuid.UUID, required=False, help='The uuid you want to associate with the system class component, default' ' is a random uuid Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}') - create_project_subparser.add_argument('--editor-system-component-class-id', type=utils.validate_uuid4, + create_project_subparser.add_argument('--editor-system-component-class-id', type=uuid.UUID, required=False, help='The uuid you want to associate with the editor system class component,' ' default is a random uuid Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}') - create_project_subparser.add_argument('--module-id', type=utils.validate_uuid4, required=False, + create_project_subparser.add_argument('--module-id', type=uuid.UUID, required=False, help='The uuid you want to associate with the module, default is a random' ' uuid Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}') + create_project_subparser.add_argument('-f', '--force', action='store_true', default=False, + help='Copies over instantiated template directory even if it exist.') create_project_subparser.set_defaults(func=_run_create_project) # creation of a gem from a template (like create from template but makes gem assumptions) create_gem_subparser = subparsers.add_parser('create-gem') - create_gem_subparser.add_argument('-gp', '--gem-path', type=str, required=True, + create_gem_subparser.add_argument('-gp', '--gem-path', type=pathlib.Path, required=True, help='The gem path, can be absolute or relative to default gems path') group = create_gem_subparser.add_mutually_exclusive_group(required=False) - group.add_argument('-tp', '--template-path', type=str, required=False, + group.add_argument('-tp', '--template-path', type=pathlib.Path, required=False, default=None, help='The template path you want to instance, can be absolute or relative' ' to default templates path') @@ -2386,7 +2384,7 @@ def add_args(subparsers) -> None: ' to DefaultGem. If supplied this will resolve the --template-path.') group = create_gem_subparser.add_mutually_exclusive_group(required=False) - group.add_argument('-grp', '--gem-restricted-path', type=str, required=False, + group.add_argument('-grp', '--gem-restricted-path', type=pathlib.Path, required=False, default=None, help='The path to the gem restricted to write to folder if any, can be' 'absolute or dev root relative, default is dev root/restricted.') @@ -2397,7 +2395,7 @@ def add_args(subparsers) -> None: ' this will resolve the --gem-restricted-path.') group = create_gem_subparser.add_mutually_exclusive_group(required=False) - group.add_argument('-trp', '--template-restricted-path', type=str, required=False, + group.add_argument('-trp', '--template-restricted-path', type=pathlib.Path, required=False, default=None, help='The templates restricted path, can be absolute or relative to' ' the restricted="templates"') @@ -2406,7 +2404,7 @@ def add_args(subparsers) -> None: help='The name of the registered templates restricted path. If supplied' ' this will resolve the --template-restricted-path.') - create_gem_subparser.add_argument('-grprp', '--gem-restricted-platform-relative-path', type=str, + create_gem_subparser.add_argument('-grprp', '--gem-restricted-platform-relative-path', type=pathlib.Path, required=False, default=None, help='Any path to append to the --gem-restricted-path/' @@ -2414,7 +2412,7 @@ def add_args(subparsers) -> None: ' --gem-restricted-path C:/restricted' ' --gem-restricted-platform-relative-path some/folder' ' => C:/restricted//some/folder/') - create_gem_subparser.add_argument('-trprp', '--template-restricted-platform-relative-path', type=str, + create_gem_subparser.add_argument('-trprp', '--template-restricted-platform-relative-path', type=pathlib.Path, required=False, default=None, help='Any path to append to the --template-restricted-path/' @@ -2443,16 +2441,18 @@ def add_args(subparsers) -> None: ' default is False, so will not keep license text by default.' ' License text is defined as all lines of text starting on a line' ' with {BEGIN_LICENSE} and ending line {END_LICENSE}.') - create_gem_subparser.add_argument('--system-component-class-id', type=utils.validate_uuid4, required=False, + create_gem_subparser.add_argument('--system-component-class-id', type=uuid.UUID, required=False, help='The uuid you want to associate with the system class component, default' ' is a random uuid Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}') - create_gem_subparser.add_argument('--editor-system-component-class-id', type=utils.validate_uuid4, + create_gem_subparser.add_argument('--editor-system-component-class-id', type=uuid.UUID, required=False, help='The uuid you want to associate with the editor system class component,' ' default is a random uuid Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}') - create_gem_subparser.add_argument('--module-id', type=utils.validate_uuid4, required=False, + create_gem_subparser.add_argument('--module-id', type=uuid.UUID, required=False, help='The uuid you want to associate with the gem module,' ' default is a random uuid Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}') + create_gem_subparser.add_argument('-f', '--force', action='store_true', default=False, + help='Copies over instantiated template directory even if it exist.') create_gem_subparser.set_defaults(func=_run_create_gem) diff --git a/scripts/o3de/o3de/register.py b/scripts/o3de/o3de/register.py index b3a6a1e44c..37c572b6a4 100644 --- a/scripts/o3de/o3de/register.py +++ b/scripts/o3de/o3de/register.py @@ -64,9 +64,9 @@ def register_shipped_engine_o3de_objects(force: bool = False) -> int: return ret_val -def register_all_in_folder(folder_path: str or pathlib.Path, +def register_all_in_folder(folder_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None, + engine_path: pathlib.Path = None, exclude: list = None) -> int: if not folder_path: logger.error(f'Folder path cannot be empty.') @@ -136,10 +136,11 @@ def register_all_in_folder(folder_path: str or pathlib.Path, return ret_val -def register_all_o3de_objects_of_type_in_folder(o3de_object_path: str or pathlib.Path, +def register_all_o3de_objects_of_type_in_folder(o3de_object_path: pathlib.Path, o3de_object_type: str, remove: bool, force: bool, + stop_iteration_callable: callable, **register_kwargs) -> int: if not o3de_object_path: logger.error(f'Engines path cannot be empty.') @@ -155,8 +156,11 @@ def register_all_o3de_objects_of_type_in_folder(o3de_object_path: str or pathlib ret_val = 0 for root, dirs, files in os.walk(o3de_object_path): + # Skip subdirectories where the stop iteration callback is true + if stop_iteration_callable and stop_iteration_callable(dirs, files): + dirs[:] = [] if f'{o3de_object_type}.json' in files: - o3de_object_type_set.add(root) + o3de_object_type_set.add(pathlib.Path(root)) # Stop iteration of any subdirectories # Nested o3de objects of the same type aren't supported(i.e an engine cannot be inside of a engine). dirs[:] = [] @@ -170,41 +174,49 @@ def register_all_o3de_objects_of_type_in_folder(o3de_object_path: str or pathlib return ret_val -def register_all_engines_in_folder(engines_path: str or pathlib.Path, +def stop_on_template_folders(dirs: list, files: list) -> bool: + return 'template.json' in files + + +def register_all_engines_in_folder(engines_path: pathlib.Path, remove: bool = False, force: bool = False) -> int: - return register_all_o3de_objects_of_type_in_folder(engines_path, 'engine', remove, force) + return register_all_o3de_objects_of_type_in_folder(engines_path, 'engine', remove, force, None) -def register_all_projects_in_folder(projects_path: str or pathlib.Path, +def register_all_projects_in_folder(projects_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: - return register_all_o3de_objects_of_type_in_folder(projects_path, 'project', remove, False, engine_path=engine_path) + engine_path: pathlib.Path = None) -> int: + return register_all_o3de_objects_of_type_in_folder(projects_path, 'project', remove, False, + stop_on_template_folders, engine_path=engine_path) -def register_all_gems_in_folder(gems_path: str or pathlib.Path, +def register_all_gems_in_folder(gems_path: pathlib.Path, remove: bool = False, engine_path: pathlib.Path = None, project_path: pathlib.Path = None) -> int: - return register_all_o3de_objects_of_type_in_folder(gems_path, 'gem', remove, False, engine_path=engine_path) + return register_all_o3de_objects_of_type_in_folder(gems_path, 'gem', remove, False, stop_on_template_folders, + engine_path=engine_path) -def register_all_templates_in_folder(templates_path: str or pathlib.Path, +def register_all_templates_in_folder(templates_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: - return register_all_o3de_objects_of_type_in_folder(templates_path, 'template', remove, False, engine_path=engine_path) + engine_path: pathlib.Path = None) -> int: + return register_all_o3de_objects_of_type_in_folder(templates_path, 'template', remove, False, None, + engine_path=engine_path) -def register_all_restricted_in_folder(restricted_path: str or pathlib.Path, +def register_all_restricted_in_folder(restricted_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: - return register_all_o3de_objects_of_type_in_folder(restricted_path, 'restricted', remove, False, engine_path=engine_path) + engine_path: pathlib.Path = None) -> int: + return register_all_o3de_objects_of_type_in_folder(restricted_path, 'restricted', remove, False, None, + engine_path=engine_path) -def register_all_repos_in_folder(repos_path: str or pathlib.Path, +def register_all_repos_in_folder(repos_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: - return register_all_o3de_objects_of_type_in_folder(repos_path, 'repo', remove, force, engine_path=engine_path) + engine_path: pathlib.Path = None) -> int: + return register_all_o3de_objects_of_type_in_folder(repos_path, 'repo', remove, force, None, engine_path=engine_path) def remove_engine_name_to_path(json_data: dict, @@ -252,7 +264,7 @@ def add_engine_name_to_path(json_data: dict, engine_path: pathlib.Path, force: b def register_engine_path(json_data: dict, - engine_path: str or pathlib.Path, + engine_path: pathlib.Path, remove: bool = False, force: bool = False) -> int: if not engine_path: @@ -260,8 +272,11 @@ def register_engine_path(json_data: dict, return 1 engine_path = pathlib.Path(engine_path).resolve() - for engine_object in json_data.get('engines', {}): - engine_object_path = pathlib.Path(engine_object['path']).resolve() + for engine_object in json_data.get('engines', []): + if isinstance(engine_object, dict): + engine_object_path = pathlib.Path(engine_object['path']).resolve() + else: + engine_object_path = pathlib.Path(engine_object).resolve() if engine_object_path == engine_path: json_data['engines'].remove(engine_object) @@ -362,7 +377,7 @@ def register_o3de_object_path(json_data: dict, def register_external_subdirectory(json_data: dict, - external_subdir_path: str or pathlib.Path, + external_subdir_path: pathlib.Path, remove: bool = False, engine_path: pathlib.Path = None, project_path: pathlib.Path = None) -> int: @@ -375,7 +390,7 @@ def register_external_subdirectory(json_data: dict, def register_gem_path(json_data: dict, - gem_path: str or pathlib.Path, + gem_path: pathlib.Path, remove: bool = False, engine_path: pathlib.Path = None, project_path: pathlib.Path = None) -> int: @@ -384,9 +399,9 @@ def register_gem_path(json_data: dict, def register_project_path(json_data: dict, - project_path: str or pathlib.Path, + project_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: + engine_path: pathlib.Path = None) -> int: result = register_o3de_object_path(json_data, project_path, 'projects', 'project.json', validation.valid_o3de_project_json, remove, engine_path, None) @@ -408,9 +423,10 @@ def register_project_path(json_data: dict, update_project_json = True if update_project_json: + project_json_path = project_path / 'project.json' project_json_data['engine'] = this_engine_json['engine_name'] - utils.backup_file(project_json) - if not manifest.save_o3de_manifest(project_json_data, project_path): + utils.backup_file(project_json_path) + if not manifest.save_o3de_manifest(project_json_data, project_json_path): return 1 @@ -418,17 +434,17 @@ def register_project_path(json_data: dict, def register_template_path(json_data: dict, - template_path: str or pathlib.Path, + template_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: + engine_path: pathlib.Path = None) -> int: return register_o3de_object_path(json_data, template_path, 'templates', 'template.json', validation.valid_o3de_template_json, remove, engine_path, None) def register_restricted_path(json_data: dict, - restricted_path: str or pathlib.Path, + restricted_path: pathlib.Path, remove: bool = False, - engine_path: str or pathlib.Path = None) -> int: + engine_path: pathlib.Path = None) -> int: return register_o3de_object_path(json_data, restricted_path, 'restricted', 'restricted.json', validation.valid_o3de_restricted_json, remove, engine_path, None) @@ -468,7 +484,7 @@ def register_repo(json_data: dict, def register_default_o3de_object_folder(json_data: dict, - default_o3de_object_folder: str or pathlib.Path, + default_o3de_object_folder: pathlib.Path, o3de_object_key: str) -> int: # make sure the path exists default_o3de_object_folder = pathlib.Path(default_o3de_object_folder).resolve() @@ -482,7 +498,7 @@ def register_default_o3de_object_folder(json_data: dict, def register_default_engines_folder(json_data: dict, - default_engines_folder: str or pathlib.Path, + default_engines_folder: pathlib.Path, remove: bool = False) -> int: return register_default_o3de_object_folder(json_data, manifest.get_o3de_engines_folder() if remove else default_engines_folder, @@ -490,7 +506,7 @@ def register_default_engines_folder(json_data: dict, def register_default_projects_folder(json_data: dict, - default_projects_folder: str or pathlib.Path, + default_projects_folder: pathlib.Path, remove: bool = False) -> int: return register_default_o3de_object_folder(json_data, manifest.get_o3de_projects_folder() if remove else default_projects_folder, @@ -498,7 +514,7 @@ def register_default_projects_folder(json_data: dict, def register_default_gems_folder(json_data: dict, - default_gems_folder: str or pathlib.Path, + default_gems_folder: pathlib.Path, remove: bool = False) -> int: return register_default_o3de_object_folder(json_data, manifest.get_o3de_gems_folder() if remove else default_gems_folder, @@ -506,7 +522,7 @@ def register_default_gems_folder(json_data: dict, def register_default_templates_folder(json_data: dict, - default_templates_folder: str or pathlib.Path, + default_templates_folder: pathlib.Path, remove: bool = False) -> int: return register_default_o3de_object_folder(json_data, manifest.get_o3de_templates_folder() if remove else default_templates_folder, @@ -514,7 +530,7 @@ def register_default_templates_folder(json_data: dict, def register_default_restricted_folder(json_data: dict, - default_restricted_folder: str or pathlib.Path, + default_restricted_folder: pathlib.Path, remove: bool = False) -> int: return register_default_o3de_object_folder(json_data, manifest.get_o3de_restricted_folder() if remove else default_restricted_folder, @@ -527,18 +543,18 @@ def register_default_third_party_folder(json_data: dict, manifest.get_o3de_third_party_folder() if remove else default_third_party_folder, 'default_third_party_folder') -def register(engine_path: str or pathlib.Path = None, - project_path: str or pathlib.Path = None, - gem_path: str or pathlib.Path = None, - external_subdir_path: str or pathlib.Path = None, - template_path: str or pathlib.Path = None, - restricted_path: str or pathlib.Path = None, +def register(engine_path: pathlib.Path = None, + project_path: pathlib.Path = None, + gem_path: pathlib.Path = None, + external_subdir_path: pathlib.Path = None, + template_path: pathlib.Path = None, + restricted_path: pathlib.Path = None, repo_uri: str or pathlib.Path = None, - default_engines_folder: str or pathlib.Path = None, - default_projects_folder: str or pathlib.Path = None, - default_gems_folder: str or pathlib.Path = None, - default_templates_folder: str or pathlib.Path = None, - default_restricted_folder: str or pathlib.Path = None, + default_engines_folder: pathlib.Path = None, + default_projects_folder: pathlib.Path = None, + default_gems_folder: pathlib.Path = None, + default_templates_folder: pathlib.Path = None, + default_restricted_folder: pathlib.Path = None, default_third_party_folder: pathlib.Path = None, external_subdir_engine_path: pathlib.Path = None, external_subdir_project_path: pathlib.Path = None, @@ -576,32 +592,32 @@ def register(engine_path: str or pathlib.Path = None, result = 0 # do anything that could require a engine context first - if isinstance(project_path, str) or isinstance(project_path, pathlib.PurePath): + if isinstance(project_path, pathlib.PurePath): if not project_path: logger.error(f'Project path cannot be empty.') return 1 result = result or register_project_path(json_data, project_path, remove, engine_path) - if isinstance(gem_path, str) or isinstance(gem_path, pathlib.PurePath): + if isinstance(gem_path, pathlib.PurePath): if not gem_path: logger.error(f'Gem path cannot be empty.') return 1 result = result or register_gem_path(json_data, gem_path, remove, external_subdir_engine_path, external_subdir_project_path) - if isinstance(external_subdir_path, str) or isinstance(external_subdir_path, pathlib.PurePath): + if isinstance(external_subdir_path, pathlib.PurePath): if not external_subdir_path: logger.error(f'External Subdirectory path is None.') return 1 result = result or register_external_subdirectory(json_data, external_subdir_path, remove, external_subdir_engine_path, external_subdir_project_path) - if isinstance(template_path, str) or isinstance(template_path, pathlib.PurePath): + if isinstance(template_path, pathlib.PurePath): if not template_path: logger.error(f'Template path cannot be empty.') return 1 result = result or register_template_path(json_data, template_path, remove, engine_path) - if isinstance(restricted_path, str) or isinstance(restricted_path, pathlib.PurePath): + if isinstance(restricted_path, pathlib.PurePath): if not restricted_path: logger.error(f'Restricted path cannot be empty.') return 1 @@ -613,28 +629,28 @@ def register(engine_path: str or pathlib.Path = None, return 1 result = result or register_repo(json_data, repo_uri, remove) - if isinstance(default_engines_folder, str) or isinstance(default_engines_folder, pathlib.PurePath): + if isinstance(default_engines_folder, pathlib.PurePath): result = result or register_default_engines_folder(json_data, default_engines_folder, remove) - if isinstance(default_projects_folder, str) or isinstance(default_projects_folder, pathlib.PurePath): + if isinstance(default_projects_folder, pathlib.PurePath): result = result or register_default_projects_folder(json_data, default_projects_folder, remove) - if isinstance(default_gems_folder, str) or isinstance(default_gems_folder, pathlib.PurePath): + if isinstance(default_gems_folder, pathlib.PurePath): result = result or register_default_gems_folder(json_data, default_gems_folder, remove) - if isinstance(default_templates_folder, str) or isinstance(default_templates_folder, pathlib.PurePath): + if isinstance(default_templates_folder, pathlib.PurePath): result = result or register_default_templates_folder(json_data, default_templates_folder, remove) - if isinstance(default_restricted_folder, str) or isinstance(default_restricted_folder, pathlib.PurePath): + if isinstance(default_restricted_folder, pathlib.PurePath): result = result or register_default_restricted_folder(json_data, default_restricted_folder, remove) - if isinstance(default_third_party_folder, str) or isinstance(default_third_party_folder, pathlib.PurePath): + if isinstance(default_third_party_folder, pathlib.PurePath): result = result or register_default_third_party_folder(json_data, default_third_party_folder, remove) # engine is done LAST # Now that everything that could have an engine context is done, if the engine is supplied that means this is # registering the engine itself - if isinstance(engine_path, str) or isinstance(engine_path, pathlib.PurePath): + if isinstance(engine_path, pathlib.PurePath): if not engine_path: logger.error(f'Engine path cannot be empty.') return 1 @@ -789,41 +805,41 @@ def add_parser_args(parser): group.add_argument('--this-engine', action='store_true', required=False, default=False, help='Registers the engine this script is running from.') - group.add_argument('-ep', '--engine-path', type=str, required=False, + group.add_argument('-ep', '--engine-path', type=pathlib.Path, required=False, help='Engine path to register/remove.') - group.add_argument('-pp', '--project-path', type=str, required=False, + group.add_argument('-pp', '--project-path', type=pathlib.Path, required=False, help='Project path to register/remove.') - group.add_argument('-gp', '--gem-path', type=str, required=False, + group.add_argument('-gp', '--gem-path', type=pathlib.Path, required=False, help='Gem path to register/remove.') - group.add_argument('-es', '--external-subdirectory', type=str, required=False, + group.add_argument('-es', '--external-subdirectory', type=pathlib.Path, required=False, help='External subdirectory path to register/remove.') - group.add_argument('-tp', '--template-path', type=str, required=False, + group.add_argument('-tp', '--template-path', type=pathlib.Path, required=False, help='Template path to register/remove.') - group.add_argument('-rp', '--restricted-path', type=str, required=False, + group.add_argument('-rp', '--restricted-path', type=pathlib.Path, required=False, help='A restricted folder to register/remove.') group.add_argument('-ru', '--repo-uri', type=str, required=False, help='A repo uri to register/remove.') - group.add_argument('-aep', '--all-engines-path', type=str, required=False, + group.add_argument('-aep', '--all-engines-path', type=pathlib.Path, required=False, help='All engines under this folder to register/remove.') - group.add_argument('-app', '--all-projects-path', type=str, required=False, + group.add_argument('-app', '--all-projects-path', type=pathlib.Path, required=False, help='All projects under this folder to register/remove.') - group.add_argument('-agp', '--all-gems-path', type=str, required=False, + group.add_argument('-agp', '--all-gems-path', type=pathlib.Path, required=False, help='All gems under this folder to register/remove.') - group.add_argument('-atp', '--all-templates-path', type=str, required=False, + group.add_argument('-atp', '--all-templates-path', type=pathlib.Path, required=False, help='All templates under this folder to register/remove.') - group.add_argument('-arp', '--all-restricted-path', type=str, required=False, + group.add_argument('-arp', '--all-restricted-path', type=pathlib.Path, required=False, help='All templates under this folder to register/remove.') - group.add_argument('-aru', '--all-repo-uri', type=str, required=False, + group.add_argument('-aru', '--all-repo-uri', type=pathlib.Path, required=False, help='All repos under this folder to register/remove.') - group.add_argument('-def', '--default-engines-folder', type=str, required=False, + group.add_argument('-def', '--default-engines-folder', type=pathlib.Path, required=False, help='The default engines folder to register/remove.') - group.add_argument('-dpf', '--default-projects-folder', type=str, required=False, + group.add_argument('-dpf', '--default-projects-folder', type=pathlib.Path, required=False, help='The default projects folder to register/remove.') - group.add_argument('-dgf', '--default-gems-folder', type=str, required=False, + group.add_argument('-dgf', '--default-gems-folder', type=pathlib.Path, required=False, help='The default gems folder to register/remove.') - group.add_argument('-dtf', '--default-templates-folder', type=str, required=False, + group.add_argument('-dtf', '--default-templates-folder', type=pathlib.Path, required=False, help='The default templates folder to register/remove.') - group.add_argument('-drf', '--default-restricted-folder', type=str, required=False, + group.add_argument('-drf', '--default-restricted-folder', type=pathlib.Path, required=False, help='The default restricted folder to register/remove.') group.add_argument('-dtpf', '--default-third-party-folder', type=pathlib.Path, required=False, help='The default 3rd Party folder to register/remove.') @@ -831,7 +847,7 @@ def add_parser_args(parser): default=False, help='Refresh the repo cache.') - parser.add_argument('-ohf', '--override-home-folder', type=str, required=False, + parser.add_argument('-ohf', '--override-home-folder', type=pathlib.Path, required=False, help='By default the home folder is the user folder, override it to this folder.') parser.add_argument('-r', '--remove', action='store_true', required=False, default=False,