diff --git a/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_diff.tif.exportsettings b/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_diff.tif.exportsettings index 5c4c862583..b65133fbb0 100644 --- a/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_diff.tif.exportsettings +++ b/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_diff.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /preset=AlbedoWithGenericAlpha /reduce="es3:2,ios:2,osx_gl:0,pc:0,provo:0" \ No newline at end of file +/autooptimizefile=0 /preset=AlbedoWithGenericAlpha /reduce="android:2,ios:2,mac:0,pc:0,provo:0" \ No newline at end of file diff --git a/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_sss.tif.exportsettings b/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_sss.tif.exportsettings index 441a11bc68..e8da408b36 100644 --- a/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_sss.tif.exportsettings +++ b/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_sss.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /preset=Albedo /reduce="es3:3,ios:3,osx_gl:0,pc:0,provo:0" \ No newline at end of file +/autooptimizefile=0 /preset=Albedo /reduce="android:3,ios:3,mac:0,pc:0,provo:0" \ No newline at end of file diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_all_platforms_setup_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_all_platforms_setup_fixture.py index e729ee9882..9a5b93ca80 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_all_platforms_setup_fixture.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/ap_all_platforms_setup_fixture.py @@ -34,10 +34,10 @@ def ap_all_platforms_setup_fixture(request, workspace, ap_setup_fixture) -> Dict # Specific platform cache locations resources["pc_cache_location"] = os.path.join(cache_dir, "pc") - resources["es3_cache_location"] = os.path.join(cache_dir, "es3") + resources["android_cache_location"] = os.path.join(cache_dir, "android") resources["ios_cache_location"] = os.path.join(cache_dir, "ios") - resources["osx_gl_cache_location"] = os.path.join(cache_dir, "osx_gl") + resources["mac_cache_location"] = os.path.join(cache_dir, "mac") resources["provo_cache_location"] = os.path.join(cache_dir, "provo") - resources["all_platforms"] = ["pc", "es3", "ios", "osx_gl", "provo"] + resources["all_platforms"] = ["pc", "android", "ios", "mac", "provo"] return resources diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py index 580816e7b5..7a85cb1813 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py @@ -54,7 +54,7 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) -> platforms = [platform.strip() for platform in platforms.split(",")] else: # No commandline argument provided, default to mac and pc - platforms = ["pc", "osx_gl"] + platforms = ["pc", "mac"] class BundlerBatchFixture: """ @@ -241,11 +241,11 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) -> def get_platform_flag(self, platform_name: str) -> int: if (platform_name == "pc"): return 1 - elif (platform_name == "es3"): + elif (platform_name == "android"): return 2 elif (platform_name == "ios"): return 4 - elif (platform_name == "osx_gl"): + elif (platform_name == "mac"): return 8 elif (platform_name == "server"): return 128 diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py index d236e87aa2..8738e8acdf 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py @@ -460,9 +460,9 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): """ helper = bundler_batch_helper # fmt:off - assert "pc" in helper["platforms"] and "osx_gl" in helper["platforms"], \ + assert "pc" in helper["platforms"] and "mac" in helper["platforms"], \ "This test requires both PC and MAC platforms to be enabled. " \ - "Please rerun with commandline option: '--bundle_platforms=pc,osx_gl'" + "Please rerun with commandline option: '--bundle_platforms=pc,mac'" # fmt:on seed_list = os.path.join(workspace.paths.engine_root(), "Engine", "SeedAssetList.seed") # Engine seed list @@ -502,7 +502,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): for bundle_file in bundle_files.values(): assert os.path.isfile(bundle_file) - # This asset is created on osx_gl platform but not on windows + # This asset is created on mac platform but not on windows file_to_check = b"engineassets/shading/defaultprobe_cm.dds.5" # [use byte str because file is in binary] # Extract the delta catalog file from pc archive. {file_to_check} SHOULD NOT be present for PC @@ -512,11 +512,11 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): f"{file_to_check} was found in DeltaCatalog.xml in pc bundle file {bundle_files['pc']}" # fmt:on - # Extract the delta catalog file from osx_gl archive. {file_to_check} SHOULD be present for MAC - file_contents = helper.extract_file_content(bundle_files["osx_gl"], "DeltaCatalog.xml") + # Extract the delta catalog file from mac archive. {file_to_check} SHOULD be present for MAC + file_contents = helper.extract_file_content(bundle_files["mac"], "DeltaCatalog.xml") # fmt:off assert file_to_check in file_contents, \ - f"{file_to_check} was not found in DeltaCatalog.xml in darwin bundle file {bundle_files['osx_gl']}" + f"{file_to_check} was not found in DeltaCatalog.xml in darwin bundle file {bundle_files['mac']}" # fmt:on # Gather checksums for first set of bundles @@ -613,7 +613,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): helper.call_seeds( seedListFile=helper["seed_list_file"], addSeed=test_asset, - platform="pc,osx_gl", + platform="pc,mac", ) # Validate both mac and pc are activated for seed @@ -626,7 +626,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): helper.call_seeds( seedListFile=helper["seed_list_file"], removePlatformFromSeeds="", - platform="osx_gl", + platform="mac", ) # Validate only pc platform for seed. Save file contents to variable all_lines = check_seed_platform(helper["seed_list_file"], test_asset, helper["platform_values"]["pc"]) @@ -646,7 +646,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): helper.call_seeds( seedListFile=helper["seed_list_file"], addPlatformToSeeds="", - platform="osx_gl", + platform="mac", ) # Validate Mac platform was added back on. Save file contents # fmt:off @@ -670,7 +670,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): helper.call_seeds( seedListFile=helper["seed_list_file"], removeSeed=test_asset, - platform="pc,osx_gl", + platform="pc,mac", ) # Validate seed was removed from file @@ -697,9 +697,9 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): env = ap_setup_fixture # fmt:off - assert "pc" in helper["platforms"] and "osx_gl" in helper["platforms"], \ + assert "pc" in helper["platforms"] and "mac" in helper["platforms"], \ "This test requires both PC and MAC platforms to be enabled. " \ - "Please rerun with commandline option: '--bundle_platforms=pc,osx_gl'" + "Please rerun with commandline option: '--bundle_platforms=pc,mac'" # fmt:on # Test assets arranged in common lists: six (0-5) .txt files and .dat files @@ -717,16 +717,16 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): file_platforms = { "txtfile_0.txt": "pc", "txtfile_1.txt": "pc", - "txtfile_2.txt": "pc,osx_gl", - "txtfile_3.txt": "pc,osx_gl", - "txtfile_4.txt": "osx_gl", - "txtfile_5.txt": "osx_gl", + "txtfile_2.txt": "pc,mac", + "txtfile_3.txt": "pc,mac", + "txtfile_4.txt": "mac", + "txtfile_5.txt": "mac", "datfile_0.dat": "pc", "datfile_1.dat": "pc", - "datfile_2.dat": "pc,osx_gl", - "datfile_3.dat": "pc,osx_gl", - "datfile_4.dat": "osx_gl", - "datfile_5.dat": "osx_gl", + "datfile_2.dat": "pc,mac", + "datfile_3.dat": "pc,mac", + "datfile_4.dat": "mac", + "datfile_5.dat": "mac", } # Comparison rules files and their associated 'comparisonType' flags @@ -741,7 +741,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): # Get our test assets ready and processed utils.prepare_test_assets(env["tests_dir"], "C16877178", env["project_test_assets_dir"]) - asset_processor.batch_process(timeout=timeout, fastscan=False, platforms="pc,osx_gl") + asset_processor.batch_process(timeout=timeout, fastscan=False, platforms="pc,mac") # *** Some helper functions *** # @@ -759,7 +759,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): helper.call_assetLists( assetListFile=os.path.join(helper["test_dir"], asset_list_file_name), seedListFile=os.path.join(helper["test_dir"], seed_file_name), - platform="pc,osx_gl", + platform="pc,mac", ) def get_platform_assets(asset_name_list: List[str]) -> Dict[str, List[str]]: @@ -769,7 +769,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): for asset_name in asset_name_list: if "pc" in file_platforms[asset_name]: win_assets.append(asset_name) - if "osx_gl" in file_platforms[asset_name]: + if "mac" in file_platforms[asset_name]: mac_assets.append(asset_name) return {"win": win_assets, "mac": mac_assets} @@ -798,7 +798,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): # Get platform result file names win_asset_list_file = helper.platform_file_name(request_file, platforms["pc"]) - mac_asset_list_file = helper.platform_file_name(request_file, platforms["osx_gl"]) + mac_asset_list_file = helper.platform_file_name(request_file, platforms["mac"]) # Get expected platforms for each asset in asset_names platform_files = get_platform_assets(asset_names) @@ -879,14 +879,14 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): # fmt:on # End verify_asset_list_contents() - def run_compare_command_and_verify(platform_arg: str, expect_pc_output: bool, expect_osx_gl_output: bool) -> None: + def run_compare_command_and_verify(platform_arg: str, expect_pc_output: bool, expect_mac_output: bool) -> None: # Expected asset list to equal result of comparison expected_pc_asset_list = None - expected_osx_gl_asset_list = None + expected_mac_asset_list = None # Last output file. Use this for comparison to 'expected' output_pc_asset_list = None - output_osx_gl_asset_list = None + output_mac_asset_list = None # Add the platform to the file name to match what the Bundler will create last_output_arg = output_arg.split(",")[-1] @@ -895,10 +895,10 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): expected_pc_asset_list = os.path.join(helper["test_dir"], helper.platform_file_name(expected_asset_list, platform)) output_pc_asset_list = helper.platform_file_name(last_output_arg, platform) - if expect_osx_gl_output: - platform = platforms["osx_gl"] - expected_osx_gl_asset_list = os.path.join(helper["test_dir"], helper.platform_file_name(expected_asset_list, platform)) - output_osx_gl_asset_list = helper.platform_file_name(last_output_arg, platform) + if expect_mac_output: + platform = platforms["mac"] + expected_mac_asset_list = os.path.join(helper["test_dir"], helper.platform_file_name(expected_asset_list, platform)) + output_mac_asset_list = helper.platform_file_name(last_output_arg, platform) # Build execution command cmd = generate_compare_command(platform_arg) @@ -911,15 +911,15 @@ class TestsAssetBundlerBatch_WindowsAndMac(object): verify_asset_list_contents(expected_pc_asset_list, output_pc_asset_list) fs.delete([output_pc_asset_list], True, True) - if expect_osx_gl_output: - verify_asset_list_contents(expected_osx_gl_asset_list, output_osx_gl_asset_list) - fs.delete([output_osx_gl_asset_list], True, True) + if expect_mac_output: + verify_asset_list_contents(expected_mac_asset_list, output_mac_asset_list) + fs.delete([output_mac_asset_list], True, True) # End run_compare_command_and_verify() # Generate command, run and validate for each platform run_compare_command_and_verify("pc", True, False) - run_compare_command_and_verify("osx_gl", False, True) - run_compare_command_and_verify("pc,osx_gl", True, True) + run_compare_command_and_verify("mac", False, True) + run_compare_command_and_verify("pc,mac", True, True) #run_compare_command_and_verify(None, True, True) # End compare_and_check() diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests.py index 50b3af1438..0d830b39e2 100755 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests.py +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_processor_batch_tests.py @@ -102,7 +102,7 @@ class TestsAssetProcessorBatch_AllPlatforms(object): def test_RunAPBatch_TwoPlatforms_ExitCodeZero(self, asset_processor): asset_processor.create_temp_asset_root() asset_processor.enable_asset_processor_platform("pc") - asset_processor.enable_asset_processor_platform("osx_gl") + asset_processor.enable_asset_processor_platform("mac") result, _ = asset_processor.batch_process() assert result, "AP Batch failed" diff --git a/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt index e8f3349df4..834254134e 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/editor/CMakeLists.txt @@ -39,4 +39,19 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ COMPONENT Editor ) + + ly_add_pytest( + NAME AutomatedTesting::EditorTests_Sandbox + TEST_SUITE sandbox + TEST_SERIAL + PATH ${CMAKE_CURRENT_LIST_DIR} + PYTEST_MARKS "SUITE_sandbox" + TIMEOUT 1500 + RUNTIME_DEPENDENCIES + Legacy::Editor + AZ::AssetProcessor + AutomatedTesting.Assets + COMPONENT + Editor + ) endif() diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_Docking.py b/AutomatedTesting/Gem/PythonTests/editor/test_Docking.py index c2d515e250..f887560a19 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/test_Docking.py +++ b/AutomatedTesting/Gem/PythonTests/editor/test_Docking.py @@ -39,7 +39,7 @@ class TestDocking(object): file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True) @pytest.mark.test_case_id("C6376081") - @pytest.mark.SUITE_periodic + @pytest.mark.SUITE_sandbox def test_Docking_BasicDockedTools(self, request, editor, level, launcher_platform): expected_lines = [ "The tools are all docked together in a tabbed widget", diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_Menus.py b/AutomatedTesting/Gem/PythonTests/editor/test_Menus.py index 70a22f9e2a..c2da1343de 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/test_Menus.py +++ b/AutomatedTesting/Gem/PythonTests/editor/test_Menus.py @@ -39,7 +39,7 @@ class TestMenus(object): file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True) @pytest.mark.test_case_id("C16780783", "C2174438") - @pytest.mark.SUITE_periodic + @pytest.mark.SUITE_sandbox def test_Menus_EditMenuOptions_Work(self, request, editor, level, launcher_platform): expected_lines = [ "Undo Action triggered", @@ -113,7 +113,7 @@ class TestMenus(object): ) @pytest.mark.test_case_id("C16780778") - @pytest.mark.SUITE_periodic + @pytest.mark.SUITE_sandbox def test_Menus_FileMenuOptions_Work(self, request, editor, level, launcher_platform): expected_lines = [ "New Level Action triggered", diff --git a/AutomatedTesting/Levels/WaterSample/WaterSample.ly b/AutomatedTesting/Levels/WaterSample/WaterSample.ly deleted file mode 100644 index b1899f3710..0000000000 --- a/AutomatedTesting/Levels/WaterSample/WaterSample.ly +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d49aceca5ad4e0b9f46c8127afb5c53b68aa30272950b1abd66fba310977ff0c -size 15032 diff --git a/AutomatedTesting/Levels/WaterSample/filelist.xml b/AutomatedTesting/Levels/WaterSample/filelist.xml deleted file mode 100644 index d14b2fdaf2..0000000000 --- a/AutomatedTesting/Levels/WaterSample/filelist.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/AutomatedTesting/Levels/WaterSample/halfsphere.cgf b/AutomatedTesting/Levels/WaterSample/halfsphere.cgf deleted file mode 100644 index 4426d8a232..0000000000 --- a/AutomatedTesting/Levels/WaterSample/halfsphere.cgf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5f221acd847ec8a15e1333a5163d6d0fd886b8eda46fa7b133f76ddbf1d11216 -size 41472 diff --git a/AutomatedTesting/Levels/WaterSample/halfsphere2.cgf b/AutomatedTesting/Levels/WaterSample/halfsphere2.cgf deleted file mode 100644 index c776ff68b8..0000000000 --- a/AutomatedTesting/Levels/WaterSample/halfsphere2.cgf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c8e5dcfbe65fd2fd8ea29a38a96e703683c544fd42b9424857b1df3718c7775a -size 41472 diff --git a/AutomatedTesting/Levels/WaterSample/level.pak b/AutomatedTesting/Levels/WaterSample/level.pak deleted file mode 100644 index 1753ef4b93..0000000000 --- a/AutomatedTesting/Levels/WaterSample/level.pak +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0378911c27933302042550d5a031a5f9104296162edc2b21e44893f1b8cff969 -size 44124 diff --git a/AutomatedTesting/Levels/WaterSample/leveldata/Environment.xml b/AutomatedTesting/Levels/WaterSample/leveldata/Environment.xml deleted file mode 100644 index 6a95c631bb..0000000000 --- a/AutomatedTesting/Levels/WaterSample/leveldata/Environment.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Levels/WaterSample/leveldata/TerrainTexture.xml b/AutomatedTesting/Levels/WaterSample/leveldata/TerrainTexture.xml deleted file mode 100644 index 21741afe52..0000000000 --- a/AutomatedTesting/Levels/WaterSample/leveldata/TerrainTexture.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/AutomatedTesting/Levels/WaterSample/leveldata/TimeOfDay.xml b/AutomatedTesting/Levels/WaterSample/leveldata/TimeOfDay.xml deleted file mode 100644 index 60ad405904..0000000000 --- a/AutomatedTesting/Levels/WaterSample/leveldata/TimeOfDay.xml +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Levels/WaterSample/leveldata/VegetationMap.dat b/AutomatedTesting/Levels/WaterSample/leveldata/VegetationMap.dat deleted file mode 100644 index dce5631cd0..0000000000 --- a/AutomatedTesting/Levels/WaterSample/leveldata/VegetationMap.dat +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0e6a5435c928079b27796f6b202bbc2623e7e454244ddc099a3cadf33b7cb9e9 -size 63 diff --git a/AutomatedTesting/Levels/WaterSample/pool.cgf b/AutomatedTesting/Levels/WaterSample/pool.cgf deleted file mode 100644 index 04bec52a62..0000000000 --- a/AutomatedTesting/Levels/WaterSample/pool.cgf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:12ca8f1942331abde4d58724aea22609c8d7951cc415afa6e5f1c550a14e67b0 -size 363624 diff --git a/AutomatedTesting/Levels/WaterSample/pool2.cgf b/AutomatedTesting/Levels/WaterSample/pool2.cgf deleted file mode 100644 index 204306f8a8..0000000000 --- a/AutomatedTesting/Levels/WaterSample/pool2.cgf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f5b525a410730d84c0b3e97396d392e1e72f4b894742ddef3de4ede5542b0f8e -size 86148 diff --git a/AutomatedTesting/Levels/WaterSample/tags.txt b/AutomatedTesting/Levels/WaterSample/tags.txt deleted file mode 100644 index 0d6c1880e7..0000000000 --- a/AutomatedTesting/Levels/WaterSample/tags.txt +++ /dev/null @@ -1,12 +0,0 @@ -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 diff --git a/AutomatedTesting/Levels/WaterSample/terraintexture.pak b/AutomatedTesting/Levels/WaterSample/terraintexture.pak deleted file mode 100644 index fe3604a050..0000000000 --- a/AutomatedTesting/Levels/WaterSample/terraintexture.pak +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8739c76e681f900923b900c9df0ef75cf421d39cabb54650c4b9ad19b6a76d85 -size 22 diff --git a/AutomatedTesting/Levels/WaterSample/woodland_canyon_river.mtl b/AutomatedTesting/Levels/WaterSample/woodland_canyon_river.mtl deleted file mode 100644 index 4548bca421..0000000000 --- a/AutomatedTesting/Levels/WaterSample/woodland_canyon_river.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/AutomatedTesting/Objects/LumberTank/ProxyGray_ddna.tif.exportsettings b/AutomatedTesting/Objects/LumberTank/ProxyGray_ddna.tif.exportsettings index 013c774e9e..a4e1a9a3c5 100644 --- a/AutomatedTesting/Objects/LumberTank/ProxyGray_ddna.tif.exportsettings +++ b/AutomatedTesting/Objects/LumberTank/ProxyGray_ddna.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="es3:1,ios:1,osx_gl:0,pc:0,provo:0" \ No newline at end of file +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:0,pc:0,provo:0" \ No newline at end of file diff --git a/AutomatedTesting/preview.png b/AutomatedTesting/preview.png index 2191a0ebc2..3d4fe78063 100644 --- a/AutomatedTesting/preview.png +++ b/AutomatedTesting/preview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a18fae4040a22d2bb359a8ca642b97bb8f6468eeb52e2826b3b029bd8f1350b6 -size 5466 +oid sha256:40949893ed7009eeaa90b7ce6057cb6be9dfaf7b162e3c26ba9dadf985939d7d +size 2038 diff --git a/Code/CryEngine/CryCommon/ISystem.h b/Code/CryEngine/CryCommon/ISystem.h index f863804f3d..653776f55b 100644 --- a/Code/CryEngine/CryCommon/ISystem.h +++ b/Code/CryEngine/CryCommon/ISystem.h @@ -125,7 +125,7 @@ enum ESystemConfigPlatform { CONFIG_INVALID_PLATFORM = 0, CONFIG_PC = 1, - CONFIG_OSX_GL = 2, + CONFIG_MAC = 2, CONFIG_OSX_METAL = 3, CONFIG_ANDROID = 4, CONFIG_IOS = 5, diff --git a/Code/CryEngine/CryCommon/LyShine/IDraw2d.h b/Code/CryEngine/CryCommon/LyShine/IDraw2d.h index 16fdfceca3..76a71c9e24 100644 --- a/Code/CryEngine/CryCommon/LyShine/IDraw2d.h +++ b/Code/CryEngine/CryCommon/LyShine/IDraw2d.h @@ -11,7 +11,6 @@ */ #pragma once -#include #include #include #include @@ -84,7 +83,7 @@ public: // types //! If this is not passed then the defaults below are used struct TextOptions { - IFFont* font; //!< default is "default" + AZStd::string fontName; //!< default is "default" unsigned int effectIndex; //!< default is 0 AZ::Vector3 color; //!< default is (1,1,1) HAlign horizontalAlignment; //!< default is HAlign::Left diff --git a/Code/CryEngine/CrySystem/System.h b/Code/CryEngine/CrySystem/System.h index b91b1ba059..a258030f70 100644 --- a/Code/CryEngine/CrySystem/System.h +++ b/Code/CryEngine/CrySystem/System.h @@ -729,7 +729,7 @@ protected: // ------------------------------------------------------------- CCmdLine* m_pCmdLine; string m_currentLanguageAudio; - string m_systemConfigName; // computed from system_(hardwareplatform)_(assetsPlatform) - eg, system_android_es3.cfg or system_android_opengl.cfg or system_windows_pc.cfg + string m_systemConfigName; // computed from system_(hardwareplatform)_(assetsPlatform) - eg, system_android_android.cfg or system_windows_pc.cfg std::vector< std::pair > m_updateTimes; diff --git a/Code/Framework/AzCore/AzCore/Component/TransformBus.h b/Code/Framework/AzCore/AzCore/Component/TransformBus.h index be18593d54..b180e97332 100644 --- a/Code/Framework/AzCore/AzCore/Component/TransformBus.h +++ b/Code/Framework/AzCore/AzCore/Component/TransformBus.h @@ -172,78 +172,10 @@ namespace AZ //! Rotation modifiers //! @{ - //! @deprecated Use SetLocalRotation() - //! Sets the entity's rotation in the world. - //! The origin of the axes is the entity's position in world space. - //! @param eulerAnglesRadians A three-dimensional vector, containing Euler angles in radians, to rotate the entity by. - virtual void SetRotation([[maybe_unused]] const AZ::Vector3& eulerAnglesRadians) {} - - //! @deprecated Use SetLocalRotation() - //! Sets the entity's rotation around the world's X axis. - //! The origin of the axis is the entity's position in world space. - //! @param eulerAngleRadians The X coordinate Euler angle in radians to use for the entity's rotation. - virtual void SetRotationX([[maybe_unused]] float eulerAngleRadian) {} - - //! @deprecated Use SetLocalRotation() - //! Sets the entity's rotation around the world's Y axis. - //! The origin of the axis is the entity's position in world space. - //! @param eulerAngleRadians The Y coordinate Euler angle in radians to use for the entity's rotation. - virtual void SetRotationY([[maybe_unused]] float eulerAngleRadian) {} - - //! @deprecated Use SetLocalRotation() - //! Sets the entity's rotation around the world's Z axis. - //! The origin of the axis is the entity's position in world space. - //! @param eulerAngleRadians The Z coordinate Euler angle in radians to use for the entity's rotation. - virtual void SetRotationZ([[maybe_unused]] float eulerAngleRadian) {} - - //! @deprecated Use SetLocalRotationQuaternion() //! Sets the entity's rotation in the world in quaternion notation. //! The origin of the axes is the entity's position in world space. //! @param quaternion A quaternion that represents the rotation to use for the entity. - virtual void SetRotationQuaternion([[maybe_unused]] const AZ::Quaternion& quaternion) {} - - //! @deprecated Use RotateAroundLocalX() - //! Rotates the entity around the world's X axis. - //! The origin of the axis is the entity's position in world space. - //! @param eulerAngleRadians The Euler angle in radians by which to rotate the entity around the X axis. - virtual void RotateByX([[maybe_unused]] float eulerAngleRadian) {} - - //! @deprecated Use RotateAroundLocalY() - //! Rotates the entity around the world's Y axis. - //! The origin of the axis is the entity's position in world space. - //! @param eulerAngleRadians The Euler angle in radians by which to rotate the entity around the Y axis. - virtual void RotateByY([[maybe_unused]] float eulerAngleRadian) {} - - //! @deprecated Use RotateAroundLocalZ() - //! Rotates the entity around the world's Z axis. - //! The origin of the axis is the entity's position in world space. - //! @param eulerAngleRadians The Euler angle in radians by which to rotate the entity around the Z axis. - virtual void RotateByZ([[maybe_unused]] float eulerAngleRadian) {} - - //! @deprecated Use GetLocalRotation() - //! Gets the entity's rotation in the world in Euler angles rotation in radians. - //! @return A three-dimensional vector, containing Euler angles in radians, that represents the entity's rotation. - virtual AZ::Vector3 GetRotationEulerRadians() { return AZ::Vector3(FLT_MAX); } - - //! @deprecated Use GetLocalRotationQuaternion() - //! Gets the entity's rotation in the world in quaternion format. - //! @return A quaternion that represents the entity's rotation in world space. - virtual AZ::Quaternion GetRotationQuaternion() { return AZ::Quaternion::CreateZero(); } - - //! @deprecated Use GetLocalRotation() - //! Gets the entity's rotation around the world's X axis. - //! @return The Euler angle in radians by which the the entity is rotated around the X axis in world space. - virtual float GetRotationX() { return FLT_MAX; } - - //! @deprecated Use GetLocalRotation() - //! Gets the entity's rotation around the world's Y axis. - //! @return The Euler angle in radians by which the the entity is rotated around the Y axis in world space. - virtual float GetRotationY() { return FLT_MAX; } - - //! @deprecated Use GetLocalRotation() - //! Gets the entity's rotation around the world's Z axis. - //! @return The Euler angle in radians by which the the entity is rotated around the Z axis in world space. - virtual float GetRotationZ() { return FLT_MAX; } + virtual void SetWorldRotationQuaternion([[maybe_unused]] const AZ::Quaternion& quaternion) {} //! Get angles in radian for each principle axis around which the world transform is //! rotated in the order of z-axis and y-axis and then x-axis. diff --git a/Code/Framework/AzCore/AzCore/Math/Random.h b/Code/Framework/AzCore/AzCore/Math/Random.h index 8b28f6aaad..8b2763df50 100644 --- a/Code/Framework/AzCore/AzCore/Math/Random.h +++ b/Code/Framework/AzCore/AzCore/Math/Random.h @@ -126,17 +126,16 @@ namespace AZ m_offsets.fill(1); // Halton sequences start at index 1. m_increments.fill(1); // By default increment by 1 between each number. } - - //! Returns a Halton sequence in an array of N length - template - AZStd::array, N> GetHaltonSequence() + + //! Fills a provided container from begin to end with a Halton sequence. + //! Entries are expected to be, or implicitly converted to, AZStd::array. + template + void FillHaltonSequence(Iterator begin, Iterator end) { - AZStd::array, N> result; - AZStd::array indices = m_offsets; // Generator that returns the Halton number for all bases for a single entry. - auto f = [&] () + auto f = [&]() { AZStd::array item; for (auto d = 0; d < Dimensions; ++d) @@ -147,12 +146,20 @@ namespace AZ return item; }; - AZStd::generate(result.begin(), result.end(), f); + AZStd::generate(begin, end, f); + } + + //! Returns a Halton sequence in an array of N length. + template + AZStd::array, N> GetHaltonSequence() + { + AZStd::array, N> result; + FillHaltonSequence(result.begin(), result.end()); return result; } //! Sets the offsets per dimension to start generating a sequence from. - //! By default, there is no offset (offset of 0 corresponds to starting at index 1) + //! By default, there is no offset (offset of 0 corresponds to starting at index 1). void SetOffsets(AZStd::array offsets) { m_offsets = offsets; diff --git a/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp index 63aad1ecf4..c3f6357706 100644 --- a/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp +++ b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp @@ -19,7 +19,7 @@ namespace AZ { inline namespace PlatformDefaults { - static const char* PlatformNames[PlatformId::NumPlatformIds] = { PlatformPC, PlatformES3, PlatformIOS, PlatformOSX, PlatformProvo, PlatformSalem, PlatformJasper, PlatformServer, PlatformAll, PlatformAllClient }; + static const char* PlatformNames[PlatformId::NumPlatformIds] = { PlatformPC, PlatformAndroid, PlatformIOS, PlatformMac, PlatformProvo, PlatformSalem, PlatformJasper, PlatformServer, PlatformAll, PlatformAllClient }; const char* PlatformIdToPalFolder(AZ::PlatformId platform) { @@ -31,11 +31,11 @@ namespace AZ { case AZ::PC: return "PC"; - case AZ::ES3: + case AZ::ANDROID_ID: return "Android"; case AZ::IOS: return "iOS"; - case AZ::OSX: + case AZ::MAC: return "Mac"; case AZ::PROVO: return "Provo"; @@ -66,11 +66,11 @@ namespace AZ } else if (osPlatform == PlatformCodeNameMac) { - return PlatformOSX; + return PlatformMac; } else if (osPlatform == PlatformCodeNameAndroid) { - return PlatformES3; + return PlatformAndroid; } else if (osPlatform == PlatformCodeNameiOS) { @@ -207,13 +207,13 @@ namespace AZ platformCodes.emplace_back(PlatformCodeNameWindows); platformCodes.emplace_back(PlatformCodeNameLinux); break; - case PlatformId::ES3: + case PlatformId::ANDROID_ID: platformCodes.emplace_back(PlatformCodeNameAndroid); break; case PlatformId::IOS: platformCodes.emplace_back(PlatformCodeNameiOS); break; - case PlatformId::OSX: + case PlatformId::MAC: platformCodes.emplace_back(PlatformCodeNameMac); break; case PlatformId::PROVO: diff --git a/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h index 2d67c860cd..93477ebeb9 100644 --- a/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h +++ b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h @@ -27,9 +27,9 @@ namespace AZ inline namespace PlatformDefaults { constexpr char PlatformPC[] = "pc"; - constexpr char PlatformES3[] = "es3"; + constexpr char PlatformAndroid[] = "android"; constexpr char PlatformIOS[] = "ios"; - constexpr char PlatformOSX[] = "osx_gl"; + constexpr char PlatformMac[] = "mac"; constexpr char PlatformProvo[] = "provo"; constexpr char PlatformSalem[] = "salem"; constexpr char PlatformJasper[] = "jasper"; @@ -54,9 +54,9 @@ namespace AZ AZ_ENUM_WITH_UNDERLYING_TYPE(PlatformId, int, (Invalid, -1), PC, - ES3, + ANDROID_ID, IOS, - OSX, + MAC, PROVO, SALEM, JASPER, @@ -73,9 +73,9 @@ namespace AZ { Platform_NONE = 0x00, Platform_PC = 1 << PlatformId::PC, - Platform_ES3 = 1 << PlatformId::ES3, + Platform_ANDROID = 1 << PlatformId::ANDROID_ID, Platform_IOS = 1 << PlatformId::IOS, - Platform_OSX = 1 << PlatformId::OSX, + Platform_MAC = 1 << PlatformId::MAC, Platform_PROVO = 1 << PlatformId::PROVO, Platform_SALEM = 1 << PlatformId::SALEM, Platform_JASPER = 1 << PlatformId::JASPER, @@ -87,7 +87,7 @@ namespace AZ // A special platform that will always correspond to all non-server platforms, even if new ones are added Platform_ALL_CLIENT = 1ULL << 31, - AllNamedPlatforms = Platform_PC | Platform_ES3 | Platform_IOS | Platform_OSX | Platform_PROVO | Platform_SALEM | Platform_JASPER | Platform_SERVER, + AllNamedPlatforms = Platform_PC | Platform_ANDROID | Platform_IOS | Platform_MAC | Platform_PROVO | Platform_SALEM | Platform_JASPER | Platform_SERVER, }; AZ_DEFINE_ENUM_BITWISE_OPERATORS(PlatformFlags); diff --git a/Code/Framework/AzCore/AzCore/PlatformId/PlatformId.cpp b/Code/Framework/AzCore/AzCore/PlatformId/PlatformId.cpp index 0258869a0c..d56140be28 100644 --- a/Code/Framework/AzCore/AzCore/PlatformId/PlatformId.cpp +++ b/Code/Framework/AzCore/AzCore/PlatformId/PlatformId.cpp @@ -28,8 +28,8 @@ namespace AZ return "Android64"; case PlatformID::PLATFORM_APPLE_IOS: return "iOS"; - case PlatformID::PLATFORM_APPLE_OSX: - return "OSX"; + case PlatformID::PLATFORM_APPLE_MAC: + return "Mac"; #if defined(AZ_EXPAND_FOR_RESTRICTED_PLATFORM) || defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) #define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\ case PlatformID::PLATFORM_##PUBLICNAME:\ diff --git a/Code/Framework/AzCore/AzCore/PlatformId/PlatformId.h b/Code/Framework/AzCore/AzCore/PlatformId/PlatformId.h index ce1a11d8ce..e8e7cef6dd 100644 --- a/Code/Framework/AzCore/AzCore/PlatformId/PlatformId.h +++ b/Code/Framework/AzCore/AzCore/PlatformId/PlatformId.h @@ -23,7 +23,7 @@ namespace AZ PLATFORM_WINDOWS_64, PLATFORM_LINUX_64, PLATFORM_APPLE_IOS, - PLATFORM_APPLE_OSX, + PLATFORM_APPLE_MAC, PLATFORM_ANDROID_64, // ARMv8 / 64-bit #if defined(AZ_EXPAND_FOR_RESTRICTED_PLATFORM) || defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) #define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\ diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp index 015554538f..11d4db2e07 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp @@ -937,7 +937,7 @@ void ScriptSystemComponent::Reflect(ReflectContext* reflection) ->Enum(PlatformID::PLATFORM_LINUX_64)>("Linux") ->Enum(PlatformID::PLATFORM_ANDROID_64)>("Android64") ->Enum(PlatformID::PLATFORM_APPLE_IOS)>("iOS") - ->Enum(PlatformID::PLATFORM_APPLE_OSX)>("OSX") + ->Enum(PlatformID::PLATFORM_APPLE_MAC)>("Mac") #if defined(AZ_EXPAND_FOR_RESTRICTED_PLATFORM) || defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) #define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\ ->Enum(PlatformID::PLATFORM_##PUBLICNAME)>(#CodeName) diff --git a/Code/Framework/AzCore/Tests/Math/RandomTests.cpp b/Code/Framework/AzCore/Tests/Math/RandomTests.cpp index ace7d99704..7fe3acff54 100644 --- a/Code/Framework/AzCore/Tests/Math/RandomTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/RandomTests.cpp @@ -24,7 +24,7 @@ namespace UnitTest EXPECT_FLOAT_EQ(5981.0f / 15625.0f, GetHaltonNumber(4321, 5)); } - TEST(MATH_Random, HaltonSequence) + TEST(MATH_Random, HaltonSequenceStandard) { HaltonSequence<3> sequence({ 2, 3, 5 }); auto regularSequence = sequence.GetHaltonSequence<5>(); @@ -48,7 +48,11 @@ namespace UnitTest EXPECT_FLOAT_EQ(5.0f / 8.0f, regularSequence[4][0]); EXPECT_FLOAT_EQ(7.0f / 9.0f, regularSequence[4][1]); EXPECT_FLOAT_EQ(1.0f / 25.0f, regularSequence[4][2]); - + } + + TEST(MATH_Random, HaltonSequenceOffsets) + { + HaltonSequence<3> sequence({ 2, 3, 5 }); sequence.SetOffsets({ 1, 2, 3 }); auto offsetSequence = sequence.GetHaltonSequence<2>(); @@ -59,10 +63,15 @@ namespace UnitTest EXPECT_FLOAT_EQ(3.0f / 4.0f, offsetSequence[1][0]); EXPECT_FLOAT_EQ(4.0f / 9.0f, offsetSequence[1][1]); EXPECT_FLOAT_EQ(1.0f / 25.0f, offsetSequence[1][2]); - + } + + TEST(MATH_Random, HaltonSequenceIncrements) + { + HaltonSequence<3> sequence({ 2, 3, 5 }); + sequence.SetOffsets({ 1, 2, 3 }); sequence.SetIncrements({ 1, 2, 3 }); auto incrementedSequence = sequence.GetHaltonSequence<2>(); - + EXPECT_FLOAT_EQ(1.0f / 4.0f, incrementedSequence[0][0]); EXPECT_FLOAT_EQ(1.0f / 9.0f, incrementedSequence[0][1]); EXPECT_FLOAT_EQ(4.0f / 5.0f, incrementedSequence[0][2]); @@ -71,4 +80,35 @@ namespace UnitTest EXPECT_FLOAT_EQ(7.0f / 9.0f, incrementedSequence[1][1]); EXPECT_FLOAT_EQ(11.0f / 25.0f, incrementedSequence[1][2]); } + + TEST(MATH_Random, FillHaltonSequence) + { + HaltonSequence<3> sequence({ 2, 3, 5 }); + auto regularSequence = sequence.GetHaltonSequence<5>(); + + struct Point + { + Point() = default; + Point(AZStd::array arr) + :x(arr[0]) + ,y(arr[1]) + ,z(arr[2]) + {} + + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; + }; + + AZStd::array ownedContainer; + sequence.FillHaltonSequence(ownedContainer.begin(), ownedContainer.end()); + + for (size_t i = 0; i < regularSequence.size(); ++i) + { + EXPECT_FLOAT_EQ(regularSequence[i][0], ownedContainer[i].x); + EXPECT_FLOAT_EQ(regularSequence[i][1], ownedContainer[i].y); + EXPECT_FLOAT_EQ(regularSequence[i][2], ownedContainer[i].z); + } + } + } diff --git a/Code/Framework/AzCore/Tests/SettingsRegistryMergeUtilsTests.cpp b/Code/Framework/AzCore/Tests/SettingsRegistryMergeUtilsTests.cpp index 36b9757ce3..751d9ded6c 100644 --- a/Code/Framework/AzCore/Tests/SettingsRegistryMergeUtilsTests.cpp +++ b/Code/Framework/AzCore/Tests/SettingsRegistryMergeUtilsTests.cpp @@ -372,15 +372,15 @@ mac_remote_filesystem=0 -- We need to know this before we establish VFS because different platform assets -- are stored in different root folders in the cache. These correspond to the names -- In the asset processor config file. This value also controls what config file is read --- when you read system_xxxx_xxxx.cfg (for example, system_windows_pc.cfg or system_android_es3.cfg) +-- when you read system_xxxx_xxxx.cfg (for example, system_windows_pc.cfg or system_android_android.cfg) -- by default, pc assets (in the 'pc' folder) are used, with RC being fed 'pc' as the platform -- by default on console we use the default assets=pc for better iteration times -- we should turn on console specific assets only when in release and/or testing assets and/or loading performance -- that way most people will not need to have 3 different caches taking up disk space assets = pc -android_assets = es3 +android_assets = android ios_assets = ios -mac_assets = osx_gl +mac_assets = mac -- Add the IP address of your console to the white list that will connect to the asset processor here -- You can list addresses or CIDR's. CIDR's are helpful if you are using DHCP. A CIDR looks like an ip address with @@ -438,9 +438,9 @@ mac_wait_for_connect=0 ConfigFileParams::SettingsKeyValuePair{"/ios_remote_filesystem", AZ::s64{0}}, ConfigFileParams::SettingsKeyValuePair{"/mac_remote_filesystem", AZ::s64{0}}, ConfigFileParams::SettingsKeyValuePair{"/assets", AZStd::string_view{"pc"}}, - ConfigFileParams::SettingsKeyValuePair{"/android_assets", AZStd::string_view{"es3"}}, + ConfigFileParams::SettingsKeyValuePair{"/android_assets", AZStd::string_view{"android"}}, ConfigFileParams::SettingsKeyValuePair{"/ios_assets", AZStd::string_view{"ios"}}, - ConfigFileParams::SettingsKeyValuePair{"/mac_assets", AZStd::string_view{"osx_gl"}}, + ConfigFileParams::SettingsKeyValuePair{"/mac_assets", AZStd::string_view{"mac"}}, ConfigFileParams::SettingsKeyValuePair{"/connect_to_remote", AZ::s64{0}}, ConfigFileParams::SettingsKeyValuePair{"/windows_connect_to_remote", AZ::s64{1}}, ConfigFileParams::SettingsKeyValuePair{"/android_connect_to_remote", AZ::s64{0}}, @@ -478,20 +478,20 @@ test_asset_processor_tag = test_value [Platform pc] tags=tools,renderer,dx12,vulkan -[Platform es3] +[Platform android] tags=android,mobile,renderer,vulkan ; With Comments at the end [Platform ios] tags=mobile,renderer,metal -[Platform osx_gl] +[Platform mac] tags=tools,renderer,metal)" , AZStd::fixed_vector{ ConfigFileParams::SettingsKeyValuePair{"/test_asset_processor_tag", AZStd::string_view{"test_value"}}, ConfigFileParams::SettingsKeyValuePair{"/Platform pc/tags", AZStd::string_view{"tools,renderer,dx12,vulkan"}}, - ConfigFileParams::SettingsKeyValuePair{"/Platform es3/tags", AZStd::string_view{"android,mobile,renderer,vulkan"}}, + ConfigFileParams::SettingsKeyValuePair{"/Platform android/tags", AZStd::string_view{"android,mobile,renderer,vulkan"}}, ConfigFileParams::SettingsKeyValuePair{"/Platform ios/tags", AZStd::string_view{"mobile,renderer,metal"}}, - ConfigFileParams::SettingsKeyValuePair{"/Platform osx_gl/tags", AZStd::string_view{"tools,renderer,metal"}}, + ConfigFileParams::SettingsKeyValuePair{"/Platform mac/tags", AZStd::string_view{"tools,renderer,metal"}}, }} ) ); diff --git a/Code/Framework/AzFramework/AzFramework/Asset/AssetProcessorMessages.cpp b/Code/Framework/AzFramework/AzFramework/Asset/AssetProcessorMessages.cpp index 020feffc47..7280c4af5c 100644 --- a/Code/Framework/AzFramework/AzFramework/Asset/AssetProcessorMessages.cpp +++ b/Code/Framework/AzFramework/AzFramework/Asset/AssetProcessorMessages.cpp @@ -308,6 +308,56 @@ namespace AzFramework } } + //--------------------------------------------------------------------- + GenerateRelativeSourcePathRequest::GenerateRelativeSourcePathRequest(const AZ::OSString& sourcePath) + { + AZ_Assert(!sourcePath.empty(), "GenerateRelativeSourcePathRequest: asset path is empty"); + m_sourcePath = sourcePath; + } + + unsigned int GenerateRelativeSourcePathRequest::GetMessageType() const + { + return MessageType; + } + + void GenerateRelativeSourcePathRequest::Reflect(AZ::ReflectContext* context) + { + auto serialize = azrtti_cast(context); + if (serialize) + { + serialize->Class() + ->Version(1) + ->Field("SourcePath", &GenerateRelativeSourcePathRequest::m_sourcePath); + } + } + + //--------------------------------------------------------------------- + GenerateRelativeSourcePathResponse::GenerateRelativeSourcePathResponse( + bool resolved, const AZ::OSString& relativeSourcePath, const AZ::OSString& rootFolder) + { + m_relativeSourcePath = relativeSourcePath; + m_resolved = resolved; + m_rootFolder = rootFolder; + } + + unsigned int GenerateRelativeSourcePathResponse::GetMessageType() const + { + return GenerateRelativeSourcePathRequest::MessageType; + } + + void GenerateRelativeSourcePathResponse::Reflect(AZ::ReflectContext* context) + { + auto serialize = azrtti_cast(context); + if (serialize) + { + serialize->Class() + ->Version(1) + ->Field("RelativeSourcePath", &GenerateRelativeSourcePathResponse::m_relativeSourcePath) + ->Field("RootFolder", &GenerateRelativeSourcePathResponse::m_rootFolder) + ->Field("Resolved", &GenerateRelativeSourcePathResponse::m_resolved); + } + } + //--------------------------------------------------------------------- GetFullSourcePathFromRelativeProductPathRequest::GetFullSourcePathFromRelativeProductPathRequest(const AZ::OSString& relativeProductPath) { diff --git a/Code/Framework/AzFramework/AzFramework/Asset/AssetProcessorMessages.h b/Code/Framework/AzFramework/AzFramework/Asset/AssetProcessorMessages.h index 9661e61828..c15f75e3e7 100644 --- a/Code/Framework/AzFramework/AzFramework/Asset/AssetProcessorMessages.h +++ b/Code/Framework/AzFramework/AzFramework/Asset/AssetProcessorMessages.h @@ -288,6 +288,45 @@ namespace AzFramework bool m_resolved; }; + ////////////////////////////////////////////////////////////////////////// + class GenerateRelativeSourcePathRequest : public BaseAssetProcessorMessage + { + public: + AZ_CLASS_ALLOCATOR(GenerateRelativeSourcePathRequest, AZ::OSAllocator, 0); + AZ_RTTI(GenerateRelativeSourcePathRequest, "{B3865033-F5A3-4749-8147-7B1AB04D5F6D}", + BaseAssetProcessorMessage); + static void Reflect(AZ::ReflectContext* context); + + // For people that are debugging the network messages and just see MessageType as a value, + // the CRC value below is 739777771 (0x2C181CEB) + static constexpr unsigned int MessageType = + AZ_CRC_CE("AssetSystem::GenerateRelativeSourcePathRequest"); + + GenerateRelativeSourcePathRequest() = default; + GenerateRelativeSourcePathRequest(const AZ::OSString& sourcePath); + unsigned int GetMessageType() const override; + + AZ::OSString m_sourcePath; + }; + + class GenerateRelativeSourcePathResponse : public BaseAssetProcessorMessage + { + public: + AZ_CLASS_ALLOCATOR(GenerateRelativeSourcePathResponse, AZ::OSAllocator, 0); + AZ_RTTI(GenerateRelativeSourcePathResponse, "{938D33DB-C8F6-4FA4-BC81-2F139A9BE1D7}", + BaseAssetProcessorMessage); + static void Reflect(AZ::ReflectContext* context); + + GenerateRelativeSourcePathResponse() = default; + GenerateRelativeSourcePathResponse( + bool resolved, const AZ::OSString& relativeSourcePath, const AZ::OSString& rootFolder); + unsigned int GetMessageType() const override; + + AZ::OSString m_relativeSourcePath; + AZ::OSString m_rootFolder; ///< This is the folder it was found in (the watched/scanned folder, such as gems /assets/ folder) + bool m_resolved; + }; + ////////////////////////////////////////////////////////////////////////// class GetFullSourcePathFromRelativeProductPathRequest : public BaseAssetProcessorMessage diff --git a/Code/Framework/AzFramework/AzFramework/Asset/AssetSystemComponent.cpp b/Code/Framework/AzFramework/AzFramework/Asset/AssetSystemComponent.cpp index 83c4907468..6b19084c2a 100644 --- a/Code/Framework/AzFramework/AzFramework/Asset/AssetSystemComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Asset/AssetSystemComponent.cpp @@ -202,6 +202,7 @@ namespace AzFramework // Requests GetUnresolvedDependencyCountsRequest::Reflect(context); GetRelativeProductPathFromFullSourceOrProductPathRequest::Reflect(context); + GenerateRelativeSourcePathRequest::Reflect(context); GetFullSourcePathFromRelativeProductPathRequest::Reflect(context); SourceAssetInfoRequest::Reflect(context); AssetInfoRequest::Reflect(context); @@ -234,6 +235,7 @@ namespace AzFramework // Responses GetUnresolvedDependencyCountsResponse::Reflect(context); GetRelativeProductPathFromFullSourceOrProductPathResponse::Reflect(context); + GenerateRelativeSourcePathResponse::Reflect(context); GetFullSourcePathFromRelativeProductPathResponse::Reflect(context); SourceAssetInfoResponse::Reflect(context); AssetInfoResponse::Reflect(context); diff --git a/Code/Framework/AzFramework/AzFramework/Components/ComponentAdapter.h b/Code/Framework/AzFramework/AzFramework/Components/ComponentAdapter.h index 682e886061..ee8b79bf06 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/ComponentAdapter.h +++ b/Code/Framework/AzFramework/AzFramework/Components/ComponentAdapter.h @@ -1,22 +1,22 @@ /* -* 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. -* -*/ + * 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 #include +#include namespace AzFramework { @@ -64,15 +64,13 @@ namespace AzFramework the EditContext. TController can friend itself to the editor component to make this work if required. */ template - class ComponentAdapter - : public AZ::Component + class ComponentAdapter : public AZ::Component { public: - AZ_RTTI((ComponentAdapter, "{644A9187-4FDB-42C1-9D59-DD75304B551A}", TController, TConfiguration), AZ::Component); ComponentAdapter() = default; - ComponentAdapter(const TConfiguration& configuration); + explicit ComponentAdapter(const TConfiguration& configuration); static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services); static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services); @@ -85,7 +83,6 @@ namespace AzFramework void Deactivate() override; protected: - static void Reflect(AZ::ReflectContext* context); // AZ::Component overrides ... diff --git a/Code/Framework/AzFramework/AzFramework/Components/ComponentAdapter.inl b/Code/Framework/AzFramework/AzFramework/Components/ComponentAdapter.inl index a1b0826193..5c36ff0bf7 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/ComponentAdapter.inl +++ b/Code/Framework/AzFramework/AzFramework/Components/ComponentAdapter.inl @@ -1,14 +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. -* -*/ + * 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 @@ -32,10 +32,12 @@ namespace AzFramework if (auto serializeContext = azrtti_cast(context)) { + // clang-format off serializeContext->Class() ->Version(1) ->Field("Controller", &ComponentAdapter::m_controller) ; + // clang-format on } } @@ -66,9 +68,6 @@ namespace AzFramework GetDependentServicesHelper(services, typename AZ::HasComponentDependentServices::type()); } - ////////////////////////////////////////////////////////////////////////// - // AZ::Component interface implementation - template void ComponentAdapter::Init() { @@ -78,7 +77,7 @@ namespace AzFramework template void ComponentAdapter::Activate() { - m_controller.Activate(GetEntityId()); + ComponentActivateHelper::Activate(m_controller, AZ::EntityComponentIdPair(GetEntityId(), GetId())); } template diff --git a/Code/Framework/AzFramework/AzFramework/Components/ComponentAdapterHelpers.h b/Code/Framework/AzFramework/AzFramework/Components/ComponentAdapterHelpers.h index 158ee95f39..f0ef262a71 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/ComponentAdapterHelpers.h +++ b/Code/Framework/AzFramework/AzFramework/Components/ComponentAdapterHelpers.h @@ -13,6 +13,7 @@ #pragma once #include +#include namespace AzFramework { @@ -27,18 +28,43 @@ namespace AzFramework template struct ComponentInitHelper { - static void Init(T& common) + static void Init([[maybe_unused]] T& controller) { - AZ_UNUSED(common); } }; template struct ComponentInitHelper().Init())>> { - static void Init(T& common) + static void Init(T& controller) { - common.Init(); + controller.Init(); + } + }; + + template + struct ComponentActivateHelper + { + static void Activate([[maybe_unused]] T& controller, [[maybe_unused]] const AZ::EntityComponentIdPair& entityComponentIdPair) + { + } + }; + + template + struct ComponentActivateHelper().Activate(AZ::EntityId()))>> + { + static void Activate(T& controller, const AZ::EntityComponentIdPair& entityComponentIdPair) + { + controller.Activate(entityComponentIdPair.GetEntityId()); + } + }; + + template + struct ComponentActivateHelper().Activate(AZ::EntityComponentIdPair()))>> + { + static void Activate(T& controller, const AZ::EntityComponentIdPair& entityComponentIdPair) + { + controller.Activate(entityComponentIdPair); } }; diff --git a/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.cpp b/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.cpp index 3dafc7c717..49adab2252 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.cpp @@ -327,99 +327,13 @@ namespace AzFramework return localZ; } - void TransformComponent::SetRotation(const AZ::Vector3& eulerAnglesRadian) + void TransformComponent::SetWorldRotationQuaternion(const AZ::Quaternion& quaternion) { - AZ_Warning("TransformComponent", false, "SetRotation is deprecated, please use SetLocalRotation"); - - AZ::Transform newWorldTransform = m_worldTM; - newWorldTransform.SetRotation(AZ::ConvertEulerRadiansToQuaternion(eulerAnglesRadian)); - SetWorldTM(newWorldTransform); - } - - void TransformComponent::SetRotationQuaternion(const AZ::Quaternion& quaternion) - { - AZ_Warning("TransformComponent", false, "SetRotationQuaternion is deprecated, please use SetLocalRotationQuaternion"); - AZ::Transform newWorldTransform = m_worldTM; newWorldTransform.SetRotation(quaternion); SetWorldTM(newWorldTransform); } - void TransformComponent::SetRotationX(float eulerAngleRadian) - { - AZ_Warning("TransformComponent", false, "SetRotationX is deprecated, please use SetLocalRotation"); - - AZ::Transform newWorldTransform = m_worldTM; - newWorldTransform.SetRotation(AZ::Quaternion::CreateRotationX(eulerAngleRadian)); - SetWorldTM(newWorldTransform); - } - - void TransformComponent::SetRotationY(float eulerAngleRadian) - { - AZ_Warning("TransformComponent", false, "SetRotationY is deprecated, please use SetLocalRotation"); - - AZ::Transform newWorldTransform = m_worldTM; - newWorldTransform.SetRotation(AZ::Quaternion::CreateRotationY(eulerAngleRadian)); - SetWorldTM(newWorldTransform); - } - - void TransformComponent::SetRotationZ(float eulerAngleRadian) - { - AZ_Warning("TransformComponent", false, "SetRotationZ is deprecated, please use SetLocalRotation"); - - AZ::Transform newWorldTransform = m_worldTM; - newWorldTransform.SetRotation(AZ::Quaternion::CreateRotationZ(eulerAngleRadian)); - SetWorldTM(newWorldTransform); - } - - void TransformComponent::RotateByX(float eulerAngleRadian) - { - AZ_Warning("TransformComponent", false, "RotateByX is deprecated, please use RotateAroundLocalX"); - RotateAroundLocalX(eulerAngleRadian); - } - - void TransformComponent::RotateByY(float eulerAngleRadian) - { - AZ_Warning("TransformComponent", false, "RotateByY is deprecated, please use RotateAroundLocalY"); - RotateAroundLocalY(eulerAngleRadian); - } - - void TransformComponent::RotateByZ(float eulerAngleRadian) - { - AZ_Warning("TransformComponent", false, "RotateByZ is deprecated, please use RotateAroundLocalZ"); - RotateAroundLocalZ(eulerAngleRadian); - } - - AZ::Vector3 TransformComponent::GetRotationEulerRadians() - { - AZ_Warning("TransformComponent", false, "GetRotationEulerRadians is deprecated, please use GetWorldRotation"); - return m_worldTM.GetRotation().GetEulerRadians(); - } - - AZ::Quaternion TransformComponent::GetRotationQuaternion() - { - AZ_Warning("TransformComponent", false, "GetRotationQuaternion is deprecated, please use GetWorldRotationQuaternion"); - return m_worldTM.GetRotation(); - } - - float TransformComponent::GetRotationX() - { - AZ_Warning("TransformComponent", false, "GetRotationX is deprecated, please use GetWorldRotation"); - return GetRotationEulerRadians().GetX(); - } - - float TransformComponent::GetRotationY() - { - AZ_Warning("TransformComponent", false, "GetRotationY is deprecated, please use GetWorldRotation"); - return GetRotationEulerRadians().GetY(); - } - - float TransformComponent::GetRotationZ() - { - AZ_Warning("TransformComponent", false, "GetRotationZ is deprecated, please use GetWorldRotation"); - return GetRotationEulerRadians().GetZ(); - } - AZ::Vector3 TransformComponent::GetWorldRotation() { return m_worldTM.GetRotation().GetEulerRadians(); @@ -830,45 +744,7 @@ namespace AzFramework ->Event("GetLocalX", &AZ::TransformBus::Events::GetLocalX) ->Event("GetLocalY", &AZ::TransformBus::Events::GetLocalY) ->Event("GetLocalZ", &AZ::TransformBus::Events::GetLocalZ) - ->Event("RotateByX", &AZ::TransformBus::Events::RotateByX) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("RotateByY", &AZ::TransformBus::Events::RotateByY) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("RotateByZ", &AZ::TransformBus::Events::RotateByZ) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("SetEulerRotation", &AZ::TransformBus::Events::SetRotation) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("SetRotationQuaternion", &AZ::TransformBus::Events::SetRotationQuaternion) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("SetRotationX", &AZ::TransformBus::Events::SetRotationX) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("SetRotationY", &AZ::TransformBus::Events::SetRotationY) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("SetRotationZ", &AZ::TransformBus::Events::SetRotationZ) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("GetEulerRotation", &AZ::TransformBus::Events::GetRotationEulerRadians) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("GetRotationQuaternion", &AZ::TransformBus::Events::GetRotationQuaternion) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("GetRotationX", &AZ::TransformBus::Events::GetRotationX) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("GetRotationY", &AZ::TransformBus::Events::GetRotationY) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("GetRotationZ", &AZ::TransformBus::Events::GetRotationZ) - ->Attribute(AZ::Script::Attributes::Deprecated, true) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) + ->Event("SetWorldRotationQuaternion", &AZ::TransformBus::Events::SetWorldRotationQuaternion) ->Event("GetWorldRotation", &AZ::TransformBus::Events::GetWorldRotation) ->Event("GetWorldRotationQuaternion", &AZ::TransformBus::Events::GetWorldRotationQuaternion) ->Event("SetLocalRotation", &AZ::TransformBus::Events::SetLocalRotation) diff --git a/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.h b/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.h index e3a647d39f..9009c6bff9 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.h +++ b/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.h @@ -112,22 +112,7 @@ namespace AzFramework float GetLocalZ() override; // Rotation modifiers - void SetRotation(const AZ::Vector3& eulerAnglesRadian) override; - void SetRotationQuaternion(const AZ::Quaternion& quaternion) override; - void SetRotationX(float eulerAngleRadian) override; - void SetRotationY(float eulerAngleRadian) override; - void SetRotationZ(float eulerAngleRadian) override; - - void RotateByX(float eulerAngleRadian) override; - void RotateByY(float eulerAngleRadian) override; - void RotateByZ(float eulerAngleRadian) override; - - AZ::Vector3 GetRotationEulerRadians() override; - AZ::Quaternion GetRotationQuaternion() override; - - float GetRotationX() override; - float GetRotationY() override; - float GetRotationZ() override; + void SetWorldRotationQuaternion(const AZ::Quaternion& quaternion) override; AZ::Vector3 GetWorldRotation() override; AZ::Quaternion GetWorldRotationQuaternion() override; diff --git a/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h b/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h index b64b61e22c..04a0572bb9 100644 --- a/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h +++ b/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -42,11 +43,15 @@ namespace AzFramework { ViewportId m_drawViewportId = InvalidViewportId; //!< Viewport to draw into AZ::Vector3 m_position; //!< world space position for 3d draws, screen space x,y,depth for 2d. - AZ::Color m_color = AZ::Colors::White; //!< Color to draw the text + AZ::Color m_color = AZ::Colors::White; //!< Color to draw the text + unsigned int m_effectIndex = 0; //!< effect index to apply AZ::Vector2 m_scale = AZ::Vector2(1.0f); //!< font scale - float m_lineSpacing; //!< Spacing between new lines, as a percentage of m_scale. + float m_textSizeFactor = 12.0f; //!< font size in pixels + float m_lineSpacing = 1.0f; //!< Spacing between new lines, as a percentage of m_scale. TextHorizontalAlignment m_hAlign = TextHorizontalAlignment::Left; //!< Horizontal text alignment TextVerticalAlignment m_vAlign = TextVerticalAlignment::Top; //!< Vertical text alignment + bool m_useTransform = false; //!< Use specified transform + AZ::Matrix3x4 m_transform = AZ::Matrix3x4::Identity(); //!< Transform to apply to text quads bool m_monospace = false; //!< disable character proportional spacing bool m_depthTest = false; //!< Test character against the depth buffer bool m_virtual800x600ScreenSize = true; //!< Text placement and size are scaled relative to a virtual 800x600 resolution diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/Spawnable.h b/Code/Framework/AzFramework/AzFramework/Spawnable/Spawnable.h index 5e507b3498..79cea647e4 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/Spawnable.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/Spawnable.h @@ -19,10 +19,13 @@ #include #include -namespace AzFramework +namespace AZ { class ReflectContext; +} +namespace AzFramework +{ class Spawnable final : public AZ::Data::AssetData { diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp index a528797f63..97169ebeb3 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp @@ -14,6 +14,10 @@ namespace AzFramework { + // + // SpawnableEntityContainerView + // + SpawnableEntityContainerView::SpawnableEntityContainerView(AZ::Entity** begin, size_t length) : m_begin(begin) , m_end(begin + length) @@ -52,6 +56,9 @@ namespace AzFramework } + // + // SpawnableConstEntityContainerView + // SpawnableConstEntityContainerView::SpawnableConstEntityContainerView(AZ::Entity** begin, size_t length) : m_begin(begin) @@ -91,6 +98,136 @@ namespace AzFramework } + // + // SpawnableIndexEntityPair + // + + SpawnableIndexEntityPair::SpawnableIndexEntityPair(AZ::Entity** entityIterator, size_t* indexIterator) + : m_entity(entityIterator) + , m_index(indexIterator) + { + } + + AZ::Entity* SpawnableIndexEntityPair::GetEntity() + { + return *m_entity; + } + + const AZ::Entity* SpawnableIndexEntityPair::GetEntity() const + { + return *m_entity; + } + + size_t SpawnableIndexEntityPair::GetIndex() const + { + return *m_index; + } + + // + // SpawnableIndexEntityIterator + // + + SpawnableIndexEntityIterator::SpawnableIndexEntityIterator(AZ::Entity** entityIterator, size_t* indexIterator) + : m_value(entityIterator, indexIterator) + { + } + + SpawnableIndexEntityIterator& SpawnableIndexEntityIterator::operator++() + { + ++m_value.m_entity; + ++m_value.m_index; + return *this; + } + + SpawnableIndexEntityIterator SpawnableIndexEntityIterator::operator++(int) + { + SpawnableIndexEntityIterator result = *this; + ++m_value.m_entity; + ++m_value.m_index; + return result; + } + + SpawnableIndexEntityIterator& SpawnableIndexEntityIterator::operator--() + { + --m_value.m_entity; + --m_value.m_index; + return *this; + } + + SpawnableIndexEntityIterator SpawnableIndexEntityIterator::operator--(int) + { + SpawnableIndexEntityIterator result = *this; + --m_value.m_entity; + --m_value.m_index; + return result; + } + + bool SpawnableIndexEntityIterator::operator==(const SpawnableIndexEntityIterator& rhs) + { + return m_value.m_entity == rhs.m_value.m_entity && m_value.m_index == rhs.m_value.m_index; + } + + bool SpawnableIndexEntityIterator::operator!=(const SpawnableIndexEntityIterator& rhs) + { + return m_value.m_entity != rhs.m_value.m_entity || m_value.m_index != rhs.m_value.m_index; + } + + SpawnableIndexEntityPair& SpawnableIndexEntityIterator::operator*() + { + return m_value; + } + + const SpawnableIndexEntityPair& SpawnableIndexEntityIterator::operator*() const + { + return m_value; + } + + SpawnableIndexEntityPair* SpawnableIndexEntityIterator::operator->() + { + return &m_value; + } + + const SpawnableIndexEntityPair* SpawnableIndexEntityIterator::operator->() const + { + return &m_value; + } + + + // + // SpawnableConstIndexEntityContainerView + // + + SpawnableConstIndexEntityContainerView::SpawnableConstIndexEntityContainerView( + AZ::Entity** beginEntity, size_t* beginIndices, size_t length) + : m_begin(beginEntity, beginIndices) + , m_end(beginEntity + length, beginIndices + length) + { + } + + const SpawnableIndexEntityIterator& SpawnableConstIndexEntityContainerView::begin() + { + return m_begin; + } + + const SpawnableIndexEntityIterator& SpawnableConstIndexEntityContainerView::end() + { + return m_end; + } + + const SpawnableIndexEntityIterator& SpawnableConstIndexEntityContainerView::cbegin() + { + return m_begin; + } + + const SpawnableIndexEntityIterator& SpawnableConstIndexEntityContainerView::cend() + { + return m_end; + } + + + // + // EntitySpawnTicket + // EntitySpawnTicket::EntitySpawnTicket(EntitySpawnTicket&& rhs) : m_payload(rhs.m_payload) diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h index ac66288ff2..69bca8e111 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h @@ -58,6 +58,72 @@ namespace AzFramework AZ::Entity** m_end; }; + class SpawnableIndexEntityPair + { + public: + friend class SpawnableIndexEntityIterator; + + AZ::Entity* GetEntity(); + const AZ::Entity* GetEntity() const; + size_t GetIndex() const; + + private: + SpawnableIndexEntityPair() = default; + SpawnableIndexEntityPair(const SpawnableIndexEntityPair&) = default; + SpawnableIndexEntityPair(SpawnableIndexEntityPair&&) = default; + SpawnableIndexEntityPair(AZ::Entity** entityIterator, size_t* indexIterator); + + SpawnableIndexEntityPair& operator=(const SpawnableIndexEntityPair&) = default; + SpawnableIndexEntityPair& operator=(SpawnableIndexEntityPair&&) = default; + + AZ::Entity** m_entity { nullptr }; + size_t* m_index { nullptr }; + }; + + class SpawnableIndexEntityIterator + { + public: + // Limited to bidirectional iterator as there's no use case for extending it further, but can be extended if a use case is found. + using iterator_category = AZStd::bidirectional_iterator_tag; + using value_type = SpawnableIndexEntityPair; + using difference_type = size_t; + using pointer = SpawnableIndexEntityPair*; + using reference = SpawnableIndexEntityPair&; + + SpawnableIndexEntityIterator(AZ::Entity** entityIterator, size_t* indexIterator); + + SpawnableIndexEntityIterator& operator++(); + SpawnableIndexEntityIterator operator++(int); + SpawnableIndexEntityIterator& operator--(); + SpawnableIndexEntityIterator operator--(int); + + bool operator==(const SpawnableIndexEntityIterator& rhs); + bool operator!=(const SpawnableIndexEntityIterator& rhs); + + SpawnableIndexEntityPair& operator*(); + const SpawnableIndexEntityPair& operator*() const; + SpawnableIndexEntityPair* operator->(); + const SpawnableIndexEntityPair* operator->() const; + + private: + SpawnableIndexEntityPair m_value; + }; + + class SpawnableConstIndexEntityContainerView + { + public: + SpawnableConstIndexEntityContainerView(AZ::Entity** beginEntity, size_t* beginIndices, size_t length); + + const SpawnableIndexEntityIterator& begin(); + const SpawnableIndexEntityIterator& end(); + const SpawnableIndexEntityIterator& cbegin(); + const SpawnableIndexEntityIterator& cend(); + + private: + SpawnableIndexEntityIterator m_begin; + SpawnableIndexEntityIterator m_end; + }; + //! Requests to the SpawnableEntitiesInterface require a ticket with a valid spawnable that be used as a template. A ticket can //! be reused for multiple calls on the same spawnable and is safe to use by multiple threads at the same time. Entities created //! from the spawnable may be tracked by the ticket and so using the same ticket is needed to despawn the exact entities created @@ -88,6 +154,7 @@ namespace AzFramework using EntityDespawnCallback = AZStd::function; using ReloadSpawnableCallback = AZStd::function; using ListEntitiesCallback = AZStd::function; + using ListIndicesEntitiesCallback = AZStd::function; using ClaimEntitiesCallback = AZStd::function; using BarrierCallback = AZStd::function; @@ -140,6 +207,15 @@ namespace AzFramework //! @param ticket Only the entities associated with this ticket will be listed. //! @param listCallback Required callback that will be called to list the entities on. virtual void ListEntities(EntitySpawnTicket& ticket, ListEntitiesCallback listCallback) = 0; + //! List all entities that are spawned using this ticket with their spawnable index. + //! Spawnables contain a flat list of entities, which are used as templates to spawn entities from. For every spawned entity + //! the index of the entity in the spawnable that was used as a template is stored. This version of ListEntities will return + //! both the entities and this index. The index can be used with SpawnEntities to create the same entities again. Note that + //! the same index may appear multiple times as there are no restriction on how many instance of a specific entity can be + //! created. + //! @param ticket Only the entities associated with this ticket will be listed. + //! @param listCallback Required callback that will be called to list the entities and indices on. + virtual void ListIndicesAndEntities(EntitySpawnTicket& ticket, ListIndicesEntitiesCallback listCallback) = 0; //! Claim all entities that are spawned using this ticket. Ownership of the entities is transferred from the ticket to the //! caller through the callback. After this call the ticket will have no entities associated with it. The caller of //! this function will need to manage the entities after this call. diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp index 8045766686..7e20f7b265 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp @@ -25,6 +25,8 @@ namespace AzFramework void SpawnableEntitiesManager::SpawnAllEntities(EntitySpawnTicket& ticket, EntityPreInsertionCallback preInsertionCallback, EntitySpawnCallback completionCallback) { + AZ_Assert(ticket.IsValid(), "Ticket provided to SpawnAllEntities hasn't been initialized."); + SpawnAllEntitiesCommand queueEntry; queueEntry.m_ticket = &ticket; queueEntry.m_completionCallback = AZStd::move(completionCallback); @@ -40,6 +42,8 @@ namespace AzFramework EntitySpawnTicket& ticket, AZStd::vector entityIndices, EntityPreInsertionCallback preInsertionCallback, EntitySpawnCallback completionCallback) { + AZ_Assert(ticket.IsValid(), "Ticket provided to SpawnEntities hasn't been initialized."); + SpawnEntitiesCommand queueEntry; queueEntry.m_ticket = &ticket; queueEntry.m_entityIndices = AZStd::move(entityIndices); @@ -54,6 +58,8 @@ namespace AzFramework void SpawnableEntitiesManager::DespawnAllEntities(EntitySpawnTicket& ticket, EntityDespawnCallback completionCallback) { + AZ_Assert(ticket.IsValid(), "Ticket provided to DespawnAllEntities hasn't been initialized."); + DespawnAllEntitiesCommand queueEntry; queueEntry.m_ticket = &ticket; queueEntry.m_completionCallback = AZStd::move(completionCallback); @@ -67,6 +73,8 @@ namespace AzFramework void SpawnableEntitiesManager::ReloadSpawnable(EntitySpawnTicket& ticket, AZ::Data::Asset spawnable, ReloadSpawnableCallback completionCallback) { + AZ_Assert(ticket.IsValid(), "Ticket provided to ReloadSpawnable hasn't been initialized."); + ReloadSpawnableCommand queueEntry; queueEntry.m_ticket = &ticket; queueEntry.m_spawnable = AZStd::move(spawnable); @@ -81,6 +89,7 @@ namespace AzFramework void SpawnableEntitiesManager::ListEntities(EntitySpawnTicket& ticket, ListEntitiesCallback listCallback) { AZ_Assert(listCallback, "ListEntities called on spawnable entities without a valid callback to use."); + AZ_Assert(ticket.IsValid(), "Ticket provided to ListEntities hasn't been initialized."); ListEntitiesCommand queueEntry; queueEntry.m_ticket = &ticket; @@ -92,9 +101,25 @@ namespace AzFramework } } + void SpawnableEntitiesManager::ListIndicesAndEntities(EntitySpawnTicket& ticket, ListIndicesEntitiesCallback listCallback) + { + AZ_Assert(listCallback, "ListEntities called on spawnable entities without a valid callback to use."); + AZ_Assert(ticket.IsValid(), "Ticket provided to ListEntities hasn't been initialized."); + + ListIndicesEntitiesCommand queueEntry; + queueEntry.m_ticket = &ticket; + queueEntry.m_listCallback = AZStd::move(listCallback); + { + AZStd::scoped_lock queueLock(m_pendingRequestQueueMutex); + queueEntry.m_ticketId = GetTicketPayload(ticket).m_nextTicketId++; + m_pendingRequestQueue.push(AZStd::move(queueEntry)); + } + } + void SpawnableEntitiesManager::ClaimEntities(EntitySpawnTicket& ticket, ClaimEntitiesCallback listCallback) { AZ_Assert(listCallback, "ClaimEntities called on spawnable entities without a valid callback to use."); + AZ_Assert(ticket.IsValid(), "Ticket provided to ClaimEntities hasn't been initialized."); ClaimEntitiesCommand queueEntry; queueEntry.m_ticket = &ticket; @@ -109,6 +134,7 @@ namespace AzFramework void SpawnableEntitiesManager::Barrier(EntitySpawnTicket& ticket, BarrierCallback completionCallback) { AZ_Assert(completionCallback, "Barrier on spawnable entities called without a valid callback to use."); + AZ_Assert(ticket.IsValid(), "Ticket provided to Barrier hasn't been initialized."); BarrierCommand queueEntry; queueEntry.m_ticket = &ticket; @@ -499,6 +525,27 @@ namespace AzFramework } } + bool SpawnableEntitiesManager::ProcessRequest(ListIndicesEntitiesCommand& request, [[maybe_unused]] AZ::SerializeContext& serializeContext) + { + Ticket& ticket = GetTicketPayload(*request.m_ticket); + if (request.m_ticketId == ticket.m_currentTicketId) + { + AZ_Assert( + ticket.m_spawnedEntities.size() == ticket.m_spawnedEntityIndices.size(), + "Entities and indices on spawnable ticket have gone out of sync."); + request.m_listCallback( + *request.m_ticket, + SpawnableConstIndexEntityContainerView( + ticket.m_spawnedEntities.begin(), ticket.m_spawnedEntityIndices.begin(), ticket.m_spawnedEntities.size())); + ticket.m_currentTicketId++; + return true; + } + else + { + return false; + } + } + bool SpawnableEntitiesManager::ProcessRequest(ClaimEntitiesCommand& request, [[maybe_unused]] AZ::SerializeContext& serializeContext) { Ticket& ticket = GetTicketPayload(*request.m_ticket); diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h index e20f58ac76..3481ab180a 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h @@ -36,6 +36,7 @@ namespace AzFramework { public: AZ_RTTI(AzFramework::SpawnableEntitiesManager, "{6E14333F-128C-464C-94CA-A63B05A5E51C}"); + AZ_CLASS_ALLOCATOR(SpawnableEntitiesManager, AZ::SystemAllocator, 0); enum class CommandQueueStatus : bool { @@ -58,6 +59,7 @@ namespace AzFramework ReloadSpawnableCallback completionCallback = {}) override; void ListEntities(EntitySpawnTicket& ticket, ListEntitiesCallback listCallback) override; + void ListIndicesAndEntities(EntitySpawnTicket& ticket, ListIndicesEntitiesCallback listCallback) override; void ClaimEntities(EntitySpawnTicket& ticket, ClaimEntitiesCallback listCallback) override; void Barrier(EntitySpawnTicket& spawnInfo, BarrierCallback completionCallback) override; @@ -123,6 +125,12 @@ namespace AzFramework EntitySpawnTicket* m_ticket; uint32_t m_ticketId; }; + struct ListIndicesEntitiesCommand + { + ListIndicesEntitiesCallback m_listCallback; + EntitySpawnTicket* m_ticket; + uint32_t m_ticketId; + }; struct ClaimEntitiesCommand { ClaimEntitiesCallback m_listCallback; @@ -141,8 +149,9 @@ namespace AzFramework uint32_t m_ticketId; }; - using Requests = AZStd::variant; + using Requests = AZStd::variant< + SpawnAllEntitiesCommand, SpawnEntitiesCommand, DespawnAllEntitiesCommand, ReloadSpawnableCommand, ListEntitiesCommand, + ListIndicesEntitiesCommand, ClaimEntitiesCommand, BarrierCommand, DestroyTicketCommand>; AZ::Entity* SpawnSingleEntity(const AZ::Entity& entityTemplate, AZ::SerializeContext& serializeContext); @@ -155,6 +164,7 @@ namespace AzFramework bool ProcessRequest(DespawnAllEntitiesCommand& request, AZ::SerializeContext& serializeContext); bool ProcessRequest(ReloadSpawnableCommand& request, AZ::SerializeContext& serializeContext); bool ProcessRequest(ListEntitiesCommand& request, AZ::SerializeContext& serializeContext); + bool ProcessRequest(ListIndicesEntitiesCommand& request, AZ::SerializeContext& serializeContext); bool ProcessRequest(ClaimEntitiesCommand& request, AZ::SerializeContext& serializeContext); bool ProcessRequest(BarrierCommand& request, AZ::SerializeContext& serializeContext); bool ProcessRequest(DestroyTicketCommand& request, AZ::SerializeContext& serializeContext); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorAssetSystemAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorAssetSystemAPI.h index 98e4c6b5eb..715de30bfa 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorAssetSystemAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorAssetSystemAPI.h @@ -60,10 +60,20 @@ namespace AzToolsFramework //! and is generally checked into source control. virtual const char* GetAbsoluteDevRootFolderPath() = 0; - /// Convert a full source path like "c:\\dev\gamename\\blah\\test.tga" into a relative product path. + /// Convert a full source path like "c:\\dev\\gamename\\blah\\test.tga" into a relative product path. /// asset paths never mention their alias and are relative to the asset cache root virtual bool GetRelativeProductPathFromFullSourceOrProductPath(const AZStd::string& fullPath, AZStd::string& relativeProductPath) = 0; + /** Convert a source path like "c:\\dev\\gamename\\blah\\test.tga" into a relative source path, like "blah/test.tga". + * If no valid relative path could be created, the input source path will be returned in relativePath. + * @param sourcePath partial or full path to a source file. (The file doesn't need to exist) + * @param relativePath the output relative path for the source file, if a valid one could be created + * @param rootFilePath the root path that relativePath is relative to + * @return true if a valid relative path was created, false if it wasn't + */ + virtual bool GenerateRelativeSourcePath( + const AZStd::string& sourcePath, AZStd::string& relativePath, AZStd::string& rootFilePath) = 0; + /// Convert a relative asset path like "blah/test.tga" to a full source path path. /// Once the asset processor has finished building, this function is capable of handling even when the extension changes /// or when the source is in a different folder or in a different location (such as inside gems) @@ -110,14 +120,14 @@ namespace AzToolsFramework /** * Query to see if a specific asset platform is enabled - * @param platform the asset platform to check e.g. es3, ios, etc. + * @param platform the asset platform to check e.g. android, ios, etc. * @return true if enabled, false otherwise */ virtual bool IsAssetPlatformEnabled(const char* platform) = 0; /** * Get the total number of pending assets left to process for a specific asset platform - * @param platform the asset platform to check e.g. es3, ios, etc. + * @param platform the asset platform to check e.g. android, ios, etc. * @return -1 if the process fails, a positive number otherwise */ virtual int GetPendingAssetsForPlatform(const char* platform) = 0; @@ -302,7 +312,7 @@ namespace AzToolsFramework inline const char* GetHostAssetPlatform() { #if defined(AZ_PLATFORM_MAC) - return "osx_gl"; + return "mac"; #elif defined(AZ_PLATFORM_WINDOWS) return "pc"; #elif defined(AZ_PLATFORM_LINUX) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorViewportIconDisplayInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorViewportIconDisplayInterface.h new file mode 100644 index 0000000000..a2264b5058 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorViewportIconDisplayInterface.h @@ -0,0 +1,80 @@ +/* +* 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 AzToolsFramework +{ + //! An interface for loading simple icon assets and rendering them to screen on a per-viewport basis. + class EditorViewportIconDisplayInterface + { + public: + AZ_RTTI(EditorViewportIconDisplayInterface, "{D5190B58-2561-4F3F-B793-F1E7D454CDF2}"); + + using IconId = AZ::s32; + static constexpr IconId InvalidIconId = -1; + + enum class CoordinateSpace : AZ::u8 + { + ScreenSpace, + WorldSpace + }; + + //! These draw parameters control rendering for a single icon to a single viewport. + struct DrawParameters + { + //! The ViewportId to render to. + AzFramework::ViewportId m_viewport = AzFramework::InvalidViewportId; + //! The icon ID, retrieved from GetOrLoadIconForPath, to render to screen. + IconId m_icon = InvalidIconId; + //! The color, including opacity, to render the icon with. White will render the icon as opaque in its original color. + AZ::Color m_color = AZ::Colors::White; + //! The position to render the icon to, in world or screen space depending on m_positionSpace. + AZ::Vector3 m_position; + //! The coordinate system to use for m_position. + //! ScreenSpace will accept m_position in the form of [X, Y, Depth], where X & Y are screen coordinates in + //! pixels and Depth is a z-ordering depth value from 0.0f to 1.0f. + //! WorldSpace will accept a 3D vector in world space coordinates that will be translated back into screen + //! space when the icon is rendered. + CoordinateSpace m_positionSpace = CoordinateSpace::ScreenSpace; + //! The size to render the icon as, in pixels. + AZ::Vector2 m_size; + }; + + //! The current load status of an icon retrieved by GetOrLoadIconForPath. + enum class IconLoadStatus : AZ::u8 + { + Unloaded, + Loading, + Loaded, + Error + }; + + //! Draws an icon to a viewport given a set of draw parameters. + //! Requires an IconId retrieved from GetOrLoadIconForPath. + virtual void DrawIcon(const DrawParameters& drawParameters) = 0; + //! Retrieves a reusable IconId for an icon at a given path. + //! This will load the icon, if it has not already been loaded. + //! @param path should be a relative asset path to an icon image asset. + //! png and svg icons are currently supported. + virtual IconId GetOrLoadIconForPath(AZStd::string_view path) = 0; + //! Gets the current load status of an icon retrieved via GetOrLoadIconForPath. + virtual IconLoadStatus GetIconLoadStatus(IconId icon) = 0; + }; + + using EditorViewportIconDisplay = AZ::Interface; +} //namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h index 82fa3f94f5..72150b1b57 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h @@ -239,6 +239,11 @@ namespace AzToolsFramework */ virtual int RemoveDirtyEntity(AZ::EntityId target) = 0; + /*! + * Clears the dirty entity set. + */ + virtual void ClearDirtyEntities() = 0; + /*! * \return true if an undo/redo operation is in progress. */ diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp index e77704c920..88057787bb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp @@ -1354,6 +1354,11 @@ namespace AzToolsFramework return static_cast(m_dirtyEntities.erase(entityId)); } + void ToolsApplication::ClearDirtyEntities() + { + m_dirtyEntities.clear(); + } + void ToolsApplication::UndoPressed() { if (m_undoStack) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h index 6c836ac888..bafced67bd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h @@ -85,6 +85,7 @@ namespace AzToolsFramework void AddDirtyEntity(AZ::EntityId entityId) override; int RemoveDirtyEntity(AZ::EntityId entityId) override; + void ClearDirtyEntities() override; bool IsDuringUndoRedo() override { return m_isDuringUndoRedo; } void UndoPressed() override; void RedoPressed() override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetSystemComponent.cpp index 5529829913..4966d9cce9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetSystemComponent.cpp @@ -265,6 +265,30 @@ namespace AzToolsFramework return response.m_resolved; } + bool AssetSystemComponent::GenerateRelativeSourcePath( + const AZStd::string& sourcePath, AZStd::string& relativePath, AZStd::string& rootFilePath) + { + AzFramework::SocketConnection* engineConnection = AzFramework::SocketConnection::GetInstance(); + if (!engineConnection || !engineConnection->IsConnected()) + { + relativePath = sourcePath; + return false; + } + + AzFramework::AssetSystem::GenerateRelativeSourcePathRequest request(sourcePath); + AzFramework::AssetSystem::GenerateRelativeSourcePathResponse response; + if (!SendRequest(request, response)) + { + AZ_Error("Editor", false, "Failed to send GenerateRelativeSourcePath request for %s", sourcePath.c_str()); + relativePath = sourcePath; + return false; + } + + relativePath = response.m_relativeSourcePath; + rootFilePath = response.m_rootFolder; + return response.m_resolved; + } + bool AssetSystemComponent::GetFullSourcePathFromRelativeProductPath(const AZStd::string& relPath, AZStd::string& fullPath) { auto foundIt = m_assetSourceRelativePathToFullPathCache.find(relPath); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetSystemComponent.h index 399ee1ac9d..9d839c60f5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetSystemComponent.h @@ -63,6 +63,8 @@ namespace AzToolsFramework const char* GetAbsoluteDevGameFolderPath() override; const char* GetAbsoluteDevRootFolderPath() override; bool GetRelativeProductPathFromFullSourceOrProductPath(const AZStd::string& fullPath, AZStd::string& outputPath) override; + bool GenerateRelativeSourcePath( + const AZStd::string& sourcePath, AZStd::string& outputPath, AZStd::string& watchFolder) override; bool GetFullSourcePathFromRelativeProductPath(const AZStd::string& relPath, AZStd::string& fullPath) override; bool GetAssetInfoById(const AZ::Data::AssetId& assetId, const AZ::Data::AssetType& assetType, const AZStd::string& platformName, AZ::Data::AssetInfo& assetInfo, AZStd::string& rootFilePath) override; bool GetSourceInfoBySourcePath(const char* sourcePath, AZ::Data::AssetInfo& assetInfo, AZStd::string& watchFolder) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h index 8412361657..a26c3b0ecf 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h @@ -56,5 +56,7 @@ namespace AzToolsFramework virtual void StartPlayInEditor() = 0; virtual void StopPlayInEditor() = 0; + + virtual void CreateNewLevelPrefab(AZStd::string_view filename) = 0; }; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index 97c3041de6..b2b36cc318 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -225,50 +225,19 @@ namespace AzToolsFramework m_rootInstance->SetTemplateSourcePath(relativePath); - bool newLevelFromTemplate = false; - if (templateId == AzToolsFramework::Prefab::InvalidTemplateId) { - AZStd::string watchFolder; - AZ::Data::AssetInfo assetInfo; - bool sourceInfoFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult( - sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, DefaultLevelTemplateName, - assetInfo, watchFolder); + m_rootInstance->m_containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent()); + HandleEntitiesAdded({ m_rootInstance->m_containerEntity.get() }); - if (sourceInfoFound) + AzToolsFramework::Prefab::PrefabDom dom; + bool success = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*m_rootInstance, dom); + if (!success) { - AZStd::string fullPath; - AZ::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), fullPath); - - // Get the default prefab and copy the Dom over to the new template being saved - Prefab::TemplateId defaultId = m_loaderInterface->LoadTemplateFromFile(fullPath.c_str()); - Prefab::PrefabDom& dom = m_prefabSystemComponent->FindTemplateDom(defaultId); - - Prefab::PrefabDom levelDefaultDom; - levelDefaultDom.CopyFrom(dom, levelDefaultDom.GetAllocator()); - - Prefab::PrefabDomPath sourcePath("/Source"); - sourcePath.Set(levelDefaultDom, relativePath.c_str()); - - templateId = m_prefabSystemComponent->AddTemplate(relativePath, std::move(levelDefaultDom)); - newLevelFromTemplate = true; - } - else - { - // Create an empty level since we couldn't find the default template - m_rootInstance->m_containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent()); - HandleEntitiesAdded({ m_rootInstance->m_containerEntity.get() }); - - AzToolsFramework::Prefab::PrefabDom dom; - bool success = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*m_rootInstance, dom); - if (!success) - { - AZ_Error("Prefab", false, "Failed to convert current root instance into a DOM when saving file '%.*s'", AZ_STRING_ARG(filename)); - return false; - } - templateId = m_prefabSystemComponent->AddTemplate(relativePath, std::move(dom)); + AZ_Error("Prefab", false, "Failed to convert current root instance into a DOM when saving file '%.*s'", AZ_STRING_ARG(filename)); + return false; } + templateId = m_prefabSystemComponent->AddTemplate(relativePath, AZStd::move(dom)); if (templateId == AzToolsFramework::Prefab::InvalidTemplateId) { @@ -286,13 +255,6 @@ namespace AzToolsFramework m_prefabSystemComponent->RemoveTemplate(prevTemplateId); } - // If we have a new level from a template, we need to make sure to propagate the changes here otherwise - // the entities from the new template won't show up - if (newLevelFromTemplate) - { - m_prefabSystemComponent->PropagateTemplateChanges(templateId); - } - AZStd::string out; if (m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out)) { @@ -303,6 +265,71 @@ namespace AzToolsFramework return false; } + void PrefabEditorEntityOwnershipService::CreateNewLevelPrefab(AZStd::string_view filename) + { + AZ::IO::Path relativePath = m_loaderInterface->GetRelativePathToProject(filename); + AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath); + + m_rootInstance->SetTemplateSourcePath(relativePath); + + AZStd::string watchFolder; + AZ::Data::AssetInfo assetInfo; + bool sourceInfoFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult( + sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, DefaultLevelTemplateName, + assetInfo, watchFolder); + + if (sourceInfoFound) + { + AZStd::string fullPath; + AZ::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), fullPath); + + // Get the default prefab and copy the Dom over to the new template being saved + Prefab::TemplateId defaultId = m_loaderInterface->LoadTemplateFromFile(fullPath.c_str()); + Prefab::PrefabDom& dom = m_prefabSystemComponent->FindTemplateDom(defaultId); + + Prefab::PrefabDom levelDefaultDom; + levelDefaultDom.CopyFrom(dom, levelDefaultDom.GetAllocator()); + + Prefab::PrefabDomPath sourcePath("/Source"); + sourcePath.Set(levelDefaultDom, assetInfo.m_relativePath.c_str()); + + templateId = m_prefabSystemComponent->AddTemplate(relativePath, AZStd::move(levelDefaultDom)); + } + else + { + m_rootInstance->m_containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent()); + HandleEntitiesAdded({ m_rootInstance->m_containerEntity.get() }); + + AzToolsFramework::Prefab::PrefabDom dom; + bool success = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*m_rootInstance, dom); + if (!success) + { + AZ_Error( + "Prefab", false, "Failed to convert current root instance into a DOM when saving file '%.*s'", AZ_STRING_ARG(filename)); + return; + } + templateId = m_prefabSystemComponent->AddTemplate(relativePath, std::move(dom)); + } + + if (templateId == AzToolsFramework::Prefab::InvalidTemplateId) + { + AZ_Error("Prefab", false, "Couldn't create new template id '%i' when creating new level '%.*s'", templateId, AZ_STRING_ARG(filename)); + return; + } + + Prefab::TemplateId prevTemplateId = m_rootInstance->GetTemplateId(); + m_rootInstance->SetTemplateId(templateId); + + if (prevTemplateId != Prefab::InvalidTemplateId && templateId != prevTemplateId) + { + // Make sure we only have one level template loaded at a time + m_prefabSystemComponent->RemoveTemplate(prevTemplateId); + } + + m_prefabSystemComponent->PropagateTemplateChanges(templateId); + } + Prefab::InstanceOptionalReference PrefabEditorEntityOwnershipService::CreatePrefab( const AZStd::vector& entities, AZStd::vector>&& nestedPrefabInstances, AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h index 606d5f495f..915cafd316 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h @@ -170,6 +170,8 @@ namespace AzToolsFramework void StartPlayInEditor() override; void StopPlayInEditor() override; + void CreateNewLevelPrefab(AZStd::string_view filename) override; + protected: AZ::SliceComponent::SliceInstanceAddress GetOwningSlice() override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/SliceEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/SliceEditorEntityOwnershipService.cpp index 906ea98357..14dcf5e55d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/SliceEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/SliceEditorEntityOwnershipService.cpp @@ -614,7 +614,7 @@ namespace AzToolsFramework AZ::Quaternion oldEntityRotation; AZ::TransformBus::EventResult(oldEntityRotation, id, &AZ::TransformBus::Events::GetWorldRotationQuaternion); - transformComponent->SetRotationQuaternion(oldEntityRotation); + transformComponent->SetWorldRotationQuaternion(oldEntityRotation); // Ensure the existing hierarchy is maintained AZ::EntityId oldParentEntityId; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.cpp index a21c5301aa..6d3ddedd51 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.cpp @@ -276,18 +276,14 @@ namespace AzToolsFramework PrefabDomValueReference linkPatchesReference = PrefabDomUtils::FindPrefabDomValue(linkDom, PrefabDomUtils::PatchesName); - // This logic only covers addition of patches. If patches already exists, the given list of patches must be appended to them. - if (!linkPatchesReference.has_value()) - { - /* - If the original allocator the patches were created with gets destroyed, then the patches would become garbage in the - linkDom. Since we cannot guarantee the lifecycle of the patch allocators, we are doing a copy of the patches here to - associate them with the linkDom's allocator. - */ - PrefabDom patchesCopy; - patchesCopy.CopyFrom(patches, linkDom.GetAllocator()); - linkDom.AddMember(rapidjson::StringRef(PrefabDomUtils::PatchesName), patchesCopy, linkDom.GetAllocator()); - } + /* + If the original allocator the patches were created with gets destroyed, then the patches would become garbage in the + linkDom. Since we cannot guarantee the lifecycle of the patch allocators, we are doing a copy of the patches here to + associate them with the linkDom's allocator. + */ + PrefabDom patchesCopy; + patchesCopy.CopyFrom(patches, linkDom.GetAllocator()); + linkDom.AddMember(rapidjson::StringRef(PrefabDomUtils::PatchesName), patchesCopy, linkDom.GetAllocator()); } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.cpp index 308749ab28..2fb22ea8e8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.cpp @@ -234,5 +234,10 @@ namespace AzToolsFramework } } + PrefabDomValueReference Link::GetLinkPatches() + { + return PrefabDomUtils::FindPrefabDomValue(m_linkDom, PrefabDomUtils::PatchesName); + } + } // namespace Prefab } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.h index 073e619f20..c8f43b291e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Link/Link.h @@ -79,6 +79,8 @@ namespace AzToolsFramework */ void AddLinkIdToInstanceDom(PrefabDomValue& instanceDomValue); + PrefabDomValueReference GetLinkPatches(); + private: /** diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 579f465eb2..0181050a32 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -10,8 +10,6 @@ * */ -#include - #include #include #include @@ -28,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -98,9 +97,13 @@ namespace AzToolsFramework AZStd::string("Could not create a new prefab out of the entities provided - invalid selection.")); } + AZStd::unordered_map oldEntityAliases; + // Detach the retrieved entities for (AZ::Entity* entity : entities) { + AZ::EntityId entityId = entity->GetId(); + oldEntityAliases.emplace(entityId, commonRootEntityOwningInstance->get().GetEntityAlias(entityId)->get()); commonRootEntityOwningInstance->get().DetachEntity(entity->GetId()).release(); } @@ -110,15 +113,18 @@ namespace AzToolsFramework { AZStd::unique_ptr outInstance = commonRootEntityOwningInstance->get().DetachNestedInstance(nestedInstance->GetInstanceAlias()); - auto linkRef = m_prefabSystemComponentInterface->FindLink(nestedInstance->GetLinkId()); + LinkId detachingInstanceLinkId = nestedInstance->GetLinkId(); + auto linkRef = m_prefabSystemComponentInterface->FindLink(detachingInstanceLinkId); + AZ_Assert(linkRef.has_value(), "Unable to find link with id '%llu' during prefab creation.", detachingInstanceLinkId); - if (linkRef.has_value()) - { - PrefabDom oldLinkPatches; - oldLinkPatches.CopyFrom(linkRef->get().GetLinkDom(), oldLinkPatches.GetAllocator()); + PrefabDomValueReference linkPatches = linkRef->get().GetLinkPatches(); + AZ_Assert( + linkPatches.has_value(), "Unable to get patches on link with id '%llu' during prefab creation.", + detachingInstanceLinkId); - nestedInstanceLinkPatchesMap.emplace(nestedInstance, AZStd::move(oldLinkPatches)); - } + PrefabDom linkPatchesCopy; + linkPatchesCopy.CopyFrom(linkPatches->get(), linkPatchesCopy.GetAllocator()); + nestedInstanceLinkPatchesMap.emplace(nestedInstance, AZStd::move(linkPatchesCopy)); RemoveLink(outInstance, commonRootEntityOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch()); @@ -182,6 +188,24 @@ namespace AzToolsFramework if (nestedInstanceLinkPatchesMap.contains(nestedInstance.get())) { previousPatch = AZStd::move(nestedInstanceLinkPatchesMap[nestedInstance.get()]); + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + previousPatch.Accept(writer); + QString previousPatchString(buffer.GetString()); + + for (AZ::Entity* entity : entities) + { + AZ::EntityId entityId = entity->GetId(); + AZStd::string oldEntityAlias = oldEntityAliases[entityId]; + EntityAliasOptionalReference newEntityAlias = instanceToCreate->get().GetEntityAlias(entityId); + AZ_Assert( + newEntityAlias.has_value(), + "Could not fetch entity alias for entity with id '%llu' during prefab creation.", + static_cast(entityId)); + ReplaceOldAliases(previousPatchString, oldEntityAlias, newEntityAlias->get()); + } + + previousPatch.Parse(previousPatchString.toUtf8().constData()); } // These link creations shouldn't be undone because that would put the template in a non-usable state if a user @@ -203,36 +227,23 @@ namespace AzToolsFramework m_instanceToTemplateInterface->GeneratePatch(reparentPatch, containerEntityDomBefore, containerEntityDomAfter); m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(reparentPatch, nestedInstanceContainerEntityId); - // Update the cache - this prevents these changes from being stored in the regular undo/redo nodes as a separate step - m_prefabUndoCache.Store(nestedInstanceContainerEntityId, AZStd::move(containerEntityDomAfter)); - - // Save these changes as patches to the link - PrefabUndoLinkUpdate* linkUpdate = aznew PrefabUndoLinkUpdate(AZStd::to_string(static_cast(nestedInstanceContainerEntityId))); - linkUpdate->SetParent(undoBatch.GetUndoBatch()); - linkUpdate->Capture(reparentPatch, nestedInstance->GetLinkId()); - - linkUpdate->Redo(); + // We won't parent this undo node to the undo batch so that the newly created template and link will remain + // unaffected by undo actions. This is needed so that any future instantiations of the template will work. + PrefabUndoLinkUpdate linkUpdate = PrefabUndoLinkUpdate(AZStd::to_string(static_cast(nestedInstanceContainerEntityId))); + linkUpdate.Capture(reparentPatch, nestedInstance->GetLinkId()); + linkUpdate.Redo(); } }); - + // Create a link between the templates of the newly created instance and the instance it's being parented under. CreateLink( instanceToCreate->get(), commonRootEntityOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch(), AZStd::move(patch)); - for (AZ::Entity* topLevelEntity : topLevelEntities) - { - AZ::EntityId topLevelEntityId = topLevelEntity->GetId(); - if (topLevelEntityId.IsValid()) - { - m_prefabUndoCache.UpdateCache(topLevelEntity->GetId()); - - // Parenting entities would mark entities as dirty. But we want to unmark the top level entities as dirty because - // if we don't, the template created would be updated and cause issues with undo operation followed by instantiation. - ToolsApplicationRequests::Bus::Broadcast( - &ToolsApplicationRequests::Bus::Events::RemoveDirtyEntity, topLevelEntity->GetId()); - } - } + // This clears any entities marked as dirty due to reparenting of entities during the process of creating a prefab. + // We are doing this so that the changes in those enities are not queued up twice for propagation. + AzToolsFramework::ToolsApplicationRequestBus::Broadcast( + &AzToolsFramework::ToolsApplicationRequestBus::Events::ClearDirtyEntities); // Select Container Entity { @@ -824,15 +835,7 @@ namespace AzToolsFramework // This will cover both cases where an alias could be used in a normal entity vs. an instance for (auto aliasMapIter : oldAliasToNewAliasMap) { - QString oldAliasQuotes = QString("\"%1\"").arg(aliasMapIter.first.c_str()); - QString newAliasQuotes = QString("\"%1\"").arg(aliasMapIter.second.c_str()); - - newEntityDomString.replace(oldAliasQuotes, newAliasQuotes); - - QString oldAliasPathRef = QString("/%1").arg(aliasMapIter.first.c_str()); - QString newAliasPathRef = QString("/%1").arg(aliasMapIter.second.c_str()); - - newEntityDomString.replace(oldAliasPathRef, newAliasPathRef); + ReplaceOldAliases(newEntityDomString, aliasMapIter.first, aliasMapIter.second); } // Create the new Entity DOM from parsing the JSON string @@ -1233,5 +1236,18 @@ namespace AzToolsFramework return true; } + + void PrefabPublicHandler::ReplaceOldAliases(QString& stringToReplace, AZStd::string_view oldAlias, AZStd::string_view newAlias) + { + QString oldAliasQuotes = QString("\"%1\"").arg(oldAlias.data()); + QString newAliasQuotes = QString("\"%1\"").arg(newAlias.data()); + + stringToReplace.replace(oldAliasQuotes, newAliasQuotes); + + QString oldAliasPathRef = QString("/%1").arg(oldAlias.data()); + QString newAliasPathRef = QString("/%1").arg(newAlias.data()); + + stringToReplace.replace(oldAliasPathRef, newAliasPathRef); + } } // namespace Prefab } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h index 223a725c6c..7e2357dd44 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h @@ -14,12 +14,15 @@ #include #include +#include #include #include #include #include +class QString; + namespace AzToolsFramework { using EntityList = AZStd::vector; @@ -27,7 +30,6 @@ namespace AzToolsFramework namespace Prefab { class Instance; - class InstanceEntityMapperInterface; class InstanceToTemplateInterface; class PrefabLoaderInterface; @@ -130,6 +132,8 @@ namespace AzToolsFramework bool IsCyclicalDependencyFound( InstanceOptionalConstReference instance, const AZStd::unordered_set& templateSourcePaths); + void ReplaceOldAliases(QString& stringToReplace, AZStd::string_view oldAlias, AZStd::string_view newAlias); + static Instance* GetParentInstance(Instance* instance); static Instance* GetAncestorOfInstanceThatIsChildOfRoot(const Instance* ancestor, Instance* descendant); static void GenerateContainerEntityTransform(const EntityList& topLevelEntities, AZ::Vector3& translation, AZ::Quaternion& rotation); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentAdapter.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentAdapter.h index 6950717499..0ca5853adc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentAdapter.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentAdapter.h @@ -1,22 +1,22 @@ /* -* 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. -* -*/ + * 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 #include +#include +#include +#include namespace AzToolsFramework { @@ -31,7 +31,7 @@ namespace AzToolsFramework To use the EditorComponentAdapter, 3 classes are required: - a class that implements the functions required for TController (see below) - a configuration struct/class which extends AZ::ComponentConfig - - A runtime component that will be generated by the editor comoinent on export + - A runtime component that will be generated by the editor component on export The concrete component extends the adapter and implements behavior which is unique to the component. @@ -64,15 +64,15 @@ namespace AzToolsFramework the EditContext. TController can friend itself to the editor component to make this work if required. */ template - class EditorComponentAdapter - : public EditorComponentBase + class EditorComponentAdapter : public EditorComponentBase { public: - - AZ_RTTI((EditorComponentAdapter, "{2F5A3669-FFE9-4CD7-B9E2-7FC8100CF1A2}", TController, TRuntimeComponent, TConfiguration), EditorComponentBase); + AZ_RTTI( + (EditorComponentAdapter, "{2F5A3669-FFE9-4CD7-B9E2-7FC8100CF1A2}", TController, TRuntimeComponent, TConfiguration), + EditorComponentBase); EditorComponentAdapter() = default; - EditorComponentAdapter(const TConfiguration& configuration); + explicit EditorComponentAdapter(const TConfiguration& configuration); static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services); static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services); @@ -86,7 +86,6 @@ namespace AzToolsFramework void BuildGameEntity(AZ::Entity* gameEntity) override; protected: - static void Reflect(AZ::ReflectContext* context); // AZ::Component overrides ... diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentAdapter.inl b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentAdapter.inl index 04619b079d..b8bd24589a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentAdapter.inl +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorComponentAdapter.inl @@ -1,14 +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. -* -*/ + * 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 @@ -28,23 +28,21 @@ namespace AzToolsFramework template void EditorComponentAdapter::Reflect(AZ::ReflectContext* context) { - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + if (auto serializeContext = azrtti_cast(context)) { - serializeContext->Class() - ->Version(1) - ->Field("Controller", &EditorComponentAdapter::m_controller) - ; + serializeContext->Class()->Version(1)->Field( + "Controller", &EditorComponentAdapter::m_controller); if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { - editContext->Class( - "EditorComponentAdapter", "") + // clang-format off + editContext->Class("EditorComponentAdapter", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(AZ::Edit::UIHandlers::Default, &EditorComponentAdapter::m_controller, "Controller", "") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorComponentAdapter::OnConfigurationChanged) - ; + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorComponentAdapter::OnConfigurationChanged); + // clang-format on } } } @@ -53,27 +51,35 @@ namespace AzToolsFramework // Get*Services functions template - void EditorComponentAdapter::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services) + void EditorComponentAdapter::GetProvidedServices( + AZ::ComponentDescriptor::DependencyArrayType& services) { - AzFramework::Components::GetProvidedServicesHelper(services, typename AZ::HasComponentProvidedServices::type()); + AzFramework::Components::GetProvidedServicesHelper( + services, typename AZ::HasComponentProvidedServices::type()); } template - void EditorComponentAdapter::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services) + void EditorComponentAdapter::GetRequiredServices( + AZ::ComponentDescriptor::DependencyArrayType& services) { - AzFramework::Components::GetRequiredServicesHelper(services, typename AZ::HasComponentRequiredServices::type()); + AzFramework::Components::GetRequiredServicesHelper( + services, typename AZ::HasComponentRequiredServices::type()); } template - void EditorComponentAdapter::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services) + void EditorComponentAdapter::GetIncompatibleServices( + AZ::ComponentDescriptor::DependencyArrayType& services) { - AzFramework::Components::GetIncompatibleServicesHelper(services, typename AZ::HasComponentIncompatibleServices::type()); + AzFramework::Components::GetIncompatibleServicesHelper( + services, typename AZ::HasComponentIncompatibleServices::type()); } template - void EditorComponentAdapter::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& services) + void EditorComponentAdapter::GetDependentServices( + AZ::ComponentDescriptor::DependencyArrayType& services) { - AzFramework::Components::GetDependentServicesHelper(services, typename AZ::HasComponentDependentServices::type()); + AzFramework::Components::GetDependentServicesHelper( + services, typename AZ::HasComponentDependentServices::type()); } ////////////////////////////////////////////////////////////////////////// @@ -99,7 +105,8 @@ namespace AzToolsFramework if (ShouldActivateController()) { - m_controller.Activate(GetEntityId()); + AzFramework::Components::ComponentActivateHelper::Activate( + m_controller, AZ::EntityComponentIdPair(GetEntityId(), GetId())); } } @@ -122,7 +129,8 @@ namespace AzToolsFramework } template - bool EditorComponentAdapter::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const + bool EditorComponentAdapter::WriteOutConfig( + AZ::ComponentConfig* outBaseConfig) const { if (auto config = azrtti_cast(outBaseConfig)) { @@ -139,7 +147,8 @@ namespace AzToolsFramework if (ShouldActivateController()) { - m_controller.Activate(GetEntityId()); + AzFramework::Components::ComponentActivateHelper::Activate( + m_controller, AZ::EntityComponentIdPair(GetEntityId(), GetId())); } return AZ::Edit::PropertyRefreshLevels::None; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorEntityIconComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorEntityIconComponent.cpp index 48a7a37487..c46bb158c6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorEntityIconComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorEntityIconComponent.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -313,8 +314,7 @@ namespace AzToolsFramework // if we do not yet have a valid texture id, request it using the entity icon path if (m_entityIconTextureId == 0) { - EditorRequestBus::BroadcastResult( - m_entityIconTextureId, &EditorRequests::GetIconTextureIdFromEntityIconPath, m_entityIconPath); + m_entityIconTextureId = EditorViewportIconDisplay::Get()->GetOrLoadIconForPath(m_entityIconPath); } return m_entityIconTextureId; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp index b73978c792..285d962b46 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp @@ -520,91 +520,13 @@ namespace AzToolsFramework return m_editorTransform.m_translate.GetZ(); } - void TransformComponent::SetRotation(const AZ::Vector3& eulerAnglesRadians) + void TransformComponent::SetWorldRotationQuaternion(const AZ::Quaternion& quaternion) { - AZ_Warning("AzToolsFramework::TransformComponent", false, "SetRotation is deprecated, please use SetLocalRotation"); - AZ::Transform newWorldTransform = GetWorldTM(); - newWorldTransform.SetRotation(AZ::ConvertEulerRadiansToQuaternion(eulerAnglesRadians)); - SetWorldTM(newWorldTransform); - } - - void TransformComponent::SetRotationQuaternion(const AZ::Quaternion& quaternion) - { - AZ_Warning("AzToolsFramework::TransformComponent", false, "SetRotationQuaternion is deprecated, please use SetLocalRotation"); AZ::Transform newWorldTransform = GetWorldTM(); newWorldTransform.SetRotation(quaternion); SetWorldTM(newWorldTransform); } - void TransformComponent::SetRotationX(float eulerAngleRadians) - { - AZ_Warning("AzToolsFramework::TransformComponent", false, "SetRotationX is deprecated, please use SetLocalRotation"); - AZ::Transform newWorldTransform = GetWorldTM(); - newWorldTransform.SetRotation(AZ::Quaternion::CreateRotationX(eulerAngleRadians)); - SetWorldTM(newWorldTransform); - } - - void TransformComponent::SetRotationY(float eulerAngleRadians) - { - AZ_Warning("AzToolsFramework::TransformComponent", false, "SetRotationY is deprecated, please use SetLocalRotation"); - AZ::Transform newWorldTransform = GetWorldTM(); - newWorldTransform.SetRotation(AZ::Quaternion::CreateRotationY(eulerAngleRadians)); - SetWorldTM(newWorldTransform); - } - - void TransformComponent::SetRotationZ(float eulerAngleRadians) - { - AZ_Warning("AzToolsFramework::TransformComponent", false, "SetRotationZ is deprecated, please use SetLocalRotation"); - AZ::Transform newWorldTransform = GetWorldTM(); - newWorldTransform.SetRotation(AZ::Quaternion::CreateRotationZ(eulerAngleRadians)); - SetWorldTM(newWorldTransform); - } - - void TransformComponent::RotateByX(float eulerAngleRadians) - { - AZ_Warning("AzToolsFramework::TransformComponent", false, "RotateByX is deprecated, please use RotateAroundLocalX"); - SetWorldTM(GetWorldTM() * AZ::Transform::CreateRotationX(eulerAngleRadians)); - } - - void TransformComponent::RotateByY(float eulerAngleRadians) - { - AZ_Warning("AzToolsFramework::TransformComponent", false, "RotateByY is deprecated, please use RotateAroundLocalY"); - SetWorldTM(GetWorldTM() * AZ::Transform::CreateRotationY(eulerAngleRadians)); - } - - void TransformComponent::RotateByZ(float eulerAngleRadians) - { - AZ_Warning("AzToolsFramework::TransformComponent", false, "RotateByZ is deprecated, please use RotateAroundLocalZ"); - SetWorldTM(GetWorldTM() * AZ::Transform::CreateRotationZ(eulerAngleRadians)); - } - - AZ::Vector3 TransformComponent::GetRotationEulerRadians() - { - AZ_Warning("AzToolsFramework::TransformComponent", false, "GetRotationEulerRadians is deprecated, please use GetWorldRotation"); - return GetWorldTM().GetRotation().GetEulerRadians(); - } - - AZ::Quaternion TransformComponent::GetRotationQuaternion() - { - AZ_Warning("AzToolsFramework::TransformComponent", false, "GetRotationQuaternion is deprecated, please use GetWorldRotationQuaternion"); - return GetWorldTM().GetRotation(); - } - - float TransformComponent::GetRotationX() - { - return GetRotationEulerRadians().GetX(); - } - - float TransformComponent::GetRotationY() - { - return GetRotationEulerRadians().GetY(); - } - - float TransformComponent::GetRotationZ() - { - return GetRotationEulerRadians().GetZ(); - } - AZ::Vector3 TransformComponent::GetWorldRotation() { return GetWorldTM().GetRotation().GetEulerRadians(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h index 91d64b0533..f772b608c1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h @@ -99,22 +99,7 @@ namespace AzToolsFramework float GetLocalZ() override; // Rotation modifiers - void SetRotation(const AZ::Vector3& eulerAnglesRadians) override; - void SetRotationQuaternion(const AZ::Quaternion& quaternion) override; - void SetRotationX(float eulerAngleRadians) override; - void SetRotationY(float eulerAngleRadians) override; - void SetRotationZ(float eulerAngleRadians) override; - - void RotateByX(float eulerAngleRadians) override; - void RotateByY(float eulerAngleRadians) override; - void RotateByZ(float eulerAngleRadians) override; - - AZ::Vector3 GetRotationEulerRadians() override; - AZ::Quaternion GetRotationQuaternion() override; - - float GetRotationX() override; - float GetRotationY() override; - float GetRotationZ() override; + void SetWorldRotationQuaternion(const AZ::Quaternion& quaternion) override; AZ::Vector3 GetWorldRotation() override; AZ::Quaternion GetWorldRotationQuaternion() override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp index 5c62a2997b..31da01fadc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp @@ -21,6 +21,7 @@ #include #include #include +#include AZ_CVAR( bool, ed_visibility_showAggregateEntitySelectionBounds, false, nullptr, AZ::ConsoleFunctorFlags::Null, @@ -232,10 +233,14 @@ namespace AzToolsFramework return AZ::Color(1.0f, 1.0f, 1.0f, 1.0f); }(); - debugDisplay.SetColor(iconHighlight); - // debugDisplay.DrawTextureLabel( - // iconTextureId, entityPosition, iconSize, iconSize, - // /*DisplayContext::ETextureIconFlags::TEXICON_ON_TOP=*/ 0x0008); + EditorViewportIconDisplay::Get()->DrawIcon({ + viewportInfo.m_viewportId, + iconTextureId, + iconHighlight, + entityPosition, + EditorViewportIconDisplayInterface::CoordinateSpace::WorldSpace, + AZ::Vector2{iconSize, iconSize} + }); } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 45f52704bf..aaf5c86d33 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -46,6 +46,7 @@ set(FILES API/EditorWindowRequestBus.h API/EntityCompositionRequestBus.h API/EntityCompositionNotificationBus.h + API/EditorViewportIconDisplayInterface.h API/ViewPaneOptions.h Application/Ticker.h Application/Ticker.cpp diff --git a/Code/Framework/AzToolsFramework/Tests/AssetSeedManager.cpp b/Code/Framework/AzToolsFramework/Tests/AssetSeedManager.cpp index 3d45c10fca..33009bc0da 100644 --- a/Code/Framework/AzToolsFramework/Tests/AssetSeedManager.cpp +++ b/Code/Framework/AzToolsFramework/Tests/AssetSeedManager.cpp @@ -82,7 +82,7 @@ namespace UnitTest } m_testPlatforms[0] = AzFramework::PlatformId::PC; - m_testPlatforms[1] = AzFramework::PlatformId::ES3; + m_testPlatforms[1] = AzFramework::PlatformId::ANDROID_ID; int platformCount = 0; for(auto thisPlatform : m_testPlatforms) @@ -170,20 +170,20 @@ namespace UnitTest AzFramework::AssetCatalog assetCatalog(useRequestBus); AZStd::string pcCatalogFile = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(AzFramework::PlatformId::PC); - AZStd::string es3CatalogFile = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(AzFramework::PlatformId::ES3); + AZStd::string androidCatalogFile = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(AzFramework::PlatformId::ANDROID_ID); if (!assetCatalog.SaveCatalog(pcCatalogFile.c_str(), m_assetRegistry)) { GTEST_FATAL_FAILURE_(AZStd::string::format("Unable to save the asset catalog (PC) file.\n").c_str()); } - if (!assetCatalog.SaveCatalog(es3CatalogFile.c_str(), m_assetRegistry)) + if (!assetCatalog.SaveCatalog(androidCatalogFile.c_str(), m_assetRegistry)) { - GTEST_FATAL_FAILURE_(AZStd::string::format("Unable to save the asset catalog (ES3) file.\n").c_str()); + GTEST_FATAL_FAILURE_(AZStd::string::format("Unable to save the asset catalog (ANDROID) file.\n").c_str()); } m_pcCatalog = new AzToolsFramework::PlatformAddressedAssetCatalog(AzFramework::PlatformId::PC); - m_es3Catalog = new AzToolsFramework::PlatformAddressedAssetCatalog(AzFramework::PlatformId::ES3); + m_androidCatalog = new AzToolsFramework::PlatformAddressedAssetCatalog(AzFramework::PlatformId::ANDROID_ID); const AZStd::string engroot = AZ::Test::GetEngineRootPath(); AZ::IO::FileIOBase::GetInstance()->SetAlias("@engroot@", engroot.c_str()); @@ -227,21 +227,21 @@ namespace UnitTest } auto pcCatalogFile = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(AzFramework::PlatformId::PC); - auto es3CatalogFile = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(AzFramework::PlatformId::ES3); + auto androidCatalogFile = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(AzFramework::PlatformId::ANDROID_ID); if (fileIO->Exists(pcCatalogFile.c_str())) { fileIO->Remove(pcCatalogFile.c_str()); } - if (fileIO->Exists(es3CatalogFile.c_str())) + if (fileIO->Exists(androidCatalogFile.c_str())) { - fileIO->Remove(es3CatalogFile.c_str()); + fileIO->Remove(androidCatalogFile.c_str()); } delete m_assetSeedManager; delete m_assetRegistry; delete m_pcCatalog; - delete m_es3Catalog; + delete m_androidCatalog; m_application->Stop(); delete m_application; } @@ -342,10 +342,10 @@ namespace UnitTest m_assetSeedManager->AddSeedAsset(assets[2], AzFramework::PlatformFlags::Platform_PC); // Step we are testing - m_assetSeedManager->AddPlatformToAllSeeds(AzFramework::PlatformId::ES3); + m_assetSeedManager->AddPlatformToAllSeeds(AzFramework::PlatformId::ANDROID_ID); // Verification - AzFramework::PlatformFlags expectedPlatformFlags = AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ES3; + AzFramework::PlatformFlags expectedPlatformFlags = AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ANDROID; for (const auto& seedInfo : m_assetSeedManager->GetAssetSeedList()) { EXPECT_EQ(seedInfo.m_platformFlags, expectedPlatformFlags); @@ -358,14 +358,14 @@ namespace UnitTest m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC); m_assetSeedManager->AddSeedAsset(assets[1], AzFramework::PlatformFlags::Platform_PC); - m_es3Catalog->UnregisterAsset(assets[2]); + m_androidCatalog->UnregisterAsset(assets[2]); m_assetSeedManager->AddSeedAsset(assets[2], AzFramework::PlatformFlags::Platform_PC); // Step we are testing - m_assetSeedManager->AddPlatformToAllSeeds(AzFramework::PlatformId::ES3); + m_assetSeedManager->AddPlatformToAllSeeds(AzFramework::PlatformId::ANDROID_ID); // Verification - AzFramework::PlatformFlags expectedPlatformFlags = AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ES3; + AzFramework::PlatformFlags expectedPlatformFlags = AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ANDROID; for (const auto& seedInfo : m_assetSeedManager->GetAssetSeedList()) { if (seedInfo.m_assetId == assets[2]) @@ -383,14 +383,14 @@ namespace UnitTest { // Setup m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC); - m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_ES3); + m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_ANDROID); m_assetSeedManager->AddSeedAsset(assets[1], AzFramework::PlatformFlags::Platform_PC); - m_assetSeedManager->AddSeedAsset(assets[1], AzFramework::PlatformFlags::Platform_ES3); + m_assetSeedManager->AddSeedAsset(assets[1], AzFramework::PlatformFlags::Platform_ANDROID); m_assetSeedManager->AddSeedAsset(assets[2], AzFramework::PlatformFlags::Platform_PC); - m_assetSeedManager->AddSeedAsset(assets[2], AzFramework::PlatformFlags::Platform_ES3); + m_assetSeedManager->AddSeedAsset(assets[2], AzFramework::PlatformFlags::Platform_ANDROID); // Step we are testing - m_assetSeedManager->RemovePlatformFromAllSeeds(AzFramework::PlatformId::ES3); + m_assetSeedManager->RemovePlatformFromAllSeeds(AzFramework::PlatformId::ANDROID_ID); // Verification for (const auto& seedInfo : m_assetSeedManager->GetAssetSeedList()) @@ -514,8 +514,8 @@ namespace UnitTest void DependencyValidation_MultipleAssetSeeds_MultiplePlatformFlags_ListValid() { - m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ES3); - m_assetSeedManager->AddSeedAsset(assets[5], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ES3); + m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ANDROID); + m_assetSeedManager->AddSeedAsset(assets[5], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ANDROID); AzToolsFramework::AssetFileInfoList assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::PC); @@ -531,7 +531,7 @@ namespace UnitTest assetList.m_fileInfoList.clear(); - m_assetSeedManager->AddSeedAsset(assets[8], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ES3); + m_assetSeedManager->AddSeedAsset(assets[8], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ANDROID); assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::PC); @@ -547,7 +547,7 @@ namespace UnitTest EXPECT_TRUE(Search(assetList, assets[8])); assetList.m_fileInfoList.clear(); - m_assetSeedManager->RemoveSeedAsset(assets[5], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ES3); + m_assetSeedManager->RemoveSeedAsset(assets[5], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ANDROID); assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::PC); @@ -562,7 +562,7 @@ namespace UnitTest EXPECT_TRUE(Search(assetList, assets[8])); // Removing the android flag from the asset should still produce the same result - m_assetSeedManager->RemoveSeedAsset(assets[8], AzFramework::PlatformFlags::Platform_ES3); + m_assetSeedManager->RemoveSeedAsset(assets[8], AzFramework::PlatformFlags::Platform_ANDROID); assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::PC); @@ -576,7 +576,7 @@ namespace UnitTest EXPECT_TRUE(Search(assetList, assets[7])); EXPECT_TRUE(Search(assetList, assets[8])); - assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::ES3); + assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::ANDROID_ID); EXPECT_EQ(assetList.m_fileInfoList.size(), 5); EXPECT_TRUE(Search(assetList, assets[0])); @@ -586,8 +586,8 @@ namespace UnitTest EXPECT_TRUE(Search(assetList, assets[4])); // Adding the android flag again to the asset - m_assetSeedManager->AddSeedAsset(assets[8], AzFramework::PlatformFlags::Platform_ES3); - assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::ES3); + m_assetSeedManager->AddSeedAsset(assets[8], AzFramework::PlatformFlags::Platform_ANDROID); + assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::ANDROID_ID); EXPECT_EQ(assetList.m_fileInfoList.size(), 8); EXPECT_TRUE(Search(assetList, assets[0])); @@ -773,7 +773,7 @@ namespace UnitTest AzFramework::AssetRegistry* m_assetRegistry; ToolsTestApplication* m_application; AzToolsFramework::PlatformAddressedAssetCatalog* m_pcCatalog; - AzToolsFramework::PlatformAddressedAssetCatalog* m_es3Catalog; + AzToolsFramework::PlatformAddressedAssetCatalog* m_androidCatalog; AZ::IO::FileIOStream m_fileStreams[s_totalTestPlatforms][s_totalAssets]; AzFramework::PlatformId m_testPlatforms[s_totalTestPlatforms]; AZStd::string m_assetsPath[s_totalAssets]; @@ -936,7 +936,7 @@ namespace UnitTest TEST_F(AssetSeedManagerTest, AddSeedAssetForValidPlatforms_AllPlatformsValid_SeedAddedForEveryInputPlatform) { using namespace AzFramework; - PlatformFlags validPlatforms = PlatformFlags::Platform_PC | PlatformFlags::Platform_ES3; + PlatformFlags validPlatforms = PlatformFlags::Platform_PC | PlatformFlags::Platform_ANDROID; AZStd::pair result = m_assetSeedManager->AddSeedAssetForValidPlatforms(TestDynamicSliceAssetPath, validPlatforms); // Verify the function outputs @@ -953,8 +953,8 @@ namespace UnitTest TEST_F(AssetSeedManagerTest, AddSeedAssetForValidPlatforms_SomePlatformsValid_SeedAddedForEveryValidPlatform) { using namespace AzFramework; - PlatformFlags validPlatforms = PlatformFlags::Platform_PC | PlatformFlags::Platform_ES3; - PlatformFlags inputPlatforms = validPlatforms | PlatformFlags::Platform_OSX; + PlatformFlags validPlatforms = PlatformFlags::Platform_PC | PlatformFlags::Platform_ANDROID; + PlatformFlags inputPlatforms = validPlatforms | PlatformFlags::Platform_MAC; AZStd::pair result = m_assetSeedManager->AddSeedAssetForValidPlatforms(TestDynamicSliceAssetPath, inputPlatforms); // Verify the function outputs @@ -971,7 +971,7 @@ namespace UnitTest TEST_F(AssetSeedManagerTest, AddSeedAssetForValidPlatforms_NoPlatformsValid_NoSeedAdded) { using namespace AzFramework; - PlatformFlags inputPlatforms = PlatformFlags::Platform_OSX; + PlatformFlags inputPlatforms = PlatformFlags::Platform_MAC; AZStd::pair result = m_assetSeedManager->AddSeedAssetForValidPlatforms(TestDynamicSliceAssetPath, inputPlatforms); // Verify the function outputs @@ -985,30 +985,30 @@ namespace UnitTest TEST_F(AssetSeedManagerTest, Valid_Seed_Remove_ForAllPlatform_OK) { - m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_MAC); - m_assetSeedManager->RemoveSeedAsset(assets[0].ToString(), AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->RemoveSeedAsset(assets[0].ToString(), AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_MAC); const AzFramework::AssetSeedList& seedList = m_assetSeedManager->GetAssetSeedList(); EXPECT_EQ(seedList.size(), 0); - m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_MAC); - m_assetSeedManager->RemoveSeedAsset("asset0.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->RemoveSeedAsset("asset0.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_MAC); const AzFramework::AssetSeedList& secondSeedList = m_assetSeedManager->GetAssetSeedList(); EXPECT_EQ(secondSeedList.size(), 0); } TEST_F(AssetSeedManagerTest, Valid_Seed_Remove_ForSpecificPlatform_OK) { - m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_MAC); - m_assetSeedManager->RemoveSeedAsset(assets[0].ToString(), AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->RemoveSeedAsset(assets[0].ToString(), AzFramework::PlatformFlags::Platform_MAC); const AzFramework::AssetSeedList& seedList = m_assetSeedManager->GetAssetSeedList(); EXPECT_EQ(seedList.size(), 1); - m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_MAC); m_assetSeedManager->RemoveSeedAsset("asset0.txt", AzFramework::PlatformFlags::Platform_PC); const AzFramework::AssetSeedList& secondSeedList = m_assetSeedManager->GetAssetSeedList(); @@ -1017,14 +1017,14 @@ namespace UnitTest TEST_F(AssetSeedManagerTest, Invalid_NotRemove_SeedForAllPlatform_Ok) { - m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_MAC); - m_assetSeedManager->RemoveSeedAsset(assets[1].ToString(), AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->RemoveSeedAsset(assets[1].ToString(), AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_MAC); const AzFramework::AssetSeedList& seedList = m_assetSeedManager->GetAssetSeedList(); EXPECT_EQ(seedList.size(), 1); - m_assetSeedManager->RemoveSeedAsset("asset1.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->RemoveSeedAsset("asset1.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_MAC); const AzFramework::AssetSeedList& secondSeedList = m_assetSeedManager->GetAssetSeedList(); EXPECT_EQ(secondSeedList.size(), 1); } diff --git a/Code/Framework/AzToolsFramework/Tests/AssetSystemMocks.h b/Code/Framework/AzToolsFramework/Tests/AssetSystemMocks.h index 1e01229d73..8a394d3ab5 100644 --- a/Code/Framework/AzToolsFramework/Tests/AssetSystemMocks.h +++ b/Code/Framework/AzToolsFramework/Tests/AssetSystemMocks.h @@ -25,6 +25,8 @@ namespace UnitTests MOCK_METHOD0(GetAbsoluteDevGameFolderPath, const char* ()); MOCK_METHOD0(GetAbsoluteDevRootFolderPath, const char* ()); MOCK_METHOD2(GetRelativeProductPathFromFullSourceOrProductPath, bool(const AZStd::string& fullPath, AZStd::string& relativeProductPath)); + MOCK_METHOD3(GenerateRelativeSourcePath, + bool(const AZStd::string& sourcePath, AZStd::string& relativePath, AZStd::string& watchFolder)); MOCK_METHOD2(GetFullSourcePathFromRelativeProductPath, bool(const AZStd::string& relPath, AZStd::string& fullSourcePath)); MOCK_METHOD5(GetAssetInfoById, bool(const AZ::Data::AssetId& assetId, const AZ::Data::AssetType& assetType, const AZStd::string& platformName, AZ::Data::AssetInfo& assetInfo, AZStd::string& rootFilePath)); MOCK_METHOD3(GetSourceInfoBySourcePath, bool(const char* sourcePath, AZ::Data::AssetInfo& assetInfo, AZStd::string& watchFolder)); diff --git a/Code/Framework/AzToolsFramework/Tests/PlatformAddressedAssetCatalogTests.cpp b/Code/Framework/AzToolsFramework/Tests/PlatformAddressedAssetCatalogTests.cpp index 4cc98106d6..0b705338d9 100644 --- a/Code/Framework/AzToolsFramework/Tests/PlatformAddressedAssetCatalogTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/PlatformAddressedAssetCatalogTests.cpp @@ -184,13 +184,13 @@ namespace UnitTest TEST_F(PlatformAddressedAssetCatalogManagerTest, PlatformAddressedAssetCatalogManager_CatalogExistsChecks_Success) { - EXPECT_EQ(AzToolsFramework::PlatformAddressedAssetCatalog::CatalogExists(AzFramework::PlatformId::ES3), true); - AZStd::string es3CatalogPath = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(AzFramework::PlatformId::ES3); - if (AZ::IO::FileIOBase::GetInstance()->Exists(es3CatalogPath.c_str())) + EXPECT_EQ(AzToolsFramework::PlatformAddressedAssetCatalog::CatalogExists(AzFramework::PlatformId::ANDROID_ID), true); + AZStd::string androidCatalogPath = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(AzFramework::PlatformId::ANDROID_ID); + if (AZ::IO::FileIOBase::GetInstance()->Exists(androidCatalogPath.c_str())) { - AZ::IO::FileIOBase::GetInstance()->Remove(es3CatalogPath.c_str()); + AZ::IO::FileIOBase::GetInstance()->Remove(androidCatalogPath.c_str()); } - EXPECT_EQ(AzToolsFramework::PlatformAddressedAssetCatalog::CatalogExists(AzFramework::PlatformId::ES3), false); + EXPECT_EQ(AzToolsFramework::PlatformAddressedAssetCatalog::CatalogExists(AzFramework::PlatformId::ANDROID_ID), false); } class PlatformAddressedAssetCatalogMessageTest : public AzToolsFramework::PlatformAddressedAssetCatalog @@ -251,7 +251,7 @@ namespace UnitTest AzFramework::AssetSystem::NetworkAssetUpdateInterface* notificationInterface = AZ::Interface::Get(); EXPECT_NE(notificationInterface, nullptr); - auto* mockCatalog = new ::testing::NiceMock(AzFramework::PlatformId::ES3); + auto* mockCatalog = new ::testing::NiceMock(AzFramework::PlatformId::ANDROID_ID); AZStd::unique_ptr< ::testing::NiceMock> catalogHolder; catalogHolder.reset(mockCatalog); @@ -259,7 +259,7 @@ namespace UnitTest EXPECT_CALL(*mockCatalog, AssetChanged(testing::_)).Times(0); notificationInterface->AssetChanged(testMessage); - testMessage.m_platform = "es3"; + testMessage.m_platform = "android"; EXPECT_CALL(*mockCatalog, AssetChanged(testing::_)).Times(1); notificationInterface->AssetChanged(testMessage); @@ -270,7 +270,7 @@ namespace UnitTest EXPECT_CALL(*mockCatalog, AssetRemoved(testing::_)).Times(0); notificationInterface->AssetRemoved(testMessage); - testMessage.m_platform = "es3"; + testMessage.m_platform = "android"; EXPECT_CALL(*mockCatalog, AssetRemoved(testing::_)).Times(1); notificationInterface->AssetRemoved(testMessage); } diff --git a/Code/Framework/AzToolsFramework/Tests/SliceStabilityTests/SliceStabilityTestFramework.h b/Code/Framework/AzToolsFramework/Tests/SliceStabilityTests/SliceStabilityTestFramework.h index 57ac16673d..7d3d312cdb 100644 --- a/Code/Framework/AzToolsFramework/Tests/SliceStabilityTests/SliceStabilityTestFramework.h +++ b/Code/Framework/AzToolsFramework/Tests/SliceStabilityTests/SliceStabilityTestFramework.h @@ -149,6 +149,9 @@ namespace UnitTest const char* GetAbsoluteDevGameFolderPath() override { return ""; } const char* GetAbsoluteDevRootFolderPath() override { return ""; } bool GetRelativeProductPathFromFullSourceOrProductPath([[maybe_unused]] const AZStd::string& fullPath, [[maybe_unused]] AZStd::string& relativeProductPath) override { return false; } + bool GenerateRelativeSourcePath( + [[maybe_unused]] const AZStd::string& sourcePath, [[maybe_unused]] AZStd::string& relativePath, + [[maybe_unused]] AZStd::string& watchFolder) override { return false; } bool GetFullSourcePathFromRelativeProductPath([[maybe_unused]] const AZStd::string& relPath, [[maybe_unused]] AZStd::string& fullSourcePath) override { return false; } bool GetAssetInfoById([[maybe_unused]] const AZ::Data::AssetId& assetId, [[maybe_unused]] const AZ::Data::AssetType& assetType, [[maybe_unused]] const AZStd::string& platformName, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& rootFilePath) override { return false; } bool GetSourceInfoBySourcePath(const char* sourcePath, AZ::Data::AssetInfo& assetInfo, AZStd::string& watchFolder) override; diff --git a/Code/Framework/Tests/PlatformHelper.cpp b/Code/Framework/Tests/PlatformHelper.cpp index 1ad7794c58..9a23fb8d25 100644 --- a/Code/Framework/Tests/PlatformHelper.cpp +++ b/Code/Framework/Tests/PlatformHelper.cpp @@ -30,11 +30,11 @@ TEST_F(PlatformHelperTest, SinglePlatformFlags_PlatformId_Valid) TEST_F(PlatformHelperTest, MultiplePlatformFlags_PlatformId_Valid) { - AzFramework::PlatformFlags platformFlags = AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ES3; + AzFramework::PlatformFlags platformFlags = AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_ANDROID; auto platforms = AzFramework::PlatformHelper::GetPlatforms(platformFlags); EXPECT_EQ(platforms.size(), 2); EXPECT_EQ(platforms[0], "pc"); - EXPECT_EQ(platforms[1], "es3"); + EXPECT_EQ(platforms[1], "android"); } TEST_F(PlatformHelperTest, SpecialAllFlag_PlatformId_Valid) @@ -42,7 +42,7 @@ TEST_F(PlatformHelperTest, SpecialAllFlag_PlatformId_Valid) AzFramework::PlatformFlags platformFlags = AzFramework::PlatformFlags::Platform_ALL; auto platforms = AzFramework::PlatformHelper::GetPlatformsInterpreted(platformFlags); EXPECT_EQ(platforms.size(), AzFramework::NumPlatforms); - EXPECT_THAT(platforms, testing::UnorderedElementsAre("pc", "es3", "ios", "osx_gl", "provo", "salem", "jasper", "server")); + EXPECT_THAT(platforms, testing::UnorderedElementsAre("pc", "android", "ios", "mac", "provo", "salem", "jasper", "server")); } TEST_F(PlatformHelperTest, SpecialAllClientFlag_PlatformId_Valid) @@ -50,7 +50,7 @@ TEST_F(PlatformHelperTest, SpecialAllClientFlag_PlatformId_Valid) AzFramework::PlatformFlags platformFlags = AzFramework::PlatformFlags::Platform_ALL_CLIENT; auto platforms = AzFramework::PlatformHelper::GetPlatformsInterpreted(platformFlags); EXPECT_EQ(platforms.size(), AzFramework::NumClientPlatforms); - EXPECT_THAT(platforms, testing::UnorderedElementsAre("pc", "es3", "ios", "osx_gl", "provo", "salem", "jasper")); + EXPECT_THAT(platforms, testing::UnorderedElementsAre("pc", "android", "ios", "mac", "provo", "salem", "jasper")); } TEST_F(PlatformHelperTest, InvalidPlatformFlags_PlatformId_Empty) diff --git a/Code/Framework/Tests/Spawnable/SpawnableEntitiesManagerTests.cpp b/Code/Framework/Tests/Spawnable/SpawnableEntitiesManagerTests.cpp new file mode 100644 index 0000000000..1fa50fff52 --- /dev/null +++ b/Code/Framework/Tests/Spawnable/SpawnableEntitiesManagerTests.cpp @@ -0,0 +1,158 @@ +/* +* 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 + +namespace UnitTest +{ + class TestApplication : public AzFramework::Application + { + public: + // ComponentApplication + void SetSettingsRegistrySpecializations(AZ::SettingsRegistryInterface::Specializations& specializations) override + { + Application::SetSettingsRegistrySpecializations(specializations); + specializations.Append("test"); + specializations.Append("spawnable"); + } + }; + + class SpawnableEntitiesManagerTest : public AllocatorsFixture + { + public: + void SetUp() override + { + AllocatorsFixture::SetUp(); + + m_application = new TestApplication(); + AZ::ComponentApplication::Descriptor descriptor; + m_application->Start(descriptor); + + m_spawnable = aznew AzFramework::Spawnable( + AZ::Data::AssetId::CreateString("{EB2E8A2B-F253-4A90-BBF4-55F2EED786B8}:0"), AZ::Data::AssetData::AssetStatus::Ready); + m_spawnableAsset = new AZ::Data::Asset(m_spawnable, AZ::Data::AssetLoadBehavior::Default); + m_ticket = new AzFramework::EntitySpawnTicket(*m_spawnableAsset); + + auto managerInterface = AzFramework::SpawnableEntitiesInterface::Get(); + m_manager = azrtti_cast(managerInterface); + } + + void TearDown() override + { + delete m_ticket; + m_ticket = nullptr; + // One more tick on the spawnable entities manager in order to delete the ticket fully. + m_manager->ProcessQueue(); + + delete m_spawnableAsset; + m_spawnableAsset = nullptr; + // This will also delete m_spawnable. + + delete m_application; + m_application = nullptr; + + AllocatorsFixture::TearDown(); + } + + void FillSpawnable(size_t numElements) + { + AzFramework::Spawnable::EntityList& entities = m_spawnable->GetEntities(); + entities.reserve(numElements); + for (size_t i=0; i()); + } + } + + protected: + AZ::Data::Asset* m_spawnableAsset { nullptr }; + AzFramework::SpawnableEntitiesManager* m_manager { nullptr }; + AzFramework::EntitySpawnTicket* m_ticket { nullptr }; + AzFramework::Spawnable* m_spawnable { nullptr }; + TestApplication* m_application { nullptr }; + }; + + TEST_F(SpawnableEntitiesManagerTest, SpawnAllEntities_Call_AllEntitiesSpawned) + { + static constexpr size_t NumEntities = 4; + FillSpawnable(NumEntities); + + size_t spawnedEntitiesCount = 0; + auto callback = + [&spawnedEntitiesCount](AzFramework::EntitySpawnTicket&, AzFramework::SpawnableConstEntityContainerView entities) + { + spawnedEntitiesCount += entities.size(); + }; + m_manager->SpawnAllEntities(*m_ticket, {}, AZStd::move(callback)); + m_manager->ProcessQueue(); + + EXPECT_EQ(NumEntities, spawnedEntitiesCount); + } + + TEST_F(SpawnableEntitiesManagerTest, ListEntities_Call_AllEntitiesAreReported) + { + static constexpr size_t NumEntities = 4; + FillSpawnable(NumEntities); + + bool allValidEntityIds = true; + size_t spawnedEntitiesCount = 0; + auto callback = [&allValidEntityIds, &spawnedEntitiesCount] + (AzFramework::EntitySpawnTicket&, AzFramework::SpawnableConstEntityContainerView entities) + { + for (auto&& entity : entities) + { + allValidEntityIds = entity->GetId().IsValid() && allValidEntityIds; + } + spawnedEntitiesCount += entities.size(); + }; + + m_manager->SpawnAllEntities(*m_ticket); + m_manager->ListEntities(*m_ticket, AZStd::move(callback)); + m_manager->ProcessQueue(); + + EXPECT_TRUE(allValidEntityIds); + EXPECT_EQ(NumEntities, spawnedEntitiesCount); + } + + TEST_F(SpawnableEntitiesManagerTest, ListIndicesAndEntities_Call_AllEntitiesAreReportedAndIncrementByOne) + { + static constexpr size_t NumEntities = 4; + FillSpawnable(NumEntities); + + bool allValidEntityIds = true; + size_t spawnedEntitiesCount = 0; + auto callback = [&allValidEntityIds, &spawnedEntitiesCount] + (AzFramework::EntitySpawnTicket&, AzFramework::SpawnableConstIndexEntityContainerView entities) + { + for (auto&& indexEntityPair : entities) + { + // Since all entities are spawned a single time, the indices should be 0..NumEntities. + if (indexEntityPair.GetIndex() == spawnedEntitiesCount) + { + spawnedEntitiesCount++; + } + allValidEntityIds = indexEntityPair.GetEntity()->GetId().IsValid() && allValidEntityIds; + } + }; + + m_manager->SpawnAllEntities(*m_ticket); + m_manager->ListIndicesAndEntities(*m_ticket, AZStd::move(callback)); + m_manager->ProcessQueue(); + + EXPECT_TRUE(allValidEntityIds); + EXPECT_EQ(NumEntities, spawnedEntitiesCount); + } +} // namespace UnitTest diff --git a/Code/Framework/Tests/frameworktests_files.cmake b/Code/Framework/Tests/frameworktests_files.cmake index 197bcc9fce..3fc84eb788 100644 --- a/Code/Framework/Tests/frameworktests_files.cmake +++ b/Code/Framework/Tests/frameworktests_files.cmake @@ -11,6 +11,7 @@ set(FILES ../AzCore/Tests/Main.cpp + Spawnable/SpawnableEntitiesManagerTests.cpp ArchiveCompressionTests.cpp ArchiveTests.cpp BehaviorEntityTests.cpp diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index 0bbc48d5f9..5fd6eb2692 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -69,6 +69,7 @@ AZ_POP_DISABLE_WARNING #include #include #include +#include #include // AzQtComponents @@ -3105,6 +3106,15 @@ CCryEditApp::ECreateLevelResult CCryEditApp::CreateLevel(const QString& levelNam GetIEditor()->GetDocument()->SetPathName(fullyQualifiedLevelName); GetIEditor()->GetGameEngine()->SetLevelPath(levelPath); + if (usePrefabSystemForLevels) + { + auto* service = AZ::Interface::Get(); + if (service) + { + service->CreateNewLevelPrefab((const char*)fullyQualifiedLevelName.toUtf8()); + } + } + if (GetIEditor()->GetDocument()->Save()) { if (!usePrefabSystemForLevels) diff --git a/Code/Sandbox/Editor/CryEditPy.cpp b/Code/Sandbox/Editor/CryEditPy.cpp index 135dd9878c..edbeccb04f 100644 --- a/Code/Sandbox/Editor/CryEditPy.cpp +++ b/Code/Sandbox/Editor/CryEditPy.cpp @@ -533,7 +533,7 @@ namespace AzToolsFramework ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation); behaviorContext->EnumProperty("SystemConfigPlatform_Pc") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation); - behaviorContext->EnumProperty("SystemConfigPlatform_OsxGl") + behaviorContext->EnumProperty("SystemConfigPlatform_Mac") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation); behaviorContext->EnumProperty("SystemConfigPlatform_OsxMetal") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation); diff --git a/Code/Tools/AssetBundler/tests/AssetProcessorPlatformConfig.setreg b/Code/Tools/AssetBundler/tests/AssetProcessorPlatformConfig.setreg index 81fcdbcf12..ac546d4f39 100644 --- a/Code/Tools/AssetBundler/tests/AssetProcessorPlatformConfig.setreg +++ b/Code/Tools/AssetBundler/tests/AssetProcessorPlatformConfig.setreg @@ -3,7 +3,7 @@ "AssetProcessor": { "Settings": { "Platforms": { - "es3": "enabled" + "android": "enabled" } } } diff --git a/Code/Tools/AssetBundler/tests/applicationManagerTests.cpp b/Code/Tools/AssetBundler/tests/applicationManagerTests.cpp index f2477782d0..be6cf61c29 100644 --- a/Code/Tools/AssetBundler/tests/applicationManagerTests.cpp +++ b/Code/Tools/AssetBundler/tests/applicationManagerTests.cpp @@ -150,7 +150,7 @@ namespace AssetBundler AzFramework::PlatformFlags platformFlags = GetEnabledPlatformFlags(m_data->m_testEngineRoot.c_str(), m_data->m_testEngineRoot.c_str(), DummyProjectName); AzFramework::PlatformFlags hostPlatformFlag = AzFramework::PlatformHelper::GetPlatformFlag(AzToolsFramework::AssetSystem::GetHostAssetPlatform()); - AzFramework::PlatformFlags expectedFlags = AzFramework::PlatformFlags::Platform_ES3 | AzFramework::PlatformFlags::Platform_IOS | AzFramework::PlatformFlags::Platform_PROVO | hostPlatformFlag; + AzFramework::PlatformFlags expectedFlags = AzFramework::PlatformFlags::Platform_ANDROID | AzFramework::PlatformFlags::Platform_IOS | AzFramework::PlatformFlags::Platform_PROVO | hostPlatformFlag; ASSERT_EQ(platformFlags, expectedFlags); } diff --git a/Code/Tools/AssetBundler/tests/tests_main.cpp b/Code/Tools/AssetBundler/tests/tests_main.cpp index 53b19c5eb4..71046a576a 100644 --- a/Code/Tools/AssetBundler/tests/tests_main.cpp +++ b/Code/Tools/AssetBundler/tests/tests_main.cpp @@ -40,14 +40,14 @@ namespace AssetBundler TEST_F(AssetBundlerBatchUtilsTest, SplitFilename_MacFile_OutputBaseNameAndPlatform) { - AZStd::string filePath = "assetInfoFile_osx_gl.xml"; + AZStd::string filePath = "assetInfoFile_mac.xml"; AZStd::string baseFilename; AZStd::string platformIdentifier; AzToolsFramework::SplitFilename(filePath, baseFilename, platformIdentifier); ASSERT_EQ(baseFilename, "assetInfoFile"); - ASSERT_EQ(platformIdentifier, "osx_gl"); + ASSERT_EQ(platformIdentifier, "mac"); } TEST_F(AssetBundlerBatchUtilsTest, SplitFilename_PcFile_OutputBaseNameAndPlatform) @@ -64,14 +64,14 @@ namespace AssetBundler TEST_F(AssetBundlerBatchUtilsTest, SplitFilename_MacFileWithUnderScoreInFileName_OutputBaseNameAndPlatform) { - AZStd::string filePath = "assetInfoFile_test_osx_gl.xml"; + AZStd::string filePath = "assetInfoFile_test_mac.xml"; AZStd::string baseFilename; AZStd::string platformIdentifier; AzToolsFramework::SplitFilename(filePath, baseFilename, platformIdentifier); ASSERT_EQ(baseFilename, "assetInfoFile_test"); - ASSERT_EQ(platformIdentifier, "osx_gl"); + ASSERT_EQ(platformIdentifier, "mac"); } TEST_F(AssetBundlerBatchUtilsTest, SplitFilename_PcFileWithUnderScoreInFileName_OutputBaseNameAndPlatform) diff --git a/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp b/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp index c477ec2c9e..4f8b4b9144 100644 --- a/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp +++ b/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp @@ -78,17 +78,17 @@ namespace AssetBuilderSDK { return AssetBuilderSDK::Platform_PC; } - if (azstricmp(newPlatformName, "es3") == 0) + if (azstricmp(newPlatformName, "android") == 0) { - return AssetBuilderSDK::Platform_ES3; + return AssetBuilderSDK::Platform_ANDROID; } if (azstricmp(newPlatformName, "ios") == 0) { return AssetBuilderSDK::Platform_IOS; } - if (azstricmp(newPlatformName, "osx_gl") == 0) + if (azstricmp(newPlatformName, "mac") == 0) { - return AssetBuilderSDK::Platform_OSX; + return AssetBuilderSDK::Platform_MAC; } if (azstricmp(newPlatformName, "provo") == 0) { @@ -115,12 +115,12 @@ namespace AssetBuilderSDK { case AssetBuilderSDK::Platform_PC: return "pc"; - case AssetBuilderSDK::Platform_ES3: - return "es3"; + case AssetBuilderSDK::Platform_ANDROID: + return "android"; case AssetBuilderSDK::Platform_IOS: return "ios"; - case AssetBuilderSDK::Platform_OSX: - return "osx_gl"; + case AssetBuilderSDK::Platform_MAC: + return "mac"; case AssetBuilderSDK::Platform_PROVO: return "provo"; case AssetBuilderSDK::Platform_SALEM: diff --git a/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.h b/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.h index a11cc9a80d..126ecda2ba 100644 --- a/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.h +++ b/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.h @@ -148,15 +148,15 @@ namespace AssetBuilderSDK { Platform_NONE = 0x00, Platform_PC = 0x01, - Platform_ES3 = 0x02, + Platform_ANDROID = 0x02, Platform_IOS = 0x04, - Platform_OSX = 0x08, + Platform_MAC = 0x08, Platform_PROVO = 0x20, Platform_SALEM = 0x40, Platform_JASPER = 0x80, //! if you add a new platform entry to this enum, you must add it to allplatforms as well otherwise that platform would not be considered valid. - AllPlatforms = Platform_PC | Platform_ES3 | Platform_IOS | Platform_OSX | Platform_PROVO | Platform_SALEM | Platform_JASPER + AllPlatforms = Platform_PC | Platform_ANDROID | Platform_IOS | Platform_MAC | Platform_PROVO | Platform_SALEM | Platform_JASPER }; #endif // defined(ENABLE_LEGACY_PLATFORMFLAGS_SUPPORT) //! Map data structure to holder parameters that are passed into a job for ProcessJob requests. @@ -503,7 +503,7 @@ namespace AssetBuilderSDK AZ_CLASS_ALLOCATOR(PlatformInfo, AZ::SystemAllocator, 0); AZ_TYPE_INFO(PlatformInfo, "{F7DA39A5-C319-4552-954B-3479E2454D3F}"); - AZStd::string m_identifier; ///< like "pc" or "es3" or "ios"... + AZStd::string m_identifier; ///< like "pc" or "android" or "ios"... AZStd::unordered_set m_tags; ///< The tags like "console" or "tools" on that platform PlatformInfo() = default; diff --git a/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.cpp b/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.cpp index 196f6b0543..8bc6d0b6f7 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.cpp +++ b/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.cpp @@ -655,6 +655,80 @@ namespace AssetProcessor return true; } + bool AssetCatalog::GenerateRelativeSourcePath( + const AZStd::string& sourcePath, AZStd::string& relativePath, AZStd::string& rootFolder) + { + QString normalizedSourcePath = AssetUtilities::NormalizeFilePath(sourcePath.c_str()); + QDir inputPath(normalizedSourcePath); + QString scanFolder; + QString relativeName; + + bool validResult = false; + + AZ_TracePrintf(AssetProcessor::DebugChannel, "ProcessGenerateRelativeSourcePathRequest: %s...\n", sourcePath.c_str()); + + if (sourcePath.empty()) + { + // For an empty input path, do nothing, we'll return an empty, invalid result. + // (We check fullPath instead of inputPath, because an empty fullPath actually produces "." for inputPath) + } + else if (inputPath.isAbsolute()) + { + // For an absolute path, try to convert it to a relative path, based on the existing scan folders. + // To get the inputPath, we use absolutePath() instead of path() so that any . or .. entries get collapsed. + validResult = m_platformConfig->ConvertToRelativePath(inputPath.absolutePath(), relativeName, scanFolder); + } + else if (inputPath.isRelative()) + { + // For a relative path, concatenate it with each scan folder, and see if a valid relative path emerges. + int scanFolders = m_platformConfig->GetScanFolderCount(); + for (int scanIdx = 0; scanIdx < scanFolders; scanIdx++) + { + auto& scanInfo = m_platformConfig->GetScanFolderAt(scanIdx); + QDir possibleRoot(scanInfo.ScanPath()); + QDir possibleAbsolutePath = possibleRoot.filePath(normalizedSourcePath); + // To get the inputPath, we use absolutePath() instead of path() so that any . or .. entries get collapsed. + if (m_platformConfig->ConvertToRelativePath(possibleAbsolutePath.absolutePath(), relativeName, scanFolder)) + { + validResult = true; + break; + } + } + } + + // The input has produced a valid relative path. However, the path might match multiple nested scan folders, + // so look to see if a higher-priority folder has a better match. + if (validResult) + { + QString overridingFile = m_platformConfig->GetOverridingFile(relativeName, scanFolder); + + if (!overridingFile.isEmpty()) + { + overridingFile = AssetUtilities::NormalizeFilePath(overridingFile); + validResult = m_platformConfig->ConvertToRelativePath(overridingFile, relativeName, scanFolder); + } + } + + if (!validResult) + { + // if we are here it means we have failed to determine the relativePath, so we will send back the original path + AZ_TracePrintf(AssetProcessor::DebugChannel, + "GenerateRelativeSourcePath found no valid result, returning original path: %s...\n", sourcePath.c_str()); + + rootFolder.clear(); + relativePath.clear(); + relativePath = sourcePath; + return false; + } + + relativePath = relativeName.toUtf8().data(); + rootFolder = scanFolder.toUtf8().data(); + + AZ_Assert(!relativePath.empty(), "ConvertToRelativePath returned true, but relativePath is empty"); + + return true; + } + bool AssetCatalog::GetFullSourcePathFromRelativeProductPath(const AZStd::string& relPath, AZStd::string& fullSourcePath) { ProcessGetFullSourcePathFromRelativeProductPathRequest(relPath, fullSourcePath); diff --git a/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.h b/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.h index f515fa3658..13dc7892b1 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.h +++ b/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.h @@ -95,6 +95,12 @@ namespace AssetProcessor const char* GetAbsoluteDevGameFolderPath() override; const char* GetAbsoluteDevRootFolderPath() override; bool GetRelativeProductPathFromFullSourceOrProductPath(const AZStd::string& fullPath, AZStd::string& relativeProductPath) override; + + //! Given a partial or full source file path, respond with its relative path and the watch folder it is relative to. + //! The input source path does not need to exist, so this can be used for new files that haven't been saved yet. + bool GenerateRelativeSourcePath( + const AZStd::string& sourcePath, AZStd::string& relativePath, AZStd::string& watchFolder) override; + bool GetFullSourcePathFromRelativeProductPath(const AZStd::string& relPath, AZStd::string& fullSourcePath) override; bool GetAssetInfoById(const AZ::Data::AssetId& assetId, const AZ::Data::AssetType& assetType, const AZStd::string& platformName, AZ::Data::AssetInfo& assetInfo, AZStd::string& rootFilePath) override; bool GetSourceInfoBySourcePath(const char* sourcePath, AZ::Data::AssetInfo& assetInfo, AZStd::string& watchFolder) override; diff --git a/Code/Tools/AssetProcessor/native/AssetManager/AssetRequestHandler.cpp b/Code/Tools/AssetProcessor/native/AssetManager/AssetRequestHandler.cpp index 97b28691dc..2d22d3d136 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/AssetRequestHandler.cpp +++ b/Code/Tools/AssetProcessor/native/AssetManager/AssetRequestHandler.cpp @@ -104,6 +104,27 @@ namespace return GetRelativeProductPathFromFullSourceOrProductPathResponse(relPathFound, relProductPath); } + GenerateRelativeSourcePathResponse HandleGenerateRelativeSourcePathRequest( + MessageData messageData) + { + bool relPathFound = false; + AZStd::string relPath; + AZStd::string watchFolder; + + AzToolsFramework::AssetSystemRequestBus::BroadcastResult( + relPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GenerateRelativeSourcePath, + messageData.m_message->m_sourcePath, relPath, watchFolder); + + if (!relPathFound) + { + AZ_TracePrintf( + AssetProcessor::ConsoleChannel, "Could not find relative source path for the source file (%s).", + messageData.m_message->m_sourcePath.c_str()); + } + + return GenerateRelativeSourcePathResponse(relPathFound, relPath, watchFolder); + } + SourceAssetInfoResponse HandleSourceAssetInfoRequest(MessageData messageData) { SourceAssetInfoResponse response; @@ -407,6 +428,7 @@ AssetRequestHandler::AssetRequestHandler() m_requestRouter.RegisterMessageHandler(&HandleGetFullSourcePathFromRelativeProductPathRequest); m_requestRouter.RegisterMessageHandler(&HandleGetRelativeProductPathFromFullSourceOrProductPathRequest); + m_requestRouter.RegisterMessageHandler(&HandleGenerateRelativeSourcePathRequest); m_requestRouter.RegisterMessageHandler(&HandleSourceAssetInfoRequest); m_requestRouter.RegisterMessageHandler(&HandleSourceAssetProductsInfoRequest); m_requestRouter.RegisterMessageHandler(&HandleGetScanFoldersRequest); diff --git a/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.h b/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.h index 88f74c886b..3dc8bd7a00 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.h +++ b/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.h @@ -57,6 +57,9 @@ namespace AzFramework class GetRelativeProductPathFromFullSourceOrProductPathRequest; class GetRelativeProductPathFromFullSourceOrProductPathResponse; + class GenerateRelativeSourcePathRequest; + class GenerateRelativeSourcePathResponse; + class GetFullSourcePathFromRelativeProductPathRequest; class GetFullSourcePathFromRelativeProductPathResponse; class AssetNotificationMessage; @@ -104,6 +107,8 @@ namespace AssetProcessor using GetAbsoluteAssetDatabaseLocationResponse = AzToolsFramework::AssetSystem::GetAbsoluteAssetDatabaseLocationResponse; using GetRelativeProductPathFromFullSourceOrProductPathRequest = AzFramework::AssetSystem::GetRelativeProductPathFromFullSourceOrProductPathRequest; using GetRelativeProductPathFromFullSourceOrProductPathResponse = AzFramework::AssetSystem::GetRelativeProductPathFromFullSourceOrProductPathResponse; + using GenerateRelativeSourcePathRequest = AzFramework::AssetSystem::GenerateRelativeSourcePathRequest; + using GenerateRelativeSourcePathResponse = AzFramework::AssetSystem::GenerateRelativeSourcePathResponse; using GetFullSourcePathFromRelativeProductPathRequest = AzFramework::AssetSystem::GetFullSourcePathFromRelativeProductPathRequest; using GetFullSourcePathFromRelativeProductPathResponse = AzFramework::AssetSystem::GetFullSourcePathFromRelativeProductPathResponse; diff --git a/Code/Tools/AssetProcessor/native/tests/AssetCatalog/AssetCatalogUnitTests.cpp b/Code/Tools/AssetProcessor/native/tests/AssetCatalog/AssetCatalogUnitTests.cpp index 3d9ecd3f5e..303f0ad0e8 100644 --- a/Code/Tools/AssetProcessor/native/tests/AssetCatalog/AssetCatalogUnitTests.cpp +++ b/Code/Tools/AssetProcessor/native/tests/AssetCatalog/AssetCatalogUnitTests.cpp @@ -224,20 +224,28 @@ namespace AssetProcessor dbConn->SetScanFolder(newScanFolder); } - // build some default configs. - void BuildConfig(const QDir& tempPath, AssetDatabaseConnection* dbConn, PlatformConfiguration& config) + virtual void AddScanFolders( + const QDir& tempPath, AssetDatabaseConnection* dbConn, PlatformConfiguration& config, + const AZStd::vector& platforms) { - config.EnablePlatform({ "pc" ,{ "desktop", "renderer" } }, true); - config.EnablePlatform({ "es3" ,{ "mobile", "renderer" } }, true); - config.EnablePlatform({ "fandango" ,{ "console", "renderer" } }, false); - AZStd::vector platforms; - config.PopulatePlatformsForScanFolder(platforms); // PATH DisplayName PortKey root recurse platforms order AddScanFolder(ScanFolderInfo(tempPath.filePath("subfolder4"), "subfolder4", "subfolder4", false, false, platforms, -6), config, dbConn); // subfolder 4 overrides subfolder3 AddScanFolder(ScanFolderInfo(tempPath.filePath("subfolder3"), "subfolder3", "subfolder3", false, false, platforms, -5), config, dbConn); // subfolder 3 overrides subfolder2 AddScanFolder(ScanFolderInfo(tempPath.filePath("subfolder2"), "subfolder2", "subfolder2", false, true, platforms, -2), config, dbConn); // subfolder 2 overrides subfolder1 AddScanFolder(ScanFolderInfo(tempPath.filePath("subfolder1"), "subfolder1", "subfolder1", false, true, platforms, -1), config, dbConn); // subfolder1 overrides root AddScanFolder(ScanFolderInfo(tempPath.absolutePath(), "temp", "tempfolder", true, false, platforms, 0), config, dbConn); // add the root + } + + // build some default configs. + void BuildConfig(const QDir& tempPath, AssetDatabaseConnection* dbConn, PlatformConfiguration& config) + { + config.EnablePlatform({ "pc" ,{ "desktop", "renderer" } }, true); + config.EnablePlatform({ "android" ,{ "mobile", "renderer" } }, true); + config.EnablePlatform({ "fandango" ,{ "console", "renderer" } }, false); + AZStd::vector platforms; + config.PopulatePlatformsForScanFolder(platforms); + + AddScanFolders(tempPath, dbConn, config, platforms); config.AddMetaDataType("exportsettings", QString()); @@ -246,22 +254,22 @@ namespace AssetProcessor AssetRecognizer rec; AssetPlatformSpec specpc; - AssetPlatformSpec speces3; + AssetPlatformSpec specandroid; - speces3.m_extraRCParams = "somerandomparam"; + specandroid.m_extraRCParams = "somerandomparam"; rec.m_name = "random files"; rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.random", AssetBuilderSDK::AssetBuilderPattern::Wildcard); rec.m_platformSpecs.insert("pc", specpc); config.AddRecognizer(rec); specpc.m_extraRCParams = ""; // blank must work - speces3.m_extraRCParams = "testextraparams"; + specandroid.m_extraRCParams = "testextraparams"; const char* builderTxt1Name = "txt files"; rec.m_name = builderTxt1Name; rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.txt", AssetBuilderSDK::AssetBuilderPattern::Wildcard); rec.m_platformSpecs.insert("pc", specpc); - rec.m_platformSpecs.insert("es3", speces3); + rec.m_platformSpecs.insert("android", specandroid); config.AddRecognizer(rec); @@ -272,7 +280,7 @@ namespace AssetProcessor ignore_rec.m_name = "ignore files"; ignore_rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.ignore", AssetBuilderSDK::AssetBuilderPattern::Wildcard); ignore_rec.m_platformSpecs.insert("pc", specpc); - ignore_rec.m_platformSpecs.insert("es3", ignore_spec); + ignore_rec.m_platformSpecs.insert("android", ignore_spec); config.AddRecognizer(ignore_rec); ExcludeAssetRecognizer excludeRecogniser; @@ -359,7 +367,8 @@ namespace AssetProcessor return false; } - // Calls the GetFullSourcePathFromRelativeProductPath function and checks the return results, returning true if it matches both of the expected results + // Calls the GetFullSourcePathFromRelativeProductPath function and checks the return results, returning true if it matches both of + // the expected results bool TestGetFullSourcePath(const QString& fileToCheck, const QDir& tempPath, bool expectToFind, const char* expectedPath) { bool fullPathfound = false; @@ -531,6 +540,177 @@ namespace AssetProcessor ASSERT_TRUE(TestGetRelativeProductPath(fileToCheck, true, { "aaa/basefile.txt" })); } + class AssetCatalogTestRelativeSourcePath : public AssetCatalogTest + { + public: + QDir GetRoot() + { + // Return an OS-friendly absolute root directory for our tests ("C:/sourceRoot" or "/sourceRoot"). It doesn't + // need to exist, it just needs to be an absolute path. + return QDir::root().filePath("sourceRoot"); + } + + // Set up custom scan folders for the "relative source path" tests, so that we can try out specific combinations of watch folders + void AddScanFolders( + [[maybe_unused]] const QDir& tempPath, AssetDatabaseConnection* dbConn, PlatformConfiguration& config, + const AZStd::vector& platforms) override + { + QDir root = GetRoot(); + + // This will set up the following watch folders, in highest to lowest priority: + + // /sourceRoot/recurseNested/nested (recurse) + // /sourceRoot/noRecurse (no recurse) + // /sourceRoot/recurseNotNested (recurse) + // /sourceRoot/recurseNested (recurse) + + AddScanFolder( + ScanFolderInfo(root.filePath("recurseNested/nested"), "nested", "nested", false, true, platforms, -4), config, dbConn); + AddScanFolder( + ScanFolderInfo(root.filePath("noRecurse"), "noRecurse", "noRecurse", false, false, platforms, -3), config, dbConn); + AddScanFolder( + ScanFolderInfo(root.filePath("recurseNotNested"), "recurseNotNested", "recurseNotNested", false, true, platforms, -2), + config, dbConn); + AddScanFolder( + ScanFolderInfo(root.filePath("recurseNested"), "recurseNested", "recurseNested", false, true, platforms, -1), + config, dbConn); + } + + // Calls the GenerateRelativeSourcePath function and validates that the results match the expected inputs. + void TestGetRelativeSourcePath( + const AZStd::string& sourcePath, bool expectedToFind, const AZStd::string& expectedPath, const AZStd::string& expectedRoot) + { + bool relPathFound = false; + AZStd::string relPath; + AZStd::string rootFolder; + + AzToolsFramework::AssetSystemRequestBus::BroadcastResult( + relPathFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GenerateRelativeSourcePath, sourcePath, + relPath, rootFolder); + + EXPECT_EQ(relPathFound, expectedToFind); + EXPECT_EQ(relPath, expectedPath); + EXPECT_EQ(rootFolder, expectedRoot); + } + }; + + TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_EmptySourcePath_ReturnsNoMatch) + { + // Test passes in an empty source path, which shouldn't produce a valid result. + // Input: empty source path + // Output: empty, not found result + TestGetRelativeSourcePath("", false, "", ""); + } + + TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_AbsolutePathOutsideWatchFolders_ReturnsNoMatch) + { + // Test passes in an invalid absolute source path, which shouldn't produce a valid result. + // Input: "/sourceRoot/noWatchFolder/test.txt" + // Output: not found result, which also returns the input as the relative file name + QDir watchFolder = GetRoot().filePath("noWatchFolder/"); + QString fileToCheck = watchFolder.filePath("test.txt"); + + TestGetRelativeSourcePath(fileToCheck.toUtf8().constData(), false, fileToCheck.toUtf8().constData(), ""); + } + + TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_AbsolutePathUnderWatchFolder_ReturnsRelativePath) + { + // Test passes in a valid absolute source path, which should produce a valid relative path + // Input: "/sourceRoot/noRecurse/test.txt" + // Output: "test.txt" in folder "/sourceRoot/noRecurse/" + QDir watchFolder = GetRoot().filePath("noRecurse/"); + QString fileToCheck = watchFolder.filePath("test.txt"); + + TestGetRelativeSourcePath(fileToCheck.toUtf8().constData(), true, "test.txt", watchFolder.path().toUtf8().constData()); + } + + TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_AbsolutePathUnderNestedWatchFolders_ReturnsRelativePath) + { + // Test passes in a valid absolute source path that matches a watch folder and a nested watch folder. + // The output relative path should match the nested folder, because the nested folder has a higher priority registered with the AP. + // Input: "/sourceRoot/recurseNested/nested/test.txt" + // Output: "test.txt" in folder "/sourceRoot/recurseNested/nested/" + QDir watchFolder = GetRoot().filePath("recurseNested/nested/"); + QString fileToCheck = watchFolder.filePath("test.txt"); + + TestGetRelativeSourcePath(fileToCheck.toUtf8().constData(), true, "test.txt", watchFolder.path().toUtf8().constData()); + } + + TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_BareFileNameValidInWatchFolder_ReturnsHighestPriorityWatchFolder) + { + // Test passes in a simple file name. The output should be relative to the highest-priority watch folder. + // Input: "test.txt" + // Output: "test.txt" in folder "/sourceRoot/recurseNested/nested/" + QDir watchFolder = GetRoot().filePath("recurseNested/nested/"); + + TestGetRelativeSourcePath("test.txt", true, "test.txt", watchFolder.path().toUtf8().constData()); + } + + TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_RelativePathValidInWatchFolder_ReturnsHighestPriorityWatchFolder) + { + // Test passes in a relative path. The output should preserve the relative path, but list it as relative to the highest-priority + // watch folder. + // Input: "a/b/c/test.txt" + // Output: "a/b/c/test.txt" in folder "/sourceRoot/recurseNested/nested/" + QDir watchFolder = GetRoot().filePath("recurseNested/nested/"); + + TestGetRelativeSourcePath("a/b/c/test.txt", true, "a/b/c/test.txt", watchFolder.path().toUtf8().constData()); + } + + TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_RelativePathNotInWatchFolder_ReturnsNoMatch) + { + // Test passes in a relative path that "backs up" two directories. This will be invalid, because no matter which watch directory + // we start at, the result will be outside of any watch directory. + // Input: "../../test.txt" + // Output: not found result, which also returns the input as the relative file name + TestGetRelativeSourcePath("../../test.txt", false, "../../test.txt", ""); + } + + TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_RelativePathValidFromNestedWatchFolder_ReturnsOuterFolder) + { + // Test passes in a relative path that "backs up" one directory. This will produce a valid result, because we can back up from + // the "recurseNested/nested/" watch folder to "recurseNested", which is also a valid watch folder. + // Input: "../test.txt" + // Output: "test.txt" in folder "/sourceRoot/recurseNested" + QDir watchFolder = GetRoot().filePath("recurseNested/"); + TestGetRelativeSourcePath("../test.txt", true, "test.txt", watchFolder.path().toUtf8().constData()); + } + + TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_RelativePathMovesToParentWatchFolder_ReturnsOuterFolder) + { + // Test passes in a relative path that backs up one directory and then forward into a directory. This will produce a valid + // result, because it can validly start in the highest-priority watch folder (recurseNested/nested), move back one into the + // outer watch folder (recurseNested), and then have a subdirectory within it. + // Note that it would also be valid to move from recurseNested to recurseNotNested, but that won't be the result of this test + // because that's a lower-priority match. + // Input: "../recurseNotNested/test.txt" + // Output: "recurseNotNested/test.txt" in folder "/sourceRoot/recurseNested/" + QDir watchFolder = GetRoot().filePath("recurseNested/"); + + TestGetRelativeSourcePath("../recurseNotNested/test.txt", true, "recurseNotNested/test.txt", watchFolder.path().toUtf8().constData()); + } + + TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_RelativePathMovesToSiblingWatchFolder_ReturnsSiblingFolder) + { + // Test passes in a relative path that backs up two directories and then forward into a directory. This will produce a valid + // result, because it can validly start in the recurseNested/nested folder, move back two folders, then forward into the sibling + // recurseNotNested folder. The result will be a relative path to the sibling folder. + // Input: "../../recurseNotNested/test.txt" + // Output: "test.txt" in folder "/sourceRoot/recurseNotNested/" + QDir watchFolder = GetRoot().filePath("recurseNotNested/"); + + TestGetRelativeSourcePath("../../recurseNotNested/test.txt", true, "test.txt", watchFolder.path().toUtf8().constData()); + } + + TEST_F(AssetCatalogTestRelativeSourcePath, GenerateRelativeSourcePath_RelativePathBacksOutOfWatchFolder_ReturnsNoMatch) + { + // Test passes in a relative path that adds a directory, then "backs up" three directories. This will be invalid, because no + // matter which watch directory we start at, the result will be outside of any watch directory. + // Input: "../test.txt" + // Output: "test.txt" in folder "/sourceRoot/recurseNested" + TestGetRelativeSourcePath("a/../../../test.txt", false, "a/../../../test.txt", ""); + } + class AssetCatalogTest_GetFullSourcePath : public AssetCatalogTest { @@ -912,7 +1092,7 @@ namespace AssetProcessor { AssetCatalogTest::SetUp(); m_platforms.push_back("pc"); - m_platforms.push_back("es3"); + m_platforms.push_back("android"); // 4 products for one platform, 1 product for the other. m_platformToProductsForSourceWithDifferentProducts["pc"].push_back("subfolder3/basefilez.arc2"); @@ -920,7 +1100,7 @@ namespace AssetProcessor m_platformToProductsForSourceWithDifferentProducts["pc"].push_back("subfolder3/basefile.arc2"); m_platformToProductsForSourceWithDifferentProducts["pc"].push_back("subfolder3/basefile.azm2"); - m_platformToProductsForSourceWithDifferentProducts["es3"].push_back("subfolder3/es3exclusivefile.azm2"); + m_platformToProductsForSourceWithDifferentProducts["android"].push_back("subfolder3/androidexclusivefile.azm2"); m_sourceFileWithDifferentProductsPerPlatform = AZ::Uuid::CreateString("{38032FC9-2838-4D6A-9DA0-79E5E4F20C1B}"); m_sourceFileWithDependency = AZ::Uuid::CreateString("{807C4174-1D19-42AD-B8BC-A59291D9388C}"); @@ -933,7 +1113,7 @@ namespace AssetProcessor // resulting in image processing jobs having different products per platform. Because of this, the material jobs will then have different // dependencies per platform, because each material will depend on a referenced texture and all of that texture's mipmaps. - // Add a source file with 4 products on pc, but 1 on es3 + // Add a source file with 4 products on pc, but 1 on android bool result = AddSourceAndJobForMultiplePlatforms( "subfolder3", "MultiplatformFile.txt", @@ -948,7 +1128,7 @@ namespace AssetProcessor result = AddSourceAndJobForMultiplePlatforms("subfolder3", "FileWithDependency.txt", &(m_data->m_dbConn), sourceFileWithSameProductsJobsPerPlatform, m_platforms, m_sourceFileWithDependency); EXPECT_TRUE(result); - const AZStd::string fileWithDependencyProductPath = "subfolder3/es3exclusivefile.azm2"; + const AZStd::string fileWithDependencyProductPath = "subfolder3/androidexclusivefile.azm2"; for (const AZStd::string& platform : m_platforms) { diff --git a/Code/Tools/AssetProcessor/native/tests/AssetProcessorMessagesTests.cpp b/Code/Tools/AssetProcessor/native/tests/AssetProcessorMessagesTests.cpp index c33943f9a7..04949c82a9 100644 --- a/Code/Tools/AssetProcessor/native/tests/AssetProcessorMessagesTests.cpp +++ b/Code/Tools/AssetProcessor/native/tests/AssetProcessorMessagesTests.cpp @@ -265,6 +265,9 @@ namespace AssetProcessorMessagesTests addPairFunc(new GetFullSourcePathFromRelativeProductPathRequest(), new GetFullSourcePathFromRelativeProductPathResponse()); addPairFunc(new GetRelativeProductPathFromFullSourceOrProductPathRequest(), new GetRelativeProductPathFromFullSourceOrProductPathResponse()); + addPairFunc( + new GenerateRelativeSourcePathRequest(), + new GenerateRelativeSourcePathResponse()); addPairFunc(new SourceAssetInfoRequest(), new SourceAssetInfoResponse()); addPairFunc(new SourceAssetProductsInfoRequest(), new SourceAssetProductsInfoResponse()); addPairFunc(new GetScanFoldersRequest(), new GetScanFoldersResponse()); diff --git a/Code/Tools/AssetProcessor/native/tests/assetBuilderSDK/assetBuilderSDKTest.cpp b/Code/Tools/AssetProcessor/native/tests/assetBuilderSDK/assetBuilderSDKTest.cpp index c2931c6a09..671d8d96a9 100644 --- a/Code/Tools/AssetProcessor/native/tests/assetBuilderSDK/assetBuilderSDKTest.cpp +++ b/Code/Tools/AssetProcessor/native/tests/assetBuilderSDK/assetBuilderSDKTest.cpp @@ -28,7 +28,7 @@ namespace AssetProcessor createJobsRequest.m_enabledPlatforms = { { "pc", {} - }, { "es3", {} + }, { "android", {} } }; ASSERT_EQ(createJobsRequest.GetEnabledPlatformsCount(), 2); @@ -48,19 +48,19 @@ namespace AssetProcessor ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_NONE); createJobsRequest.m_enabledPlatforms = { - { "es3", {} + { "android", {} } }; - ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(0), AssetBuilderSDK::Platform_ES3); + ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(0), AssetBuilderSDK::Platform_ANDROID); ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_NONE); createJobsRequest.m_enabledPlatforms = { { "pc", {} - }, { "es3", {} + }, { "android", {} } }; ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(0), AssetBuilderSDK::Platform_PC); - ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_ES3); + ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_ANDROID); ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(2), AssetBuilderSDK::Platform_NONE); createJobsRequest.m_enabledPlatforms = { @@ -72,24 +72,24 @@ namespace AssetProcessor createJobsRequest.m_enabledPlatforms = { { "pc", {} - }, { "es3", {} + }, { "android", {} }, { "ios", {} - }, { "osx_gl", {} + }, { "mac", {} } }; ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(0), AssetBuilderSDK::Platform_PC); - ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_ES3); + ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_ANDROID); ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(2), AssetBuilderSDK::Platform_IOS); - ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(3), AssetBuilderSDK::Platform_OSX); + ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(3), AssetBuilderSDK::Platform_MAC); ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(4), AssetBuilderSDK::Platform_NONE); createJobsRequest.m_enabledPlatforms = { { "pc", {} - }, { "es3", {} + }, { "android", {} } }; ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(0), AssetBuilderSDK::Platform_PC); - ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_ES3); + ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(1), AssetBuilderSDK::Platform_ANDROID); ASSERT_EQ(createJobsRequest.GetEnabledPlatformAt(2), AssetBuilderSDK::Platform_NONE); // using a deprecated API should have generated warnings. // but we can't test for it because these warnings are WarningOnce and some other unit test might have already triggered it @@ -106,23 +106,23 @@ namespace AssetProcessor } }; ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_PC)); - ASSERT_FALSE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_ES3)); + ASSERT_FALSE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_ANDROID)); createJobsRequest.m_enabledPlatforms = { { "pc", {} - }, { "es3", {} + }, { "android", {} } }; ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_PC)); - ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_ES3)); + ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_ANDROID)); createJobsRequest.m_enabledPlatforms = { { "pc", {} - }, { "es3", {} + }, { "android", {} } }; ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_PC)); - ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_ES3)); + ASSERT_TRUE(createJobsRequest.IsPlatformEnabled(AssetBuilderSDK::Platform_ANDROID)); // using a deprecated API should have generated warnings. // but we can't test for it because these warnings are WarningOnce and some other unit test might have already triggered it } @@ -133,9 +133,9 @@ namespace AssetProcessor UnitTestUtils::AssertAbsorber absorb; ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_PC)); - ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_ES3)); + ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_ANDROID)); ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_IOS)); - ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_OSX)); + ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_MAC)); ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_PROVO)); ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_SALEM)); ASSERT_TRUE(createJobsRequest.IsPlatformValid(AssetBuilderSDK::Platform_JASPER)); diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp index d592ecb012..bd99cf7a94 100644 --- a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp +++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp @@ -4020,15 +4020,15 @@ TEST_F(ModtimeScanningTest, ModtimeSkipping_EnablePlatform_ShouldProcessFilesFor m_assetProcessorManager->m_allowModtimeSkippingFeature = true; AssetUtilities::SetUseFileHashOverride(true, true); - // Enable es3 platform after the initial SetUp has already processed the files for pc + // Enable android platform after the initial SetUp has already processed the files for pc QDir tempPath(m_tempDir.path()); - AssetBuilderSDK::PlatformInfo es3Platform("es3", { "host", "renderer" }); - m_config->EnablePlatform(es3Platform, true); + AssetBuilderSDK::PlatformInfo androidPlatform("android", { "host", "renderer" }); + m_config->EnablePlatform(androidPlatform, true); // There's no way to remove scanfolders and adding a new one after enabling the platform will cause the pc assets to build as well, which we don't want // Instead we'll just const cast the vector and modify the enabled platforms for the scanfolder auto& platforms = const_cast&>(m_config->GetScanFolderAt(0).GetPlatforms()); - platforms.push_back(es3Platform); + platforms.push_back(androidPlatform); // We need the builder fingerprints to be updated to reflect the newly enabled platform m_assetProcessorManager->ComputeBuilderDirty(); @@ -4036,10 +4036,10 @@ TEST_F(ModtimeScanningTest, ModtimeSkipping_EnablePlatform_ShouldProcessFilesFor QSet filePaths = BuildFileSet(); SimulateAssetScanner(filePaths); - ExpectWork(4, 2); // CreateJobs = 4, 2 files * 2 platforms. ProcessJobs = 2, just the es3 platform jobs (pc is already processed) + ExpectWork(4, 2); // CreateJobs = 4, 2 files * 2 platforms. ProcessJobs = 2, just the android platform jobs (pc is already processed) - ASSERT_TRUE(m_data->m_processResults[0].m_destinationPath.contains("es3")); - ASSERT_TRUE(m_data->m_processResults[1].m_destinationPath.contains("es3")); + ASSERT_TRUE(m_data->m_processResults[0].m_destinationPath.contains("android")); + ASSERT_TRUE(m_data->m_processResults[1].m_destinationPath.contains("android")); } TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyTimestamp) diff --git a/Code/Tools/AssetProcessor/native/tests/platformconfiguration/platformconfigurationtests.cpp b/Code/Tools/AssetProcessor/native/tests/platformconfiguration/platformconfigurationtests.cpp index 829d63472d..9c80b267eb 100644 --- a/Code/Tools/AssetProcessor/native/tests/platformconfiguration/platformconfigurationtests.cpp +++ b/Code/Tools/AssetProcessor/native/tests/platformconfiguration/platformconfigurationtests.cpp @@ -120,14 +120,14 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Regular_Platforms) // verify the data. ASSERT_NE(config.GetPlatformByIdentifier(AzToolsFramework::AssetSystem::GetHostAssetPlatform()), nullptr); - ASSERT_NE(config.GetPlatformByIdentifier("es3"), nullptr); + ASSERT_NE(config.GetPlatformByIdentifier("android"), nullptr); ASSERT_NE(config.GetPlatformByIdentifier("server"), nullptr); - ASSERT_TRUE(config.GetPlatformByIdentifier("es3")->HasTag("mobile")); - ASSERT_TRUE(config.GetPlatformByIdentifier("es3")->HasTag("renderer")); - ASSERT_TRUE(config.GetPlatformByIdentifier("es3")->HasTag("android")); + ASSERT_TRUE(config.GetPlatformByIdentifier("android")->HasTag("mobile")); + ASSERT_TRUE(config.GetPlatformByIdentifier("android")->HasTag("renderer")); + ASSERT_TRUE(config.GetPlatformByIdentifier("android")->HasTag("android")); ASSERT_TRUE(config.GetPlatformByIdentifier("server")->HasTag("server")); - ASSERT_FALSE(config.GetPlatformByIdentifier("es3")->HasTag("server")); + ASSERT_FALSE(config.GetPlatformByIdentifier("android")->HasTag("server")); ASSERT_FALSE(config.GetPlatformByIdentifier("server")->HasTag("renderer")); } @@ -397,7 +397,7 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolderP AZStd::vector platforms = config.GetScanFolderAt(0).GetPlatforms(); ASSERT_EQ(platforms.size(), 4); ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo(AzToolsFramework::AssetSystem::GetHostAssetPlatform(), AZStd::unordered_set{})) != platforms.end()); - ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("es3", AZStd::unordered_set{})) != platforms.end()); + ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("android", AZStd::unordered_set{})) != platforms.end()); ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("ios", AZStd::unordered_set{})) != platforms.end()); ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("server", AZStd::unordered_set{})) != platforms.end()); @@ -405,12 +405,12 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_RegularScanfolderP platforms = config.GetScanFolderAt(1).GetPlatforms(); ASSERT_EQ(platforms.size(), 2); ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo(AzToolsFramework::AssetSystem::GetHostAssetPlatform(), AZStd::unordered_set{})) != platforms.end()); - ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("es3", AZStd::unordered_set{})) != platforms.end()); + ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("android", AZStd::unordered_set{})) != platforms.end()); ASSERT_EQ(config.GetScanFolderAt(2).GetDisplayName(), QString("folder1output")); platforms = config.GetScanFolderAt(2).GetPlatforms(); ASSERT_EQ(platforms.size(), 1); - ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("es3", AZStd::unordered_set{})) != platforms.end()); + ASSERT_TRUE(AZStd::find(platforms.begin(), platforms.end(), AssetBuilderSDK::PlatformInfo("android", AZStd::unordered_set{})) != platforms.end()); ASSERT_EQ(config.GetScanFolderAt(3).GetDisplayName(), QString("folder2output")); platforms = config.GetScanFolderAt(3).GetPlatforms(); @@ -454,7 +454,7 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Recognizers) using namespace AzToolsFramework::AssetSystem; using namespace AssetProcessor; #if defined(AZ_PLATFORM_WINDOWS) - const char* platformWhichIsNotCurrentPlatform = "osx_gl"; + const char* platformWhichIsNotCurrentPlatform = "mac"; #else const char* platformWhichIsNotCurrentPlatform = "pc"; #endif @@ -475,27 +475,27 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Recognizers) ASSERT_EQ(recogs["i_caf"].m_patternMatcher.GetBuilderPattern().m_pattern, "*.i_caf"); ASSERT_EQ(recogs["i_caf"].m_patternMatcher.GetBuilderPattern().m_type, AssetBuilderSDK::AssetBuilderPattern::Wildcard); ASSERT_EQ(recogs["i_caf"].m_platformSpecs.size(), 2); - ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains("es3")); + ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains("android")); ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform())); ASSERT_FALSE(recogs["i_caf"].m_platformSpecs.contains("server")); // server has been set to skip. - ASSERT_EQ(recogs["i_caf"].m_platformSpecs["es3"].m_extraRCParams, "mobile"); + ASSERT_EQ(recogs["i_caf"].m_platformSpecs["android"].m_extraRCParams, "mobile"); ASSERT_EQ(recogs["i_caf"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "defaultparams"); ASSERT_TRUE(recogs.contains("caf")); - ASSERT_TRUE(recogs["caf"].m_platformSpecs.contains("es3")); + ASSERT_TRUE(recogs["caf"].m_platformSpecs.contains("android")); ASSERT_TRUE(recogs["caf"].m_platformSpecs.contains("server")); ASSERT_TRUE(recogs["caf"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform())); ASSERT_EQ(recogs["caf"].m_platformSpecs.size(), 3); - ASSERT_EQ(recogs["caf"].m_platformSpecs["es3"].m_extraRCParams, "rendererparams"); + ASSERT_EQ(recogs["caf"].m_platformSpecs["android"].m_extraRCParams, "rendererparams"); ASSERT_EQ(recogs["caf"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "rendererparams"); ASSERT_EQ(recogs["caf"].m_platformSpecs["server"].m_extraRCParams, "copy"); ASSERT_TRUE(recogs.contains("mov")); - ASSERT_TRUE(recogs["mov"].m_platformSpecs.contains("es3")); + ASSERT_TRUE(recogs["mov"].m_platformSpecs.contains("android")); ASSERT_TRUE(recogs["mov"].m_platformSpecs.contains("server")); ASSERT_TRUE(recogs["mov"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform())); ASSERT_EQ(recogs["mov"].m_platformSpecs.size(), 3); - ASSERT_EQ(recogs["mov"].m_platformSpecs["es3"].m_extraRCParams, "platformspecificoverride"); + ASSERT_EQ(recogs["mov"].m_platformSpecs["android"].m_extraRCParams, "platformspecificoverride"); ASSERT_EQ(recogs["mov"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "rendererparams"); ASSERT_EQ(recogs["mov"].m_platformSpecs["server"].m_extraRCParams, "copy"); @@ -503,27 +503,27 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Recognizers) // (but platforms can override it) ASSERT_TRUE(recogs.contains("rend")); ASSERT_TRUE(recogs["rend"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform())); - ASSERT_TRUE(recogs["rend"].m_platformSpecs.contains("es3")); + ASSERT_TRUE(recogs["rend"].m_platformSpecs.contains("android")); ASSERT_TRUE(recogs["rend"].m_platformSpecs.contains("server")); ASSERT_FALSE(recogs["rend"].m_platformSpecs.contains(platformWhichIsNotCurrentPlatform)); // this is not an enabled platform and should not be there. ASSERT_EQ(recogs["rend"].m_platformSpecs.size(), 3); ASSERT_EQ(recogs["rend"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "rendererparams"); - ASSERT_EQ(recogs["rend"].m_platformSpecs["es3"].m_extraRCParams, "rendererparams"); + ASSERT_EQ(recogs["rend"].m_platformSpecs["android"].m_extraRCParams, "rendererparams"); ASSERT_EQ(recogs["rend"].m_platformSpecs["server"].m_extraRCParams, ""); // default if not specified is empty string ASSERT_TRUE(recogs.contains("alldefault")); ASSERT_TRUE(recogs["alldefault"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform())); - ASSERT_TRUE(recogs["alldefault"].m_platformSpecs.contains("es3")); + ASSERT_TRUE(recogs["alldefault"].m_platformSpecs.contains("android")); ASSERT_TRUE(recogs["alldefault"].m_platformSpecs.contains("server")); ASSERT_FALSE(recogs["alldefault"].m_platformSpecs.contains(platformWhichIsNotCurrentPlatform)); // this is not an enabled platform and should not be there. ASSERT_EQ(recogs["alldefault"].m_platformSpecs.size(), 3); ASSERT_EQ(recogs["alldefault"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, ""); - ASSERT_EQ(recogs["alldefault"].m_platformSpecs["es3"].m_extraRCParams, ""); + ASSERT_EQ(recogs["alldefault"].m_platformSpecs["android"].m_extraRCParams, ""); ASSERT_EQ(recogs["alldefault"].m_platformSpecs["server"].m_extraRCParams, ""); ASSERT_TRUE(recogs.contains("skipallbutone")); ASSERT_FALSE(recogs["skipallbutone"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform())); - ASSERT_FALSE(recogs["skipallbutone"].m_platformSpecs.contains("es3")); + ASSERT_FALSE(recogs["skipallbutone"].m_platformSpecs.contains("android")); ASSERT_TRUE(recogs["skipallbutone"].m_platformSpecs.contains("server")); // server is only one enabled (set to copy) ASSERT_EQ(recogs["skipallbutone"].m_platformSpecs.size(), 1); ASSERT_EQ(recogs["skipallbutone"].m_platformSpecs["server"].m_extraRCParams, "copy"); @@ -549,7 +549,7 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Overrides) // verify the data. ASSERT_NE(config.GetPlatformByIdentifier(AzToolsFramework::AssetSystem::GetHostAssetPlatform()), nullptr); - ASSERT_NE(config.GetPlatformByIdentifier("es3"), nullptr); + ASSERT_NE(config.GetPlatformByIdentifier("android"), nullptr); ASSERT_NE(config.GetPlatformByIdentifier("provo"), nullptr); // this override swaps server with provo in that it turns ON provo, turns off server ASSERT_EQ(config.GetPlatformByIdentifier("server"), nullptr); // this should be off due to overrides @@ -566,11 +566,11 @@ TEST_F(PlatformConfigurationUnitTests, TestFailReadConfigFile_Overrides) ASSERT_EQ(recogs["i_caf"].m_patternMatcher.GetBuilderPattern().m_pattern, "*.i_caf"); ASSERT_EQ(recogs["i_caf"].m_patternMatcher.GetBuilderPattern().m_type, AssetBuilderSDK::AssetBuilderPattern::Wildcard); ASSERT_EQ(recogs["i_caf"].m_platformSpecs.size(), 3); - ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains("es3")); + ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains("android")); ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains("provo")); ASSERT_TRUE(recogs["i_caf"].m_platformSpecs.contains(AzToolsFramework::AssetSystem::GetHostAssetPlatform())); ASSERT_FALSE(recogs["i_caf"].m_platformSpecs.contains("server")); // server has been set to skip. - ASSERT_EQ(recogs["i_caf"].m_platformSpecs["es3"].m_extraRCParams, "mobile"); + ASSERT_EQ(recogs["i_caf"].m_platformSpecs["android"].m_extraRCParams, "mobile"); ASSERT_EQ(recogs["i_caf"].m_platformSpecs[AzToolsFramework::AssetSystem::GetHostAssetPlatform()].m_extraRCParams, "defaultparams"); ASSERT_EQ(recogs["i_caf"].m_platformSpecs["provo"].m_extraRCParams, "copy"); diff --git a/Code/Tools/AssetProcessor/native/unittests/AssetProcessorManagerUnitTests.cpp b/Code/Tools/AssetProcessor/native/unittests/AssetProcessorManagerUnitTests.cpp index 5940caadb7..079cdb7c66 100644 --- a/Code/Tools/AssetProcessor/native/unittests/AssetProcessorManagerUnitTests.cpp +++ b/Code/Tools/AssetProcessor/native/unittests/AssetProcessorManagerUnitTests.cpp @@ -51,6 +51,8 @@ namespace AssetProcessor public: using GetRelativeProductPathFromFullSourceOrProductPathRequest = AzFramework::AssetSystem::GetRelativeProductPathFromFullSourceOrProductPathRequest; using GetRelativeProductPathFromFullSourceOrProductPathResponse = AzFramework::AssetSystem::GetRelativeProductPathFromFullSourceOrProductPathResponse; + using GenerateRelativeSourcePathRequest = AzFramework::AssetSystem::GenerateRelativeSourcePathRequest; + using GenerateRelativeSourcePathResponse = AzFramework::AssetSystem::GenerateRelativeSourcePathResponse; using GetFullSourcePathFromRelativeProductPathRequest = AzFramework::AssetSystem::GetFullSourcePathFromRelativeProductPathRequest; using GetFullSourcePathFromRelativeProductPathResponse = AzFramework::AssetSystem::GetFullSourcePathFromRelativeProductPathResponse; }; @@ -88,34 +90,34 @@ namespace AssetProcessor //AZ_TracePrintf("test", "-------------------------\n"); } - void ComputeFingerprints(unsigned int& fingerprintForPC, unsigned int& fingerprintForES3, PlatformConfiguration& config, QString scanFolderPath, QString relPath) + void ComputeFingerprints(unsigned int& fingerprintForPC, unsigned int& fingerprintForANDROID, PlatformConfiguration& config, QString scanFolderPath, QString relPath) { QString extraInfoForPC; - QString extraInfoForES3; + QString extraInfoForANDROID; RecognizerPointerContainer output; QString filePath = scanFolderPath + "/" + relPath; config.GetMatchingRecognizers(filePath, output); for (const AssetRecognizer* assetRecogniser : output) { extraInfoForPC.append(assetRecogniser->m_platformSpecs["pc"].m_extraRCParams); - extraInfoForES3.append(assetRecogniser->m_platformSpecs["es3"].m_extraRCParams); + extraInfoForANDROID.append(assetRecogniser->m_platformSpecs["android"].m_extraRCParams); extraInfoForPC.append(assetRecogniser->m_version); - extraInfoForES3.append(assetRecogniser->m_version); + extraInfoForANDROID.append(assetRecogniser->m_version); } - //Calculating fingerprints for the file for pc and es3 platforms + //Calculating fingerprints for the file for pc and android platforms AZ::Uuid sourceId = AZ::Uuid("{2206A6E0-FDBC-45DE-B6FE-C2FC63020BD5}"); JobEntry jobEntryPC(scanFolderPath, relPath, relPath, 0, { "pc", {"desktop", "renderer"} }, "", 0, 1, sourceId); - JobEntry jobEntryES3(scanFolderPath, relPath, relPath, 0, { "es3", {"mobile", "renderer"} }, "", 0, 2, sourceId); + JobEntry jobEntryANDROID(scanFolderPath, relPath, relPath, 0, { "android", {"mobile", "renderer"} }, "", 0, 2, sourceId); JobDetails jobDetailsPC; jobDetailsPC.m_extraInformationForFingerprinting = extraInfoForPC.toUtf8().constData(); jobDetailsPC.m_jobEntry = jobEntryPC; - JobDetails jobDetailsES3; - jobDetailsES3.m_extraInformationForFingerprinting = extraInfoForES3.toUtf8().constData(); - jobDetailsES3.m_jobEntry = jobEntryES3; + JobDetails jobDetailsANDROID; + jobDetailsANDROID.m_extraInformationForFingerprinting = extraInfoForANDROID.toUtf8().constData(); + jobDetailsANDROID.m_jobEntry = jobEntryANDROID; fingerprintForPC = AssetUtilities::GenerateFingerprint(jobDetailsPC); - fingerprintForES3 = AssetUtilities::GenerateFingerprint(jobDetailsES3); + fingerprintForANDROID = AssetUtilities::GenerateFingerprint(jobDetailsANDROID); } } @@ -240,7 +242,7 @@ namespace AssetProcessor PlatformConfiguration config; config.EnablePlatform({ "pc",{ "desktop", "renderer" } }, true); - config.EnablePlatform({ "es3",{ "mobile", "renderer" } }, true); + config.EnablePlatform({ "android",{ "mobile", "renderer" } }, true); config.EnablePlatform({ "fandago",{ "console", "renderer" } }, false); AZStd::vector platforms; config.PopulatePlatformsForScanFolder(platforms); @@ -259,9 +261,9 @@ namespace AssetProcessor AssetRecognizer rec; AssetPlatformSpec specpc; - AssetPlatformSpec speces3; + AssetPlatformSpec specandroid; - speces3.m_extraRCParams = "somerandomparam"; + specandroid.m_extraRCParams = "somerandomparam"; rec.m_name = "random files"; rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.random", AssetBuilderSDK::AssetBuilderPattern::Wildcard); rec.m_platformSpecs.insert("pc", specpc); @@ -269,13 +271,13 @@ namespace AssetProcessor UNIT_TEST_EXPECT_TRUE(mockAppManager.RegisterAssetRecognizerAsBuilder(rec)); specpc.m_extraRCParams = ""; // blank must work - speces3.m_extraRCParams = "testextraparams"; + specandroid.m_extraRCParams = "testextraparams"; const char* builderTxt1Name = "txt files"; rec.m_name = builderTxt1Name; rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.txt", AssetBuilderSDK::AssetBuilderPattern::Wildcard); rec.m_platformSpecs.insert("pc", specpc); - rec.m_platformSpecs.insert("es3", speces3); + rec.m_platformSpecs.insert("android", specandroid); config.AddRecognizer(rec); @@ -305,21 +307,21 @@ namespace AssetProcessor rec.m_testLockSource = false; specpc.m_extraRCParams = "pcparams"; - speces3.m_extraRCParams = "es3params"; + specandroid.m_extraRCParams = "androidparams"; rec.m_name = "xxx files"; rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.xxx", AssetBuilderSDK::AssetBuilderPattern::Wildcard); rec.m_platformSpecs.insert("pc", specpc); - rec.m_platformSpecs.insert("es3", speces3); + rec.m_platformSpecs.insert("android", specandroid); config.AddRecognizer(rec); mockAppManager.RegisterAssetRecognizerAsBuilder(rec); // two recognizers for the same pattern. rec.m_name = "xxx files 2 (builder2)"; specpc.m_extraRCParams = "pcparams2"; - speces3.m_extraRCParams = "es3params2"; + specandroid.m_extraRCParams = "androidparams2"; rec.m_platformSpecs.insert("pc", specpc); - rec.m_platformSpecs.insert("es3", speces3); + rec.m_platformSpecs.insert("android", specandroid); config.AddRecognizer(rec); mockAppManager.RegisterAssetRecognizerAsBuilder(rec); @@ -330,7 +332,7 @@ namespace AssetProcessor ignore_rec.m_name = "ignore files"; ignore_rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.ignore", AssetBuilderSDK::AssetBuilderPattern::Wildcard); ignore_rec.m_platformSpecs.insert("pc", specpc); - ignore_rec.m_platformSpecs.insert("es3", ignore_spec); + ignore_rec.m_platformSpecs.insert("android", ignore_spec); config.AddRecognizer(ignore_rec); mockAppManager.RegisterAssetRecognizerAsBuilder(ignore_rec); @@ -432,7 +434,7 @@ namespace AssetProcessor sortAssetToProcessResultList(processResults); - UNIT_TEST_EXPECT_TRUE(processResults.size() == 1); // 1, since we have one recognizer for .ignore, but the 'es3' platform is marked as skip + UNIT_TEST_EXPECT_TRUE(processResults.size() == 1); // 1, since we have one recognizer for .ignore, but the 'android' platform is marked as skip UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "pc")); @@ -455,16 +457,16 @@ namespace AssetProcessor sortAssetToProcessResultList(processResults); - UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and es3,since we have two recognizer for .txt file + UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier); UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier); - UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3")); - UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3")); + UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android")); + UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android")); UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc")); - QList es3JobsIndex; + QList androidJobsIndex; QList pcJobsIndex; for (int checkIdx = 0; checkIdx < 4; ++checkIdx) { @@ -662,19 +664,19 @@ namespace AssetProcessor // ---------- test successes ---------- - QStringList es3outs; - es3outs.push_back(cacheRoot.filePath(QString("es3/basefile.arc1"))); - es3outs.push_back(cacheRoot.filePath(QString("es3/basefile.arc2"))); + QStringList androidouts; + androidouts.push_back(cacheRoot.filePath(QString("android/basefile.arc1"))); + androidouts.push_back(cacheRoot.filePath(QString("android/basefile.arc2"))); // feed it the messages its waiting for (create the files) - UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[0], "products.")); - UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[1], "products.")) + UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts[0], "products.")); + UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts[1], "products.")) - //Invoke Asset Processed for es3 platform , txt files job description + //Invoke Asset Processed for android platform , txt files job description AssetBuilderSDK::ProcessJobResponse response; response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData(), AZ::Uuid::CreateNull(), 1)); - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[1].toUtf8().constData(), AZ::Uuid::CreateNull(), 2)); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData(), AZ::Uuid::CreateNull(), 1)); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[1].toUtf8().constData(), AZ::Uuid::CreateNull(), 2)); // make sure legacy SubIds get stored in the DB and in asset response messages. // also make sure they don't get filed for the wrong asset. @@ -693,8 +695,8 @@ namespace AssetProcessor UNIT_TEST_EXPECT_TRUE(changedInputResults.size() == 1); // always RELATIVE, always with the product name. - UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "es3"); - UNIT_TEST_EXPECT_TRUE(assetMessages[1].m_platform == "es3"); + UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "android"); + UNIT_TEST_EXPECT_TRUE(assetMessages[1].m_platform == "android"); UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_data == "basefile.arc1"); UNIT_TEST_EXPECT_TRUE(assetMessages[1].m_data == "basefile.arc2"); UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_type == AzFramework::AssetSystem::AssetNotificationMessage::AssetChanged); @@ -793,14 +795,14 @@ namespace AssetProcessor changedInputResults.clear(); assetMessages.clear(); - es3outs.clear(); - es3outs.push_back(cacheRoot.filePath(QString("es3/basefile.azm"))); - UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[0], "products.")); + androidouts.clear(); + androidouts.push_back(cacheRoot.filePath(QString("android/basefile.azm"))); + UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts[0], "products.")); - //Invoke Asset Processed for es3 platform , txt files2 job description + //Invoke Asset Processed for android platform , txt files2 job description response.m_outputProducts.clear(); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData())); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData())); QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[1].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response)); @@ -812,7 +814,7 @@ namespace AssetProcessor UNIT_TEST_EXPECT_TRUE(changedInputResults.size() == 1); // always RELATIVE, always with the product name. - UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "es3"); + UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "android"); UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_data == "basefile.azm"); changedInputResults.clear(); @@ -1002,11 +1004,11 @@ namespace AssetProcessor sortAssetToProcessResultList(processResults); // --------- same result as above ---------- - UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and es3,since we have two recognizer for .txt file + UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier); UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier); - UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3")); - UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3")); + UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android")); + UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android")); UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_computedFingerprint != 0); @@ -1025,25 +1027,25 @@ namespace AssetProcessor // this time make different products: - QStringList oldes3outs; + QStringList oldandroidouts; QStringList oldpcouts; - oldes3outs = es3outs; + oldandroidouts = androidouts; oldpcouts.append(pcouts); - QStringList es3outs2; + QStringList androidouts2; QStringList pcouts2; - es3outs.clear(); + androidouts.clear(); pcouts.clear(); - es3outs.push_back(cacheRoot.filePath(QString("es3/basefilea.arc1"))); - es3outs2.push_back(cacheRoot.filePath(QString("es3/basefilea.azm"))); - // note that the ES3 outs have changed + androidouts.push_back(cacheRoot.filePath(QString("android/basefilea.arc1"))); + androidouts2.push_back(cacheRoot.filePath(QString("android/basefilea.azm"))); + // note that the android outs have changed // but the pc outs are still the same. pcouts.push_back(cacheRoot.filePath(QString("pc/basefile.arc1"))); pcouts2.push_back(cacheRoot.filePath(QString("pc/basefile.azm"))); // feed it the messages its waiting for (create the files) - UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[0], "newfile.")); + UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts[0], "newfile.")); UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "newfile.")); - UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs2[0], "newfile.")); + UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts2[0], "newfile.")); UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts2[0], "newfile.")); QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents, 50); @@ -1055,12 +1057,12 @@ namespace AssetProcessor response.m_outputProducts.clear(); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData())); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData())); QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[0].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response)); response.m_outputProducts.clear(); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs2[0].toUtf8().constData())); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts2[0].toUtf8().constData())); QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[1].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response)); response.m_outputProducts.clear(); @@ -1083,12 +1085,12 @@ namespace AssetProcessor // The files removed should be the ones we did not emit this time // note that order isn't guarantee but an example output it this - // [0] Removed: ES3, basefile.arc1 - // [1] Removed: ES3, basefile.arc2 - // [2] Changed: ES3, basefilea.arc1 (added) + // [0] Removed: ANDROID, basefile.arc1 + // [1] Removed: ANDROID, basefile.arc2 + // [2] Changed: ANDROID, basefilea.arc1 (added) - // [3] Removed: ES3, basefile.azm - // [4] Changed: ES3, basefilea.azm (added) + // [3] Removed: ANDROID, basefile.azm + // [4] Changed: ANDROID, basefilea.azm (added) // [5] changed: PC, basefile.arc1 (changed) // [6] changed: PC, basefile.azm (changed) @@ -1110,18 +1112,18 @@ namespace AssetProcessor if (element.m_data == "basefilea.arc1") { UNIT_TEST_EXPECT_TRUE(element.m_type == AzFramework::AssetSystem::AssetNotificationMessage::AssetChanged); - UNIT_TEST_EXPECT_TRUE(element.m_platform == "es3"); + UNIT_TEST_EXPECT_TRUE(element.m_platform == "android"); } if (element.m_data == "basefile.arc2") { UNIT_TEST_EXPECT_TRUE(element.m_type == AzFramework::AssetSystem::AssetNotificationMessage::AssetRemoved); - UNIT_TEST_EXPECT_TRUE(element.m_platform == "es3"); + UNIT_TEST_EXPECT_TRUE(element.m_platform == "android"); } } // original products must no longer exist since it should have found and deleted them! - for (QString outFile: oldes3outs) + for (QString outFile: oldandroidouts) { UNIT_TEST_EXPECT_FALSE(QFile::exists(outFile)); } @@ -1145,11 +1147,11 @@ namespace AssetProcessor sortAssetToProcessResultList(processResults); // --------- same result as above ---------- - UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // pc and es3 + UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // pc and android UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier); UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier); - UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3")); - UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3")); + UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android")); + UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android")); UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_computedFingerprint != 0); @@ -1169,12 +1171,12 @@ namespace AssetProcessor response.m_outputProducts.clear(); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData())); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData())); QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[0].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response)); response.m_outputProducts.clear(); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs2[0].toUtf8().constData())); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts2[0].toUtf8().constData())); QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[1].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response)); response.m_outputProducts.clear(); @@ -1205,11 +1207,11 @@ namespace AssetProcessor sortAssetToProcessResultList(processResults); // --------- same result as above ---------- - UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and es3,since we have two recognizer for .txt file + UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier); UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier); - UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3")); - UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3")); + UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android")); + UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android")); UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_computedFingerprint != 0); @@ -1220,12 +1222,12 @@ namespace AssetProcessor response.m_outputProducts.clear(); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData())); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData())); QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[0].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response)); response.m_outputProducts.clear(); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs2[0].toUtf8().constData())); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts2[0].toUtf8().constData())); QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[1].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response)); response.m_outputProducts.clear(); @@ -1243,9 +1245,9 @@ namespace AssetProcessor // deleting the fingerprint file should not have erased the products UNIT_TEST_EXPECT_TRUE(QFile::exists(pcouts[0])); - UNIT_TEST_EXPECT_TRUE(QFile::exists(es3outs[0])); + UNIT_TEST_EXPECT_TRUE(QFile::exists(androidouts[0])); UNIT_TEST_EXPECT_TRUE(QFile::exists(pcouts2[0])); - UNIT_TEST_EXPECT_TRUE(QFile::exists(es3outs2[0])); + UNIT_TEST_EXPECT_TRUE(QFile::exists(androidouts2[0])); changedInputResults.clear(); assetMessages.clear(); @@ -1304,9 +1306,9 @@ namespace AssetProcessor } UNIT_TEST_EXPECT_FALSE(QFile::exists(pcouts[0])); - UNIT_TEST_EXPECT_FALSE(QFile::exists(es3outs[0])); + UNIT_TEST_EXPECT_FALSE(QFile::exists(androidouts[0])); UNIT_TEST_EXPECT_FALSE(QFile::exists(pcouts2[0])); - UNIT_TEST_EXPECT_FALSE(QFile::exists(es3outs2[0])); + UNIT_TEST_EXPECT_FALSE(QFile::exists(androidouts2[0])); changedInputResults.clear(); assetMessages.clear(); @@ -1321,28 +1323,28 @@ namespace AssetProcessor sortAssetToProcessResultList(processResults); // --------- same result as above ---------- - UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and es3,since we have two recognizer for .txt file + UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier); UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier); - UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3")); - UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3")); + UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android")); + UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android")); UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_computedFingerprint != 0); - UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[0], "newfile.")); - UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs2[0], "newfile.")); + UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts[0], "newfile.")); + UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts2[0], "newfile.")); UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts2[0], "newfile.")); // send both done messages simultaneously! response.m_outputProducts.clear(); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData())); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData())); QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[0].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response)); response.m_outputProducts.clear(); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs2[0].toUtf8().constData())); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts2[0].toUtf8().constData())); QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[1].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response)); // send one failure only for PC : @@ -1420,12 +1422,12 @@ namespace AssetProcessor UNIT_TEST_EXPECT_TRUE(changedInputResults.size() == 3); UNIT_TEST_EXPECT_TRUE(assetMessages.size() == 3); - // which should be for the ES3: + // which should be for the ANDROID: UNIT_TEST_EXPECT_TRUE(AssetUtilities::NormalizeFilePath(changedInputResults[0].first) == absolutePath); // always RELATIVE, always with the product name. UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_data == "basefilea.arc1" || assetMessages[0].m_data == "basefilea.azm"); - UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "es3"); + UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "android"); for (auto& payload : payloadList) { @@ -1526,28 +1528,28 @@ namespace AssetProcessor sortAssetToProcessResultList(processResults); // --------- same result as above ---------- - UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and es3,since we have two recognizer for .txt file + UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier); UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier); - UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3")); - UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3")); + UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android")); + UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android")); UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_computedFingerprint != 0); - es3outs.clear(); - es3outs2.clear(); + androidouts.clear(); + androidouts2.clear(); pcouts.clear(); pcouts2.clear(); - es3outs.push_back(cacheRoot.filePath(QString("es3/basefilez.arc2"))); - es3outs2.push_back(cacheRoot.filePath(QString("es3/basefileaz.azm2"))); - // note that the ES3 outs have changed + androidouts.push_back(cacheRoot.filePath(QString("android/basefilez.arc2"))); + androidouts2.push_back(cacheRoot.filePath(QString("android/basefileaz.azm2"))); + // note that the android outs have changed // but the pc outs are still the same. pcouts.push_back(cacheRoot.filePath(QString("pc/basefile.arc2"))); pcouts2.push_back(cacheRoot.filePath(QString("pc/basefile.azm2"))); - UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs[0], "newfile.")); + UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts[0], "newfile.")); UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts[0], "newfile.")); - UNIT_TEST_EXPECT_TRUE(CreateDummyFile(es3outs2[0], "newfile.")); + UNIT_TEST_EXPECT_TRUE(CreateDummyFile(androidouts2[0], "newfile.")); UNIT_TEST_EXPECT_TRUE(CreateDummyFile(pcouts2[0], "newfile.")); changedInputResults.clear(); assetMessages.clear(); @@ -1555,12 +1557,12 @@ namespace AssetProcessor // send all the done messages simultaneously: response.m_outputProducts.clear(); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs[0].toUtf8().constData(), AZ::Uuid::CreateNull(), 1)); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts[0].toUtf8().constData(), AZ::Uuid::CreateNull(), 1)); QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[0].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response)); response.m_outputProducts.clear(); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(es3outs2[0].toUtf8().constData(), AZ::Uuid::CreateNull(), 2)); + response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(androidouts2[0].toUtf8().constData(), AZ::Uuid::CreateNull(), 2)); QMetaObject::invokeMethod(&apm, "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResults[1].m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response)); response.m_outputProducts.clear(); @@ -1620,11 +1622,11 @@ namespace AssetProcessor sortAssetToProcessResultList(processResults); // --------- same result as above ---------- - UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and es3,since we have two recognizer for .txt file + UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // 2 each for pc and android,since we have two recognizer for .txt file UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier); UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier); - UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3")); - UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3")); + UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android")); + UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android")); UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_computedFingerprint != 0); @@ -1645,9 +1647,9 @@ namespace AssetProcessor absolutePath = watchFolderPath + "/" + relativePathFromWatchFolder; unsigned int fingerprintForPC = 0; - unsigned int fingerprintForES3 = 0; + unsigned int fingerprintForANDROID = 0; - ComputeFingerprints(fingerprintForPC, fingerprintForES3, config, watchFolderPath, relativePathFromWatchFolder); + ComputeFingerprints(fingerprintForPC, fingerprintForANDROID, config, watchFolderPath, relativePathFromWatchFolder); processResults.clear(); QMetaObject::invokeMethod(&apm, "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, absolutePath)); @@ -1655,11 +1657,11 @@ namespace AssetProcessor sortAssetToProcessResultList(processResults); - UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // // 2 each for pc and es3,since we have two recognizer for .xxx file + UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // // 2 each for pc and android,since we have two recognizer for .xxx file UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier); UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier); - UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3")); - UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3")); + UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android")); + UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android")); UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc")); @@ -1681,11 +1683,11 @@ namespace AssetProcessor // we never actually submitted any fingerprints or indicated success, so the same number of jobs should occur as before sortAssetToProcessResultList(processResults); - UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // // 2 each for pc and es3,since we have two recognizer for .xxx file + UNIT_TEST_EXPECT_TRUE(processResults.size() == 4); // // 2 each for pc and android,since we have two recognizer for .xxx file UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == processResults[1].m_jobEntry.m_platformInfo.m_identifier); UNIT_TEST_EXPECT_TRUE(processResults[2].m_jobEntry.m_platformInfo.m_identifier == processResults[3].m_jobEntry.m_platformInfo.m_identifier); - UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3")); - UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3")); + UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android")); + UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android")); UNIT_TEST_EXPECT_TRUE((processResults[2].m_jobEntry.m_platformInfo.m_identifier == "pc")); UNIT_TEST_EXPECT_TRUE((processResults[3].m_jobEntry.m_platformInfo.m_identifier == "pc")); @@ -1705,7 +1707,7 @@ namespace AssetProcessor // now re-perform the same test, this time only the pc ones should re-appear. // this should happen because we're changing the extra params, which should be part of the fingerprint // if this unit test fails, check to make sure that the extra params are being ingested into the fingerprint computation functions - // and also make sure that the jobs that are for the remaining es3 platform don't change. + // and also make sure that the jobs that are for the remaining android platform don't change. // store the UUID so that we can insert the new one with the same UUID AZStd::shared_ptr builderTxt2Builder; @@ -1743,12 +1745,12 @@ namespace AssetProcessor // --------------------- unsigned int newfingerprintForPC = 0; - unsigned int newfingerprintForES3 = 0; + unsigned int newfingerprintForANDROID = 0; - ComputeFingerprints(newfingerprintForPC, newfingerprintForES3, config, watchFolderPath, relativePathFromWatchFolder); + ComputeFingerprints(newfingerprintForPC, newfingerprintForANDROID, config, watchFolderPath, relativePathFromWatchFolder); UNIT_TEST_EXPECT_TRUE(newfingerprintForPC != fingerprintForPC);//Fingerprints should be different - UNIT_TEST_EXPECT_TRUE(newfingerprintForES3 == fingerprintForES3);//Fingerprints are same + UNIT_TEST_EXPECT_TRUE(newfingerprintForANDROID == fingerprintForANDROID);//Fingerprints are same config.RemoveRecognizer("xxx files 2 (builder2)"); mockAppManager.UnRegisterAssetRecognizerAsBuilder("xxx files 2 (builder2)"); @@ -1763,18 +1765,18 @@ namespace AssetProcessor absolutePath = AssetUtilities::NormalizeFilePath(absolutePath); QMetaObject::invokeMethod(&apm, "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, absolutePath)); UNIT_TEST_EXPECT_TRUE(BlockUntil(idling, 5000)); - UNIT_TEST_EXPECT_TRUE(processResults.size() == 2); // pc and es3 + UNIT_TEST_EXPECT_TRUE(processResults.size() == 2); // pc and android UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier != processResults[1].m_jobEntry.m_platformInfo.m_identifier); - UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "pc") || (processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3")); - UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "pc") || (processResults[1].m_jobEntry.m_platformInfo.m_identifier == "es3")); + UNIT_TEST_EXPECT_TRUE((processResults[0].m_jobEntry.m_platformInfo.m_identifier == "pc") || (processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android")); + UNIT_TEST_EXPECT_TRUE((processResults[1].m_jobEntry.m_platformInfo.m_identifier == "pc") || (processResults[1].m_jobEntry.m_platformInfo.m_identifier == "android")); unsigned int newfingerprintForPCAfterVersionChange = 0; - unsigned int newfingerprintForES3AfterVersionChange = 0; + unsigned int newfingerprintForANDROIDAfterVersionChange = 0; - ComputeFingerprints(newfingerprintForPCAfterVersionChange, newfingerprintForES3AfterVersionChange, config, watchFolderPath, relativePathFromWatchFolder); + ComputeFingerprints(newfingerprintForPCAfterVersionChange, newfingerprintForANDROIDAfterVersionChange, config, watchFolderPath, relativePathFromWatchFolder); UNIT_TEST_EXPECT_TRUE((newfingerprintForPCAfterVersionChange != fingerprintForPC) || (newfingerprintForPCAfterVersionChange != newfingerprintForPC));//Fingerprints should be different - UNIT_TEST_EXPECT_TRUE((newfingerprintForES3AfterVersionChange != fingerprintForES3) || (newfingerprintForES3AfterVersionChange != newfingerprintForES3));//Fingerprints should be different + UNIT_TEST_EXPECT_TRUE((newfingerprintForANDROIDAfterVersionChange != fingerprintForANDROID) || (newfingerprintForANDROIDAfterVersionChange != newfingerprintForANDROID));//Fingerprints should be different //------Test for Files which are excluded processResults.clear(); @@ -1919,7 +1921,7 @@ namespace AssetProcessor UNIT_TEST_EXPECT_TRUE(processResults.size() == 0); // nothing to process - // we are aware that 4 products went missing (es3 and pc versions of the 2 files since we renamed the SOURCE folder) + // we are aware that 4 products went missing (android and pc versions of the 2 files since we renamed the SOURCE folder) UNIT_TEST_EXPECT_TRUE(assetMessages.size() == 4); for (auto element : assetMessages) { @@ -2178,8 +2180,8 @@ namespace AssetProcessor UNIT_TEST_EXPECT_TRUE(assetMessages[2].m_assetId != AZ::Data::AssetId()); UNIT_TEST_EXPECT_TRUE(assetMessages[3].m_assetId != AZ::Data::AssetId()); - UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "es3"); - UNIT_TEST_EXPECT_TRUE(assetMessages[1].m_platform == "es3"); + UNIT_TEST_EXPECT_TRUE(assetMessages[0].m_platform == "android"); + UNIT_TEST_EXPECT_TRUE(assetMessages[1].m_platform == "android"); UNIT_TEST_EXPECT_TRUE(assetMessages[2].m_platform == "pc"); UNIT_TEST_EXPECT_TRUE(assetMessages[3].m_platform == "pc"); @@ -2212,12 +2214,12 @@ namespace AssetProcessor mockAppManager.UnRegisterAllBuilders(); AssetRecognizer abt_rec1; - AssetPlatformSpec abt_speces3; + AssetPlatformSpec abt_specandroid; abt_rec1.m_name = "UnitTestTextBuilder1"; abt_rec1.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.txt", AssetBuilderSDK::AssetBuilderPattern::Wildcard); //abt_rec1.m_regexp.setPatternSyntax(QRegExp::Wildcard); //abt_rec1.m_regexp.setPattern("*.txt"); - abt_rec1.m_platformSpecs.insert("es3", speces3); + abt_rec1.m_platformSpecs.insert("android", specandroid); mockAppManager.RegisterAssetRecognizerAsBuilder(abt_rec1); AssetRecognizer abt_rec2; @@ -2266,8 +2268,8 @@ namespace AssetProcessor sortAssetToProcessResultList(processResults); - UNIT_TEST_EXPECT_TRUE(processResults.size() == 2); // 1 for pc and es3 - UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == "es3"); + UNIT_TEST_EXPECT_TRUE(processResults.size() == 2); // 1 for pc and android + UNIT_TEST_EXPECT_TRUE(processResults[0].m_jobEntry.m_platformInfo.m_identifier == "android"); UNIT_TEST_EXPECT_TRUE(processResults[1].m_jobEntry.m_platformInfo.m_identifier == "pc"); UNIT_TEST_EXPECT_TRUE(QString::compare(processResults[0].m_jobEntry.GetAbsoluteSourcePath(), absolutePath, Qt::CaseInsensitive) == 0); UNIT_TEST_EXPECT_TRUE(QString::compare(processResults[1].m_jobEntry.GetAbsoluteSourcePath(), absolutePath, Qt::CaseInsensitive) == 0); diff --git a/Code/Tools/AssetProcessor/native/unittests/ConnectionUnitTests.cpp b/Code/Tools/AssetProcessor/native/unittests/ConnectionUnitTests.cpp index 29a0570d39..992cf09539 100644 --- a/Code/Tools/AssetProcessor/native/unittests/ConnectionUnitTests.cpp +++ b/Code/Tools/AssetProcessor/native/unittests/ConnectionUnitTests.cpp @@ -17,16 +17,16 @@ void ConnectionUnitTest::StartTest() m_testConnection.SetAssetPlatformsString("pc"); AzFramework::AssetSystem::AssetNotificationMessage testMessage; EXPECT_CALL(m_testConnection, Send(testing::_, testing::_)).Times(0); - m_testConnection.SendPerPlatform(0, testMessage, "osx_gl"); + m_testConnection.SendPerPlatform(0, testMessage, "mac"); EXPECT_CALL(m_testConnection, Send(testing::_, testing::_)).Times(1); m_testConnection.SendPerPlatform(0, testMessage, "pc"); - m_testConnection.SetAssetPlatformsString("pc,es3"); + m_testConnection.SetAssetPlatformsString("pc,android"); EXPECT_CALL(m_testConnection, Send(testing::_, testing::_)).Times(1); m_testConnection.SendPerPlatform(0, testMessage, "pc"); EXPECT_CALL(m_testConnection, Send(testing::_, testing::_)).Times(0); - m_testConnection.SendPerPlatform(0, testMessage, "osx_gl"); + m_testConnection.SendPerPlatform(0, testMessage, "mac"); EXPECT_CALL(m_testConnection, Send(testing::_, testing::_)).Times(1); - m_testConnection.SendPerPlatform(0, testMessage, "es3"); + m_testConnection.SendPerPlatform(0, testMessage, "android"); EXPECT_CALL(m_testConnection, Send(testing::_, testing::_)).Times(0); // Intended partial string match test - shouldn't send m_testConnection.SendPerPlatform(0, testMessage, "es"); diff --git a/Code/Tools/AssetProcessor/native/unittests/MockConnectionHandler.h b/Code/Tools/AssetProcessor/native/unittests/MockConnectionHandler.h index f0553d5e84..75ffdfe218 100644 --- a/Code/Tools/AssetProcessor/native/unittests/MockConnectionHandler.h +++ b/Code/Tools/AssetProcessor/native/unittests/MockConnectionHandler.h @@ -63,7 +63,7 @@ namespace AssetProcessor size_t SendPerPlatform(unsigned int serial, const AzFramework::AssetSystem::BaseAssetProcessorMessage& message, const QString& platform) override { - if (QString::compare(platform, "pc", Qt::CaseInsensitive) == 0 || QString::compare(platform, "es3", Qt::CaseInsensitive) == 0) + if (QString::compare(platform, "pc", Qt::CaseInsensitive) == 0 || QString::compare(platform, "android", Qt::CaseInsensitive) == 0) { return Send(serial, message); } @@ -72,7 +72,7 @@ namespace AssetProcessor size_t SendRawPerPlatform(unsigned int type, unsigned int serial, const QByteArray& data, const QString& platform) override { - if (QString::compare(platform, "pc", Qt::CaseInsensitive) == 0 || QString::compare(platform, "es3", Qt::CaseInsensitive) == 0) + if (QString::compare(platform, "pc", Qt::CaseInsensitive) == 0 || QString::compare(platform, "android", Qt::CaseInsensitive) == 0) { return SendRaw(type, serial, data); } diff --git a/Code/Tools/AssetProcessor/native/unittests/PlatformConfigurationUnitTests.cpp b/Code/Tools/AssetProcessor/native/unittests/PlatformConfigurationUnitTests.cpp index e09a6366a1..ff29cf2ca9 100644 --- a/Code/Tools/AssetProcessor/native/unittests/PlatformConfigurationUnitTests.cpp +++ b/Code/Tools/AssetProcessor/native/unittests/PlatformConfigurationUnitTests.cpp @@ -64,7 +64,7 @@ void PlatformConfigurationTests::StartTest() PlatformConfiguration config; config.EnablePlatform({ "pc",{ "desktop", "host" } }, true); - config.EnablePlatform({ "es3",{ "mobile", "android" } }, true); + config.EnablePlatform({ "android",{ "mobile", "android" } }, true); config.EnablePlatform({ "fandago",{ "console" } }, false); AZStd::vector platforms; config.PopulatePlatformsForScanFolder(platforms); @@ -88,15 +88,15 @@ void PlatformConfigurationTests::StartTest() AssetRecognizer rec; AssetPlatformSpec specpc; - AssetPlatformSpec speces3; + AssetPlatformSpec specandroid; AssetPlatformSpec specfandago; specpc.m_extraRCParams = ""; // blank must work - speces3.m_extraRCParams = "testextraparams"; + specandroid.m_extraRCParams = "testextraparams"; rec.m_name = "txt files"; rec.m_patternMatcher = AssetBuilderSDK::FilePatternMatcher("*.txt", AssetBuilderSDK::AssetBuilderPattern::Wildcard); rec.m_platformSpecs.insert("pc", specpc); - rec.m_platformSpecs.insert("es3", speces3); + rec.m_platformSpecs.insert("android", specandroid); rec.m_platformSpecs.insert("fandago", specfandago); config.AddRecognizer(rec); @@ -111,7 +111,7 @@ void PlatformConfigurationTests::StartTest() UNIT_TEST_EXPECT_TRUE(config.GetEnabledPlatforms().size() == 2); UNIT_TEST_EXPECT_TRUE(config.GetEnabledPlatforms()[0].m_identifier == "pc"); - UNIT_TEST_EXPECT_TRUE(config.GetEnabledPlatforms()[1].m_identifier == "es3"); + UNIT_TEST_EXPECT_TRUE(config.GetEnabledPlatforms()[1].m_identifier == "android"); UNIT_TEST_EXPECT_TRUE(config.GetScanFolderCount() == 11); UNIT_TEST_EXPECT_FALSE(config.GetScanFolderAt(0).IsRoot()); diff --git a/Code/Tools/AssetProcessor/native/unittests/RCcontrollerUnitTests.cpp b/Code/Tools/AssetProcessor/native/unittests/RCcontrollerUnitTests.cpp index 0e771f7fd1..02b98e5e33 100644 --- a/Code/Tools/AssetProcessor/native/unittests/RCcontrollerUnitTests.cpp +++ b/Code/Tools/AssetProcessor/native/unittests/RCcontrollerUnitTests.cpp @@ -239,14 +239,14 @@ void RCcontrollerUnitTests::RunRCControllerTests() createdJobs.push_back(job); } - // double them up for "es3" to make sure that platform is respected + // double them up for "android" to make sure that platform is respected for (QString name : tempJobNames) { AZ::Uuid uuidOfSource = AZ::Uuid::CreateName(name.toUtf8().constData()); RCJob* job0 = new RCJob(rcJobListModel); AssetProcessor::JobDetails jobDetails; jobDetails.m_jobEntry.m_databaseSourceName = jobDetails.m_jobEntry.m_pathRelativeToWatchFolder = name; - jobDetails.m_jobEntry.m_platformInfo = { "es3" ,{ "mobile", "renderer" } }; + jobDetails.m_jobEntry.m_platformInfo = { "android" ,{ "mobile", "renderer" } }; jobDetails.m_jobEntry.m_jobKey = "Compile Other Stuff"; jobDetails.m_jobEntry.m_sourceFileUUID = uuidOfSource; job0->Init(jobDetails); @@ -490,7 +490,7 @@ void RCcontrollerUnitTests::RunRCControllerTests() UNIT_TEST_EXPECT_FALSE(gotJobsInQueueCall); // submit same job but different platform: - details.m_jobEntry = JobEntry("d:/test", "test1.txt", "test1.txt", AZ::Uuid("{7954065D-CFD1-4666-9E4C-3F36F417C7AC}"), { "es3" ,{ "mobile", "renderer" } }, "Test Job", 1234, 3, sourceId); + details.m_jobEntry = JobEntry("d:/test", "test1.txt", "test1.txt", AZ::Uuid("{7954065D-CFD1-4666-9E4C-3F36F417C7AC}"), { "android" ,{ "mobile", "renderer" } }, "Test Job", 1234, 3, sourceId); m_rcController.JobSubmitted(details); QCoreApplication::processEvents(QEventLoop::AllEvents); diff --git a/Code/Tools/AssetProcessor/native/unittests/UnitTestRunner.cpp b/Code/Tools/AssetProcessor/native/unittests/UnitTestRunner.cpp index 1e10002b53..650f3120dd 100644 --- a/Code/Tools/AssetProcessor/native/unittests/UnitTestRunner.cpp +++ b/Code/Tools/AssetProcessor/native/unittests/UnitTestRunner.cpp @@ -54,7 +54,7 @@ namespace UnitTestUtils { void SleepForMinimumFileSystemTime() { - // note that on OSX, the file system has a resolution of 1 second, and since we're using modtime for a bunch of things, + // note that on Mac, the file system has a resolution of 1 second, and since we're using modtime for a bunch of things, // not the actual hash files, we have to wait different amount depending on the OS. #ifdef AZ_PLATFORM_WINDOWS int milliseconds = 1; diff --git a/Code/Tools/AssetProcessor/testdata/config_broken_badplatform/AssetProcessorPlatformConfig.setreg b/Code/Tools/AssetProcessor/testdata/config_broken_badplatform/AssetProcessorPlatformConfig.setreg index 468ab68f5d..05ed19cb74 100644 --- a/Code/Tools/AssetProcessor/testdata/config_broken_badplatform/AssetProcessorPlatformConfig.setreg +++ b/Code/Tools/AssetProcessor/testdata/config_broken_badplatform/AssetProcessorPlatformConfig.setreg @@ -5,11 +5,11 @@ "Platform pc": { "tags": "tools,renderer" }, - "Platform osx_gl": { + "Platform mac": { "tags": "tools,renderer" }, "Platforms": { - "es3": "enabled" + "android": "enabled" }, "ScanFolder Game": { "watch": "@PROJECTROOT@", diff --git a/Code/Tools/AssetProcessor/testdata/config_broken_noscans/AssetProcessorPlatformConfig.setreg b/Code/Tools/AssetProcessor/testdata/config_broken_noscans/AssetProcessorPlatformConfig.setreg index 507fe4afb1..23f5725548 100644 --- a/Code/Tools/AssetProcessor/testdata/config_broken_noscans/AssetProcessorPlatformConfig.setreg +++ b/Code/Tools/AssetProcessor/testdata/config_broken_noscans/AssetProcessorPlatformConfig.setreg @@ -5,7 +5,7 @@ "Platform pc": { "tags": "tools,renderer" }, - "Platform osx_gl": { + "Platform mac": { "tags": "tools,renderer" }, "RC i_caf": { diff --git a/Code/Tools/AssetProcessor/testdata/config_broken_recognizers/AssetProcessorPlatformConfig.setreg b/Code/Tools/AssetProcessor/testdata/config_broken_recognizers/AssetProcessorPlatformConfig.setreg index 0e687062b2..32c0af0593 100644 --- a/Code/Tools/AssetProcessor/testdata/config_broken_recognizers/AssetProcessorPlatformConfig.setreg +++ b/Code/Tools/AssetProcessor/testdata/config_broken_recognizers/AssetProcessorPlatformConfig.setreg @@ -5,7 +5,7 @@ "Platform pc": { "tags": "tools,renderer" }, - "Platform osx_gl": { + "Platform mac": { "tags": "tools,renderer" }, "ScanFolder Game": { diff --git a/Code/Tools/AssetProcessor/testdata/config_regular/AssetProcessorPlatformConfig.setreg b/Code/Tools/AssetProcessor/testdata/config_regular/AssetProcessorPlatformConfig.setreg index 1c5c487a46..c43996f3d5 100644 --- a/Code/Tools/AssetProcessor/testdata/config_regular/AssetProcessorPlatformConfig.setreg +++ b/Code/Tools/AssetProcessor/testdata/config_regular/AssetProcessorPlatformConfig.setreg @@ -5,17 +5,17 @@ "Platform pc": { "tags": "tools,renderer" }, - "Platform es3": { + "Platform android": { "tags": "android,mobile,renderer" }, - "Platform osx_gl": { + "Platform mac": { "tags": "tools,renderer" }, "Platform server": { "tags": "server" }, "Platforms": { - "es3": "enabled", + "android": "enabled", "server": "enabled" }, "Jobs": { @@ -56,7 +56,7 @@ "glob": "*.i_caf", "params": "defaultparams", "server": "skip", - "es3": "mobile", + "android": "mobile", "priority": 5, "checkServer": true }, @@ -68,7 +68,7 @@ "RC mov": { "glob": "*.mov", "params": "copy", - "es3": "platformspecificoverride", + "android": "platformspecificoverride", "renderer": "rendererparams" }, "RC rend": { diff --git a/Code/Tools/AssetProcessor/testdata/config_regular_platform_scanfolder/AssetProcessorPlatformConfig.setreg b/Code/Tools/AssetProcessor/testdata/config_regular_platform_scanfolder/AssetProcessorPlatformConfig.setreg index e1c2d6e8cc..5fe1071fd5 100644 --- a/Code/Tools/AssetProcessor/testdata/config_regular_platform_scanfolder/AssetProcessorPlatformConfig.setreg +++ b/Code/Tools/AssetProcessor/testdata/config_regular_platform_scanfolder/AssetProcessorPlatformConfig.setreg @@ -5,13 +5,13 @@ "Platform pc": { "tags": "tools,renderer" }, - "Platform es3": { + "Platform android": { "tags": "android,mobile,renderer" }, "Platform ios": { "tags": "mobile,renderer" }, - "Platform osx_gl": { + "Platform mac": { "tags": "tools,renderer" }, "Platform server": { @@ -21,7 +21,7 @@ "tags": "console,renderer" }, "Platforms": { - "es3": "enabled", + "android": "enabled", "ios": "enabled", "server": "enabled" }, @@ -54,14 +54,14 @@ "display": "folder1output", "recursive": 1, "order": 50000, - "include": "es3" + "include": "android" }, "ScanFolder Folder2": { "watch": "@ENGINEROOT@/Folder2", "display": "folder2output", "recursive": 1, "order": 60000, - "exclude": "es3" + "exclude": "android" }, "ScanFolder Folder3": { "watch": "@ENGINEROOT@/Folder3", @@ -80,7 +80,7 @@ "glob": "*.i_caf", "params": "defaultparams", "server": "skip", - "es3": "mobile", + "android": "mobile", "test": "copy", "priority": 5 }, @@ -92,7 +92,7 @@ "RC mov": { "glob": "*.mov", "params": "copy", - "es3": "platformspecificoverride", + "android": "platformspecificoverride", "renderer": "rendererparams" }, "RC rend": { diff --git a/Code/Tools/GridHub/GridHub/gridhub.cpp b/Code/Tools/GridHub/GridHub/gridhub.cpp index 7f85ade238..4b2d8e425b 100644 --- a/Code/Tools/GridHub/GridHub/gridhub.cpp +++ b/Code/Tools/GridHub/GridHub/gridhub.cpp @@ -552,7 +552,7 @@ GridHubComponent::OnMemberJoined([[maybe_unused]] GridMate::GridSession* session switch( member->GetPlatformId() ) { case AZ::PlatformID::PLATFORM_WINDOWS_64: - case AZ::PlatformID::PLATFORM_APPLE_OSX: + case AZ::PlatformID::PLATFORM_APPLE_MAC: { GridMate::string localMachineName = GridMate::Utils::GetMachineAddress(); if( member->GetMachineName() == localMachineName ) diff --git a/Code/Tools/ProjectManager/Resources/AddOffset.svg b/Code/Tools/ProjectManager/Resources/AddOffset.svg new file mode 100644 index 0000000000..4c62234070 --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/AddOffset.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Code/Tools/ProjectManager/Resources/AddOffset_Hover.svg b/Code/Tools/ProjectManager/Resources/AddOffset_Hover.svg new file mode 100644 index 0000000000..a0e2a07eda --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/AddOffset_Hover.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Code/Tools/ProjectManager/Resources/ArrowBack.svg b/Code/Tools/ProjectManager/Resources/ArrowBack.svg new file mode 100644 index 0000000000..749bb5a02e --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/ArrowBack.svg @@ -0,0 +1,3 @@ + + + diff --git a/Code/Tools/ProjectManager/Resources/FolderOffset.svg b/Code/Tools/ProjectManager/Resources/FolderOffset.svg new file mode 100644 index 0000000000..a048fbcc39 --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/FolderOffset.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Code/Tools/ProjectManager/Resources/FolderOffset_Hover.svg b/Code/Tools/ProjectManager/Resources/FolderOffset_Hover.svg new file mode 100644 index 0000000000..fb13cd8558 --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/FolderOffset_Hover.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qrc b/Code/Tools/ProjectManager/Resources/ProjectManager.qrc index 2e60e84326..04d5e98a10 100644 --- a/Code/Tools/ProjectManager/Resources/ProjectManager.qrc +++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qrc @@ -4,6 +4,12 @@ Add.svg + AddOffset.svg + AddOffset_Hover.svg + ArrowBack.svg + build.svg + FolderOffset.svg + FolderOffset_Hover.svg Select_Folder.svg o3de_editor.ico Windows.svg @@ -14,6 +20,9 @@ DefaultProjectImage.png ArrowDownLine.svg ArrowUpLine.svg + o3de.svg + menu.svg + menu_hover.svg Backgrounds/FirstTimeBackgroundImage.jpg ArrowDownLine.svg ArrowUpLine.svg diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss index 16ef48ee7c..5eb92964dd 100644 --- a/Code/Tools/ProjectManager/Resources/ProjectManager.qss +++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qss @@ -1,29 +1,69 @@ /************** General (MainWindow) **************/ QMainWindow { - background-color: #333333; + background:#131313 url(:/o3de.svg) no-repeat top left; + /* position the logo using padding and background-origin, Qt does not support background-position pixels */ + background-origin:content; + padding:25px 16px; + margin:0; } - QPushButton:focus { outline: none; border:1px solid #1e70eb; } +QTabBar { + background-color: transparent; +} +QTabWidget::tab-bar +{ + left: 78px; /* make room for the logo */ +} +QTabBar::tab { + height:82px; + background-color: transparent; + font-size:24px; + min-width:100px; + margin-right:40px; + border-bottom: 3px solid transparent; +} +QTabBar::tab:text +{ + text-align:left; +} +QTabWidget::pane { + background-color: #333333; + border:0 none; +} +QTabBar::tab:selected +{ + border-bottom: 3px solid #1e70eb; + color: #1e70eb; +} +QTabBar::tab:hover +{ + color: #1e70eb; +} +QTabBar::tab:pressed +{ + color: #0e60eb; +} + /************** General (Forms) **************/ #formLineEditWidget, #formBrowseEditWidget { - max-width: 780px; + max-width: 890px; } #formFrame { - max-width: 720px; + max-width: 840px; background-color: #444444; border:1px solid #dddddd; border-radius: 4px; padding: 0px 10px 2px 6px; margin-top:10px; - margin-left:30px; + margin-left:50px; } #formFrame[Focus="true"] { @@ -59,15 +99,241 @@ QPushButton:focus { padding-top: -4px; } + #formErrorLabel { color: #ec3030; font-size: 14px; - margin-left: 40px; + margin-left: 50px; } #formTitleLabel { font-size:21px; color:#ffffff; - margin: 10px 0 10px 30px; + margin: 24px 0 10px 50px; } +/************** General (Modal windows) **************/ + +#header { + background-color:#111111; + min-height:80px; + max-height:80px; +} + +#header QPushButton { + /* settings min/max lets us use a fixed size */ + min-width: 24px; + max-width: 24px; + min-height: 24px; + max-height: 24px; + margin: 20px 10px 0px 10px; + background:transparent url(:/ArrowBack.svg) no-repeat center; + background-origin:content; + qproperty-flat: true; + qproperty-iconSize: 50px; +} + +#header QPushButton:focus { + border:none; +} +#header QPushButton:hover { + background:#333333 url(:/ArrowBack.svg) no-repeat center; +} +#header QPushButton:pressed { + background:#222222 url(:/ArrowBack.svg) no-repeat center; +} + +#headerTitle { + font-size:14px; + text-align:left; + margin:0; + padding-top:10px; + padding-bottom:-5px; + min-height:15px; + max-height:15px; +} +#headerSubTitle { + font-size:24px; + text-align:left; + margin:0; + min-height:42px; + max-height:42px; +} + +#body { + background-color:#333333; +} +#footer { + /* settings min/max lets us use a fixed size */ + min-width: 50px; + min-height:54px; + max-height:54px; +} + +#footer > QPushButton { + qproperty-flat: true; + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #0095f2, stop: 1.0 #1e70eb); + border-radius: 3px; + min-height: 28px; + max-height: 28px; + min-width: 150px; + margin-right:30px; +} +#footer > QPushButton:hover { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #10A5f2, stop: 1.0 #2e80eb); +} +#footer > QPushButton:pressed { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #0085e2, stop: 1.0 #0e60db); +} + +#footer > QPushButton[secondary="true"] { + margin-right: 10px; + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #888888, stop: 1.0 #555555); +} +#footer > QPushButton[secondary="true"]:hover { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #999999, stop: 1.0 #666666); +} +#footer > QPushButton[secondary="true"]:pressed { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #555555, stop: 1.0 #777777); +} + +/************** Project Settings **************/ +#projectSettings { + margin-top:42px; +} + +#projectTemplate { + margin: 55px 0 0 50px; + max-width: 780px; + min-height:200px; + max-height:200px; +} +#projectTemplateLabel { + font-size:16px; + font-weight:100; +} + +#projectTemplateDetailsLabel { + font-size:14px; + min-height:40px; + margin-bottom:20px; +} + +#projectTemplateDetails { + background-color:#444444; + max-width:240px; + min-width:240px; + margin-left:30px; +} + +/************** Projects **************/ +#firstTimeContent > #titleLabel { + font-size:60px; + margin:73px 0px 0px 0px; + qproperty-indent: 0; +} + +#firstTimeContent > #introLabel { + font-size:14px; + margin:10px 0 60px 0; + qproperty-indent: 0; +} + +#firstTimeContent > QPushButton { + min-width: 210px; + max-width: 210px; + min-height: 276px; + max-height: 276px; + qproperty-flat: true; + background-origin:content; + font-size:14px; + border: 1px solid #ffffff; +} + +#firstTimeContent > QPushButton:hover { + border: 1px solid #1e70eb; + color: #1e70eb; +} + +#firstTimeContent > QPushButton:pressed { + border: 1px solid #0e60eb; + color: #0e60eb; +} + +#createProjectButton { + background:rgba(0,0,0,180) url(:/AddOffset.svg) no-repeat center center; +} +#createProjectButton:hover, +#createProjectButton:pressed { + background:rgba(0,0,0,180) url(:/AddOffset_Hover.svg) no-repeat center center; +} + +#addProjectButton { + background:rgba(0,0,0,180) url(:/FolderOffset.svg) no-repeat center center; +} +#addProjectButton:hover, +#addProjectButton:pressed { + background:rgba(0,0,0,180) url(:/FolderOffset_Hover.svg) no-repeat center center; +} + +#projectsContent > QFrame { + margin-top:60px; +} + +#projectsContent > QFrame > #titleLabel { + font-size:24px; + qproperty-indent: 0; +} + +#projectsContent > QScrollArea { + margin-top:40px; + margin-bottom:5px; +} + +#projectButton > #labelButton { + border:1px solid white; +} +#projectButton > #labelButton:hover, +#projectButton > #labelButton:pressed { + border:1px solid #1e70eb; +} + +#projectButton > QFrame { + margin-top:6px; +} + +#projectButton > QFrame > QLabel { + font-weight:bold; + font-size:14px; + qproperty-indent: 0; +} + +#projectMenuButton { + qproperty-flat: true; + background:transparent url(:/menu.svg) no-repeat center center; + max-width:30px; + min-width:30px; + max-height:14px; + min-height:14px; +} + +#projectsContent > QFrame > #newProjectButton { + min-width:150px; + max-width:150px; + min-height:26px; + max-height:26px; +} + +#labelButtonOverlay { + background-color: rgba(50,50,50,200); + min-width:210px; + max-width:210px;; + min-height:278px; + max-height:278px; +} \ No newline at end of file diff --git a/Code/Tools/ProjectManager/Resources/build.svg b/Code/Tools/ProjectManager/Resources/build.svg new file mode 100644 index 0000000000..b6c3546443 --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/build.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Code/Tools/ProjectManager/Resources/menu.svg b/Code/Tools/ProjectManager/Resources/menu.svg new file mode 100644 index 0000000000..a639c74ab4 --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/menu.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Code/Tools/ProjectManager/Resources/menu_hover.svg b/Code/Tools/ProjectManager/Resources/menu_hover.svg new file mode 100644 index 0000000000..4eea63faca --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/menu_hover.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Code/Tools/ProjectManager/Resources/o3de.svg b/Code/Tools/ProjectManager/Resources/o3de.svg new file mode 100644 index 0000000000..bb6e596a00 --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/o3de.svg @@ -0,0 +1,3 @@ + + + diff --git a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp index 03e6a34b89..69f0a3983d 100644 --- a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp @@ -14,11 +14,17 @@ #include #include #include +#include +#include #include +#include #include #include #include +#include +#include +#include namespace O3DE::ProjectManager { @@ -26,29 +32,34 @@ namespace O3DE::ProjectManager : ScreenWidget(parent) { QVBoxLayout* vLayout = new QVBoxLayout(); - setLayout(vLayout); + vLayout->setContentsMargins(0,0,0,0); - m_screensCtrl = new ScreensCtrl(); - vLayout->addWidget(m_screensCtrl); + m_header = new ScreenHeader(this); + m_header->setTitle(tr("Create a New Project")); + m_header->setSubTitle(tr("Enter Project Details")); + connect(m_header->backButton(), &QPushButton::clicked, this, &CreateProjectCtrl::HandleBackButton); + vLayout->addWidget(m_header); + + m_stack = new QStackedWidget(this); + m_stack->setObjectName("body"); + m_stack->setSizePolicy(QSizePolicy(QSizePolicy::Preferred,QSizePolicy::Expanding)); + m_stack->addWidget(new NewProjectSettingsScreen()); + m_stack->addWidget(new GemCatalogScreen()); + vLayout->addWidget(m_stack); QDialogButtonBox* backNextButtons = new QDialogButtonBox(); + backNextButtons->setObjectName("footer"); vLayout->addWidget(backNextButtons); m_backButton = backNextButtons->addButton(tr("Back"), QDialogButtonBox::RejectRole); + m_backButton->setProperty("secondary", true); m_nextButton = backNextButtons->addButton(tr("Next"), QDialogButtonBox::ApplyRole); - connect(m_backButton, &QPushButton::pressed, this, &CreateProjectCtrl::HandleBackButton); - connect(m_nextButton, &QPushButton::pressed, this, &CreateProjectCtrl::HandleNextButton); + connect(m_backButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandleBackButton); + connect(m_nextButton, &QPushButton::clicked, this, &CreateProjectCtrl::HandleNextButton); - m_screensOrder = - { - ProjectManagerScreen::NewProjectSettings, - ProjectManagerScreen::GemCatalog - }; - m_screensCtrl->BuildScreens(m_screensOrder); - m_screensCtrl->ForceChangeToScreen(ProjectManagerScreen::NewProjectSettings, false); - - UpdateNextButtonText(); + Update(); + setLayout(vLayout); } ProjectManagerScreen CreateProjectCtrl::GetScreenEnum() @@ -58,28 +69,20 @@ namespace O3DE::ProjectManager void CreateProjectCtrl::HandleBackButton() { - if (!m_screensCtrl->GotoPreviousScreen()) + if (m_stack->currentIndex() > 0) { - emit GotoPreviousScreenRequest(); + m_stack->setCurrentIndex(m_stack->currentIndex() - 1); + Update(); } else { - UpdateNextButtonText(); + emit GotoPreviousScreenRequest(); } } void CreateProjectCtrl::HandleNextButton() { - ScreenWidget* currentScreen = m_screensCtrl->GetCurrentScreen(); + ScreenWidget* currentScreen = reinterpret_cast(m_stack->currentWidget()); ProjectManagerScreen screenEnum = currentScreen->GetScreenEnum(); - auto screenOrderIter = m_screensOrder.begin(); - for (; screenOrderIter != m_screensOrder.end(); ++screenOrderIter) - { - if (*screenOrderIter == screenEnum) - { - ++screenOrderIter; - break; - } - } if (screenEnum == ProjectManagerScreen::NewProjectSettings) { @@ -97,10 +100,10 @@ namespace O3DE::ProjectManager } } - if (screenOrderIter != m_screensOrder.end()) + if (m_stack->currentIndex() != m_stack->count() - 1) { - m_screensCtrl->ChangeToScreen(*screenOrderIter); - UpdateNextButtonText(); + m_stack->setCurrentIndex(m_stack->currentIndex() + 1); + Update(); } else { @@ -108,7 +111,7 @@ namespace O3DE::ProjectManager if (result.IsSuccess()) { // adding gems is not implemented yet because we don't know what targets to add or how to add them - emit ChangeScreenRequest(ProjectManagerScreen::ProjectsHome); + emit ChangeScreenRequest(ProjectManagerScreen::Projects); } else { @@ -117,14 +120,21 @@ namespace O3DE::ProjectManager } } - void CreateProjectCtrl::UpdateNextButtonText() + void CreateProjectCtrl::Update() { - QString nextButtonText = tr("Next"); - if (m_screensCtrl->GetCurrentScreen()->GetScreenEnum() == ProjectManagerScreen::GemCatalog) + ScreenWidget* currentScreen = reinterpret_cast(m_stack->currentWidget()); + if (currentScreen && currentScreen->GetScreenEnum() == ProjectManagerScreen::GemCatalog) { - nextButtonText = tr("Create Project"); + m_header->setTitle(tr("Create Project")); + m_header->setSubTitle(tr("Configure project with Gems")); + m_nextButton->setText(tr("Create Project")); + } + else + { + m_header->setTitle(tr("Create Project")); + m_header->setSubTitle(tr("Enter Project Details")); + m_nextButton->setText(tr("Next")); } - m_nextButton->setText(nextButtonText); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.h b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.h index 213bff3bc2..01e3349b21 100644 --- a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.h +++ b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.h @@ -12,15 +12,18 @@ #pragma once #if !defined(Q_MOC_RUN) -#include "ProjectInfo.h" #include -#include -#include +#include #endif +QT_FORWARD_DECLARE_CLASS(QStackedWidget) +QT_FORWARD_DECLARE_CLASS(QPushButton) +QT_FORWARD_DECLARE_CLASS(QLabel) namespace O3DE::ProjectManager { + QT_FORWARD_DECLARE_CLASS(ScreenHeader) + class CreateProjectCtrl : public ScreenWidget { @@ -34,12 +37,13 @@ namespace O3DE::ProjectManager void HandleNextButton(); private: - void UpdateNextButtonText(); + void Update(); + + QStackedWidget* m_stack; + ScreenHeader* m_header; - ScreensCtrl* m_screensCtrl; QPushButton* m_backButton; QPushButton* m_nextButton; - QVector m_screensOrder; QString m_projectTemplatePath; ProjectInfo m_projectInfo; diff --git a/Code/Tools/ProjectManager/Source/EngineSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/EngineSettingsScreen.cpp index f51996bd65..6342041da4 100644 --- a/Code/Tools/ProjectManager/Source/EngineSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/EngineSettingsScreen.cpp @@ -82,6 +82,16 @@ namespace O3DE::ProjectManager return ProjectManagerScreen::EngineSettings; } + QString EngineSettingsScreen::GetTabText() + { + return tr("Engine"); + } + + bool EngineSettingsScreen::IsTab() + { + return true; + } + void EngineSettingsScreen::OnTextChanged() { // save engine settings diff --git a/Code/Tools/ProjectManager/Source/EngineSettingsScreen.h b/Code/Tools/ProjectManager/Source/EngineSettingsScreen.h index 0e91ec2d3b..36e329cdf6 100644 --- a/Code/Tools/ProjectManager/Source/EngineSettingsScreen.h +++ b/Code/Tools/ProjectManager/Source/EngineSettingsScreen.h @@ -26,7 +26,10 @@ namespace O3DE::ProjectManager public: explicit EngineSettingsScreen(QWidget* parent = nullptr); ~EngineSettingsScreen() = default; + ProjectManagerScreen GetScreenEnum() override; + QString GetTabText() override; + bool IsTab() override; protected slots: void OnTextChanged(); diff --git a/Code/Tools/ProjectManager/Source/FirstTimeUseScreen.cpp b/Code/Tools/ProjectManager/Source/FirstTimeUseScreen.cpp deleted file mode 100644 index 8654b221fb..0000000000 --- a/Code/Tools/ProjectManager/Source/FirstTimeUseScreen.cpp +++ /dev/null @@ -1,95 +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. - * - */ - -#include - -#include -#include -#include -#include -#include -#include - -namespace O3DE::ProjectManager -{ - FirstTimeUseScreen::FirstTimeUseScreen(QWidget* parent) - : ScreenWidget(parent) - { - QVBoxLayout* vLayout = new QVBoxLayout(); - setLayout(vLayout); - vLayout->setContentsMargins(s_contentMargins, s_contentMargins, s_contentMargins, s_contentMargins); - - QLabel* titleLabel = new QLabel(this); - titleLabel->setText(tr("Ready. Set. Create!")); - titleLabel->setStyleSheet("font-size: 60px"); - vLayout->addWidget(titleLabel); - - QLabel* introLabel = new QLabel(this); - introLabel->setTextFormat(Qt::AutoText); - introLabel->setText(tr("

Welcome to O3DE! Start something new by creating a project. Not sure what to create?

Explore what\342\200\231s available by downloading our sample project.

")); - introLabel->setStyleSheet("font-size: 14px"); - vLayout->addWidget(introLabel); - - QHBoxLayout* buttonLayout = new QHBoxLayout(); - buttonLayout->setSpacing(s_buttonSpacing); - - m_createProjectButton = CreateLargeBoxButton(QIcon(":/Add.svg"), tr("Create Project"), this); - m_createProjectButton->setIconSize(QSize(s_iconSize, s_iconSize)); - buttonLayout->addWidget(m_createProjectButton); - - m_addProjectButton = CreateLargeBoxButton(QIcon(":/Select_Folder.svg"), tr("Add a Project"), this); - m_addProjectButton->setIconSize(QSize(s_iconSize, s_iconSize)); - buttonLayout->addWidget(m_addProjectButton); - - QSpacerItem* buttonSpacer = new QSpacerItem(s_spacerSize, s_spacerSize, QSizePolicy::Expanding, QSizePolicy::Minimum); - buttonLayout->addItem(buttonSpacer); - - vLayout->addItem(buttonLayout); - - QSpacerItem* verticalSpacer = new QSpacerItem(s_spacerSize, s_spacerSize, QSizePolicy::Minimum, QSizePolicy::Expanding); - vLayout->addItem(verticalSpacer); - - // Using border-image allows for scaling options background-image does not support - setStyleSheet("O3DE--ProjectManager--ScreenWidget { border-image: url(:/Backgrounds/FirstTimeBackgroundImage.jpg) repeat repeat; }"); - - connect(m_createProjectButton, &QPushButton::pressed, this, &FirstTimeUseScreen::HandleNewProjectButton); - connect(m_addProjectButton, &QPushButton::pressed, this, &FirstTimeUseScreen::HandleAddProjectButton); - } - - ProjectManagerScreen FirstTimeUseScreen::GetScreenEnum() - { - return ProjectManagerScreen::FirstTimeUse; - } - - void FirstTimeUseScreen::HandleNewProjectButton() - { - emit ResetScreenRequest(ProjectManagerScreen::CreateProject); - emit ChangeScreenRequest(ProjectManagerScreen::CreateProject); - } - void FirstTimeUseScreen::HandleAddProjectButton() - { - emit ChangeScreenRequest(ProjectManagerScreen::ProjectsHome); - } - - QPushButton* FirstTimeUseScreen::CreateLargeBoxButton(const QIcon& icon, const QString& text, QWidget* parent) - { - QPushButton* largeBoxButton = new QPushButton(icon, text, parent); - - largeBoxButton->setFixedSize(s_boxButtonWidth, s_boxButtonHeight); - largeBoxButton->setFlat(true); - largeBoxButton->setFocusPolicy(Qt::FocusPolicy::NoFocus); - largeBoxButton->setStyleSheet("QPushButton { font-size: 14px; background-color: rgba(0, 0, 0, 191); }"); - - return largeBoxButton; - } - -} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/FirstTimeUseScreen.h b/Code/Tools/ProjectManager/Source/FirstTimeUseScreen.h deleted file mode 100644 index 80a2310d7a..0000000000 --- a/Code/Tools/ProjectManager/Source/FirstTimeUseScreen.h +++ /dev/null @@ -1,49 +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. - * - */ -#pragma once - -#if !defined(Q_MOC_RUN) -#include -#endif - -QT_FORWARD_DECLARE_CLASS(QIcon) -QT_FORWARD_DECLARE_CLASS(QPushButton) - -namespace O3DE::ProjectManager -{ - class FirstTimeUseScreen - : public ScreenWidget - { - public: - explicit FirstTimeUseScreen(QWidget* parent = nullptr); - ~FirstTimeUseScreen() = default; - ProjectManagerScreen GetScreenEnum() override; - - protected slots: - void HandleNewProjectButton(); - void HandleAddProjectButton(); - - private: - QPushButton* CreateLargeBoxButton(const QIcon& icon, const QString& text, QWidget* parent = nullptr); - - QPushButton* m_createProjectButton; - QPushButton* m_addProjectButton; - - inline constexpr static int s_contentMargins = 80; - inline constexpr static int s_buttonSpacing = 30; - inline constexpr static int s_iconSize = 24; - inline constexpr static int s_spacerSize = 20; - inline constexpr static int s_boxButtonWidth = 210; - inline constexpr static int s_boxButtonHeight = 280; - }; - -} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp index ffbf1bf6fe..b57a2b35b2 100644 --- a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp +++ b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.cpp @@ -12,6 +12,9 @@ #include #include +#include +#include +#include #include #include @@ -23,6 +26,7 @@ #include #include #include +#include namespace O3DE::ProjectManager { @@ -31,64 +35,81 @@ namespace O3DE::ProjectManager NewProjectSettingsScreen::NewProjectSettingsScreen(QWidget* parent) : ScreenWidget(parent) { - QHBoxLayout* hLayout = new QHBoxLayout(); - this->setLayout(hLayout); + QHBoxLayout* hLayout = new QHBoxLayout(this); + hLayout->setAlignment(Qt::AlignLeft); + hLayout->setContentsMargins(0,0,0,0); + // if we don't provide a parent for this box layout the stylesheet doesn't take + // if we don't set this in a frame (just use a sub-layout) all the content will align incorrectly horizontally + QFrame* projectSettingsFrame = new QFrame(this); + projectSettingsFrame->setObjectName("projectSettings"); QVBoxLayout* vLayout = new QVBoxLayout(this); - QLabel* projectNameLabel = new QLabel(tr("Project Name"), this); - vLayout->addWidget(projectNameLabel); - - m_projectNameLineEdit = new QLineEdit(tr("New Project"), this); - vLayout->addWidget(m_projectNameLineEdit); - - QLabel* projectPathLabel = new QLabel(tr("Project Location"), this); - vLayout->addWidget(projectPathLabel); - + // you cannot remove content margins in qss + vLayout->setContentsMargins(0,0,0,0); + vLayout->setAlignment(Qt::AlignTop); { - QHBoxLayout* projectPathLayout = new QHBoxLayout(this); + m_projectName = new FormLineEditWidget(tr("Project name"), tr("New Project"), this); + m_projectName->setErrorLabelText( + tr("A project with this name already exists at this location. Please choose a new name or location.")); + vLayout->addWidget(m_projectName); - m_projectPathLineEdit = new QLineEdit(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), this); - projectPathLayout->addWidget(m_projectPathLineEdit); + m_projectPath = + new FormBrowseEditWidget(tr("Project Location"), QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), this); + m_projectPath->lineEdit()->setReadOnly(true); + m_projectPath->setErrorLabelText(tr("Please provide a valid path to a folder that exists")); + m_projectPath->lineEdit()->setValidator(new PathValidator(PathValidator::PathMode::ExistingFolder, this)); + vLayout->addWidget(m_projectPath); - QPushButton* browseButton = new QPushButton(tr("Browse"), this); - connect(browseButton, &QPushButton::pressed, this, &NewProjectSettingsScreen::HandleBrowseButton); - projectPathLayout->addWidget(browseButton); - - vLayout->addLayout(projectPathLayout); - } - - QLabel* projectTemplateLabel = new QLabel(this); - projectTemplateLabel->setText("Project Template"); - vLayout->addWidget(projectTemplateLabel); - - QHBoxLayout* templateLayout = new QHBoxLayout(this); - vLayout->addItem(templateLayout); - - m_projectTemplateButtonGroup = new QButtonGroup(this); - auto templatesResult = PythonBindingsInterface::Get()->GetProjectTemplates(); - if (templatesResult.IsSuccess() && !templatesResult.GetValue().isEmpty()) - { - for (auto projectTemplate : templatesResult.GetValue()) + // if we don't use a QFrame we cannot "contain" the widgets inside and move them around + // as a group + QFrame* projectTemplateWidget = new QFrame(this); + projectTemplateWidget->setObjectName("projectTemplate"); + QVBoxLayout* containerLayout = new QVBoxLayout(); + containerLayout->setAlignment(Qt::AlignTop); { - QRadioButton* radioButton = new QRadioButton(projectTemplate.m_name, this); - radioButton->setProperty(k_pathProperty, projectTemplate.m_path); - m_projectTemplateButtonGroup->addButton(radioButton); + QLabel* projectTemplateLabel = new QLabel(tr("Select a Project Template")); + projectTemplateLabel->setObjectName("projectTemplateLabel"); + containerLayout->addWidget(projectTemplateLabel); - templateLayout->addWidget(radioButton); + QLabel* projectTemplateDetailsLabel = new QLabel(tr("Project templates are pre-configured with relevant Gems that provide " + "additional functionality and content to the project.")); + projectTemplateDetailsLabel->setWordWrap(true); + projectTemplateDetailsLabel->setObjectName("projectTemplateDetailsLabel"); + containerLayout->addWidget(projectTemplateDetailsLabel); + + QHBoxLayout* templateLayout = new QHBoxLayout(this); + containerLayout->addItem(templateLayout); + + m_projectTemplateButtonGroup = new QButtonGroup(this); + m_projectTemplateButtonGroup->setObjectName("templateButtonGroup"); + auto templatesResult = PythonBindingsInterface::Get()->GetProjectTemplates(); + if (templatesResult.IsSuccess() && !templatesResult.GetValue().isEmpty()) + { + for (auto projectTemplate : templatesResult.GetValue()) + { + QRadioButton* radioButton = new QRadioButton(projectTemplate.m_name, this); + radioButton->setProperty(k_pathProperty, projectTemplate.m_path); + m_projectTemplateButtonGroup->addButton(radioButton); + + containerLayout->addWidget(radioButton); + } + + m_projectTemplateButtonGroup->buttons().first()->setChecked(true); + } } - - m_projectTemplateButtonGroup->buttons().first()->setChecked(true); + projectTemplateWidget->setLayout(containerLayout); + vLayout->addWidget(projectTemplateWidget); } + projectSettingsFrame->setLayout(vLayout); - QSpacerItem* verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); - vLayout->addItem(verticalSpacer); + hLayout->addWidget(projectSettingsFrame); - hLayout->addItem(vLayout); + QWidget* projectTemplateDetails = new QWidget(this); + projectTemplateDetails->setObjectName("projectTemplateDetails"); + hLayout->addWidget(projectTemplateDetails); - QWidget* gemsListPlaceholder = new QWidget(this); - gemsListPlaceholder->setFixedWidth(250); - hLayout->addWidget(gemsListPlaceholder); + this->setLayout(hLayout); } ProjectManagerScreen NewProjectSettingsScreen::GetScreenEnum() @@ -96,26 +117,12 @@ namespace O3DE::ProjectManager return ProjectManagerScreen::NewProjectSettings; } - void NewProjectSettingsScreen::HandleBrowseButton() - { - QString defaultPath = m_projectPathLineEdit->text(); - if (defaultPath.isEmpty()) - { - defaultPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); - } - - QString directory = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this, tr("New project path"), defaultPath)); - if (!directory.isEmpty()) - { - m_projectPathLineEdit->setText(directory); - } - } ProjectInfo NewProjectSettingsScreen::GetProjectInfo() { ProjectInfo projectInfo; - projectInfo.m_projectName = m_projectNameLineEdit->text(); - projectInfo.m_path = QDir::toNativeSeparators(m_projectPathLineEdit->text() + "/" + projectInfo.m_projectName); + projectInfo.m_projectName = m_projectName->lineEdit()->text(); + projectInfo.m_path = QDir::toNativeSeparators(m_projectPath->lineEdit()->text() + "/" + projectInfo.m_projectName); return projectInfo; } @@ -127,18 +134,18 @@ namespace O3DE::ProjectManager bool NewProjectSettingsScreen::Validate() { bool projectNameIsValid = true; - if (m_projectNameLineEdit->text().isEmpty()) + if (m_projectName->lineEdit()->text().isEmpty()) { projectNameIsValid = false; } bool projectPathIsValid = true; - if (m_projectPathLineEdit->text().isEmpty()) + if (m_projectPath->lineEdit()->text().isEmpty()) { projectPathIsValid = false; } - QDir path(QDir::toNativeSeparators(m_projectPathLineEdit->text() + "/" + m_projectNameLineEdit->text())); + QDir path(QDir::toNativeSeparators(m_projectPath->lineEdit()->text() + "/" + m_projectName->lineEdit()->text())); if (path.exists() && !path.isEmpty()) { projectPathIsValid = false; diff --git a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h index 1cfd3c9c35..f0e9609fdc 100644 --- a/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h +++ b/Code/Tools/ProjectManager/Source/NewProjectSettingsScreen.h @@ -17,10 +17,12 @@ #endif QT_FORWARD_DECLARE_CLASS(QButtonGroup) -QT_FORWARD_DECLARE_CLASS(QLineEdit) namespace O3DE::ProjectManager { + QT_FORWARD_DECLARE_CLASS(FormLineEditWidget) + QT_FORWARD_DECLARE_CLASS(FormBrowseEditWidget) + class NewProjectSettingsScreen : public ScreenWidget { @@ -38,8 +40,8 @@ namespace O3DE::ProjectManager void HandleBrowseButton(); private: - QLineEdit* m_projectNameLineEdit; - QLineEdit* m_projectPathLineEdit; + FormLineEditWidget* m_projectName; + FormBrowseEditWidget* m_projectPath; QButtonGroup* m_projectTemplateButtonGroup; }; diff --git a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp index ec1acdad61..4be876e79f 100644 --- a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp @@ -31,11 +31,31 @@ namespace O3DE::ProjectManager LabelButton::LabelButton(QWidget* parent) : QLabel(parent) { + setObjectName("labelButton"); + m_overlayLabel = new QLabel("", this); + m_overlayLabel->setObjectName("labelButtonOverlay"); + m_overlayLabel->setWordWrap(true); + m_overlayLabel->setAlignment(Qt::AlignCenter); + m_overlayLabel->setVisible(false); } void LabelButton::mousePressEvent([[maybe_unused]] QMouseEvent* event) { - emit triggered(); + if(m_enabled) + { + emit triggered(); + } + } + + void LabelButton::SetEnabled(bool enabled) + { + m_enabled = enabled; + m_overlayLabel->setVisible(!enabled); + } + + void LabelButton::SetOverlayText(const QString& text) + { + m_overlayLabel->setText(text); } ProjectButton::ProjectButton(const QString& projectName, QWidget* parent) @@ -56,6 +76,8 @@ namespace O3DE::ProjectManager void ProjectButton::Setup() { + setObjectName("projectButton"); + QVBoxLayout* vLayout = new QVBoxLayout(); vLayout->setSpacing(0); vLayout->setContentsMargins(0, 0, 0, 0); @@ -79,14 +101,21 @@ namespace O3DE::ProjectManager m_deleteProjectAction = newProjectMenu->addAction(tr("Delete the Project")); #endif - m_projectSettingsMenuButton = new QPushButton(this); - m_projectSettingsMenuButton->setText(m_projectName); - m_projectSettingsMenuButton->setMenu(newProjectMenu); - m_projectSettingsMenuButton->setFocusPolicy(Qt::FocusPolicy::NoFocus); - m_projectSettingsMenuButton->setStyleSheet("font-size: 14px; text-align:left;"); - vLayout->addWidget(m_projectSettingsMenuButton); + QFrame* footer = new QFrame(this); + QHBoxLayout* hLayout = new QHBoxLayout(); + hLayout->setContentsMargins(0, 0, 0, 0); + footer->setLayout(hLayout); + { + QLabel* projectNameLabel = new QLabel(m_projectName, this); + hLayout->addWidget(projectNameLabel); - setFixedSize(s_projectImageWidth, s_projectImageHeight + m_projectSettingsMenuButton->height()); + QPushButton* projectMenuButton = new QPushButton(this); + projectMenuButton->setObjectName("projectMenuButton"); + projectMenuButton->setMenu(newProjectMenu); + hLayout->addWidget(projectMenuButton); + } + + vLayout->addWidget(footer); connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectName); }); connect(m_editProjectAction, &QAction::triggered, [this]() { emit EditProject(m_projectName); }); @@ -99,4 +128,13 @@ namespace O3DE::ProjectManager #endif } + void ProjectButton::SetButtonEnabled(bool enabled) + { + m_projectImageLabel->SetEnabled(enabled); + } + + void ProjectButton::SetButtonOverlayText(const QString& text) + { + m_projectImageLabel->SetOverlayText(text); + } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h index c1aee8e63e..671debf6d0 100644 --- a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h +++ b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h @@ -32,11 +32,18 @@ namespace O3DE::ProjectManager explicit LabelButton(QWidget* parent = nullptr); ~LabelButton() = default; + void SetEnabled(bool enabled); + void SetOverlayText(const QString& text); + signals: void triggered(); public slots: void mousePressEvent(QMouseEvent* event) override; + + private: + QLabel* m_overlayLabel; + bool m_enabled = true; }; class ProjectButton @@ -49,6 +56,9 @@ namespace O3DE::ProjectManager explicit ProjectButton(const QString& projectName, const QString& projectImage, QWidget* parent = nullptr); ~ProjectButton() = default; + void SetButtonEnabled(bool enabled); + void SetButtonOverlayText(const QString& text); + signals: void OpenProject(const QString& projectName); void EditProject(const QString& projectName); @@ -63,7 +73,6 @@ namespace O3DE::ProjectManager QString m_projectName; QString m_projectImagePath; LabelButton* m_projectImageLabel; - QPushButton* m_projectSettingsMenuButton; QAction* m_editProjectAction; QAction* m_editProjectGemsAction; QAction* m_copyProjectAction; diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp index eb79f2da1e..76bcc2eb99 100644 --- a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp @@ -11,52 +11,46 @@ */ #include -#include +#include #include #include #include -#include - namespace O3DE::ProjectManager { ProjectManagerWindow::ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath) : QMainWindow(parent) - , m_ui(new Ui::ProjectManagerWindowClass()) { - m_ui->setupUi(this); - QLayout* layout = m_ui->centralWidget->layout(); - layout->setMargin(0); - layout->setSpacing(0); - layout->setContentsMargins(0, 0, 0, 0); - m_pythonBindings = AZStd::make_unique(engineRootPath); - m_screensCtrl = new ScreensCtrl(); - m_ui->verticalLayout->addWidget(m_screensCtrl); + setWindowTitle(tr("O3DE Project Manager")); - connect(m_ui->projectsMenu, &QMenu::aboutToShow, this, &ProjectManagerWindow::HandleProjectsMenu); - connect(m_ui->engineMenu, &QMenu::aboutToShow, this, &ProjectManagerWindow::HandleEngineMenu); + ScreensCtrl* screensCtrl = new ScreensCtrl(); + // currently the tab order on the home page is based on the order of this list + QVector screenEnums = + { + ProjectManagerScreen::Projects, + ProjectManagerScreen::EngineSettings, + ProjectManagerScreen::CreateProject, + ProjectManagerScreen::UpdateProject + }; + screensCtrl->BuildScreens(screenEnums); + + setCentralWidget(screensCtrl); + + // setup stylesheets and hot reloading QDir rootDir = QString::fromUtf8(engineRootPath.Native().data(), aznumeric_cast(engineRootPath.Native().size())); const auto pathOnDisk = rootDir.absoluteFilePath("Code/Tools/ProjectManager/Resources"); const auto qrcPath = QStringLiteral(":/ProjectManager/style"); AzQtComponents::StyleManager::addSearchPaths("style", pathOnDisk, qrcPath, engineRootPath); + // set stylesheet after creating the screens or their styles won't get updated AzQtComponents::StyleManager::setStyleSheet(this, QStringLiteral("style:ProjectManager.qss")); - QVector screenEnums = - { - ProjectManagerScreen::FirstTimeUse, - ProjectManagerScreen::CreateProject, - ProjectManagerScreen::ProjectsHome, - ProjectManagerScreen::UpdateProject, - ProjectManagerScreen::EngineSettings - }; - m_screensCtrl->BuildScreens(screenEnums); - m_screensCtrl->ForceChangeToScreen(ProjectManagerScreen::FirstTimeUse, false); + screensCtrl->ForceChangeToScreen(ProjectManagerScreen::Projects, false); } ProjectManagerWindow::~ProjectManagerWindow() @@ -64,13 +58,4 @@ namespace O3DE::ProjectManager m_pythonBindings.reset(); } - void ProjectManagerWindow::HandleProjectsMenu() - { - m_screensCtrl->ChangeToScreen(ProjectManagerScreen::ProjectsHome); - } - void ProjectManagerWindow::HandleEngineMenu() - { - m_screensCtrl->ChangeToScreen(ProjectManagerScreen::EngineSettings); - } - } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.h b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.h index d5c586e59b..74db3467c5 100644 --- a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.h +++ b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.h @@ -13,17 +13,9 @@ #if !defined(Q_MOC_RUN) #include - -#include - #include #endif -namespace Ui -{ - class ProjectManagerWindowClass; -} - namespace O3DE::ProjectManager { class ProjectManagerWindow @@ -35,13 +27,7 @@ namespace O3DE::ProjectManager explicit ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath); ~ProjectManagerWindow(); - protected slots: - void HandleProjectsMenu(); - void HandleEngineMenu(); - private: - QScopedPointer m_ui; - ScreensCtrl* m_screensCtrl; AZStd::unique_ptr m_pythonBindings; }; diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.ui b/Code/Tools/ProjectManager/Source/ProjectManagerWindow.ui deleted file mode 100644 index 633cd61182..0000000000 --- a/Code/Tools/ProjectManager/Source/ProjectManagerWindow.ui +++ /dev/null @@ -1,67 +0,0 @@ - - - ProjectManagerWindowClass - - - - 0 - 0 - 1200 - 800 - - - - - 0 - 0 - - - - O3DE Project Manager - - - - - - - - 0 - 0 - 1200 - 36 - - - - - 16 - - - - - Icon - - - - :/o3de_editor.ico:/o3de_editor.ico - - - - - Projects - - - - - Engine - - - - - - - - - - - - diff --git a/Code/Tools/ProjectManager/Source/ProjectsHomeScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectsHomeScreen.cpp deleted file mode 100644 index 411b46c55d..0000000000 --- a/Code/Tools/ProjectManager/Source/ProjectsHomeScreen.cpp +++ /dev/null @@ -1,158 +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. - * - */ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace O3DE::ProjectManager -{ - ProjectsHomeScreen::ProjectsHomeScreen(QWidget* parent) - : ScreenWidget(parent) - { - QVBoxLayout* vLayout = new QVBoxLayout(); - setLayout(vLayout); - vLayout->setContentsMargins(s_contentMargins, s_contentMargins, s_contentMargins, s_contentMargins); - - QHBoxLayout* topLayout = new QHBoxLayout(); - - QLabel* titleLabel = new QLabel(this); - titleLabel->setText("My Projects"); - titleLabel->setStyleSheet("font-size: 24px"); - topLayout->addWidget(titleLabel); - - QSpacerItem* topSpacer = new QSpacerItem(s_spacerSize, s_spacerSize, QSizePolicy::Expanding, QSizePolicy::Minimum); - topLayout->addItem(topSpacer); - - QMenu* newProjectMenu = new QMenu(this); - m_createNewProjectAction = newProjectMenu->addAction("Create New Project"); - m_addExistingProjectAction = newProjectMenu->addAction("Add Existing Project"); - - QPushButton* newProjectMenuButton = new QPushButton(this); - newProjectMenuButton->setText("New Project..."); - newProjectMenuButton->setMenu(newProjectMenu); - newProjectMenuButton->setFixedWidth(s_newProjectButtonWidth); - newProjectMenuButton->setStyleSheet("font-size: 14px;"); - topLayout->addWidget(newProjectMenuButton); - - vLayout->addLayout(topLayout); - - // Get all projects and create a horizontal scrolling list of them - auto projectsResult = PythonBindingsInterface::Get()->GetProjects(); - if (projectsResult.IsSuccess() && !projectsResult.GetValue().isEmpty()) - { - QScrollArea* projectsScrollArea = new QScrollArea(this); - QWidget* scrollWidget = new QWidget(); - QGridLayout* projectGridLayout = new QGridLayout(); - scrollWidget->setLayout(projectGridLayout); - projectsScrollArea->setWidget(scrollWidget); - projectsScrollArea->setWidgetResizable(true); - - int gridIndex = 0; - for (auto project : projectsResult.GetValue()) - { - ProjectButton* projectButton; - QString projectPreviewPath = project.m_path + m_projectPreviewImagePath; - QFileInfo doesPreviewExist(projectPreviewPath); - if (doesPreviewExist.exists() && doesPreviewExist.isFile()) - { - projectButton = new ProjectButton(project.m_projectName, projectPreviewPath, this); - } - else - { - projectButton = new ProjectButton(project.m_projectName, this); - } - - // Create rows of projects buttons s_projectButtonRowCount buttons wide - projectGridLayout->addWidget(projectButton, gridIndex / s_projectButtonRowCount, gridIndex % s_projectButtonRowCount); - - connect(projectButton, &ProjectButton::OpenProject, this, &ProjectsHomeScreen::HandleOpenProject); - connect(projectButton, &ProjectButton::EditProject, this, &ProjectsHomeScreen::HandleEditProject); - -#ifdef SHOW_ALL_PROJECT_ACTIONS - connect(projectButton, &ProjectButton::EditProjectGems, this, &ProjectsHomeScreen::HandleEditProjectGems); - connect(projectButton, &ProjectButton::CopyProject, this, &ProjectsHomeScreen::HandleCopyProject); - connect(projectButton, &ProjectButton::RemoveProject, this, &ProjectsHomeScreen::HandleRemoveProject); - connect(projectButton, &ProjectButton::DeleteProject, this, &ProjectsHomeScreen::HandleDeleteProject); -#endif - ++gridIndex; - } - - vLayout->addWidget(projectsScrollArea); - } - - // Using border-image allows for scaling options background-image does not support - setStyleSheet("O3DE--ProjectManager--ScreenWidget { border-image: url(:/Backgrounds/FirstTimeBackgroundImage.jpg) repeat repeat; }"); - - connect(m_createNewProjectAction, &QAction::triggered, this, &ProjectsHomeScreen::HandleNewProjectButton); - connect(m_addExistingProjectAction, &QAction::triggered, this, &ProjectsHomeScreen::HandleAddProjectButton); - } - - ProjectManagerScreen ProjectsHomeScreen::GetScreenEnum() - { - return ProjectManagerScreen::ProjectsHome; - } - - void ProjectsHomeScreen::HandleNewProjectButton() - { - emit ResetScreenRequest(ProjectManagerScreen::CreateProject); - emit ChangeScreenRequest(ProjectManagerScreen::CreateProject); - } - void ProjectsHomeScreen::HandleAddProjectButton() - { - // Do nothing for now - } - void ProjectsHomeScreen::HandleOpenProject(const QString& projectPath) - { - // Open the editor with this project open - emit NotifyCurrentProject(projectPath); - } - void ProjectsHomeScreen::HandleEditProject(const QString& projectPath) - { - emit NotifyCurrentProject(projectPath); - emit ResetScreenRequest(ProjectManagerScreen::UpdateProject); - emit ChangeScreenRequest(ProjectManagerScreen::UpdateProject); - } - void ProjectsHomeScreen::HandleEditProjectGems(const QString& projectPath) - { - emit NotifyCurrentProject(projectPath); - emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog); - } - void ProjectsHomeScreen::HandleCopyProject([[maybe_unused]] const QString& projectPath) - { - // Open file dialog and choose location for copied project then register copy with O3DE - } - void ProjectsHomeScreen::HandleRemoveProject([[maybe_unused]] const QString& projectPath) - { - // Unregister Project from O3DE - } - void ProjectsHomeScreen::HandleDeleteProject([[maybe_unused]] const QString& projectPath) - { - // Remove project from 03DE and delete from disk - ProjectsHomeScreen::HandleRemoveProject(projectPath); - } - -} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp new file mode 100644 index 0000000000..5f1c0e2b36 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp @@ -0,0 +1,347 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define DISPLAY_PROJECT_DEV_DATA true + +namespace O3DE::ProjectManager +{ + ProjectsScreen::ProjectsScreen(QWidget* parent) + : ScreenWidget(parent) + { + QVBoxLayout* vLayout = new QVBoxLayout(); + vLayout->setAlignment(Qt::AlignTop); + vLayout->setContentsMargins(s_contentMargins, 0, s_contentMargins, 0); + setLayout(vLayout); + + m_background.load(":/Backgrounds/FirstTimeBackgroundImage.jpg"); + + m_stack = new QStackedWidget(this); + + m_firstTimeContent = CreateFirstTimeContent(); + m_stack->addWidget(m_firstTimeContent); + + m_projectsContent = CreateProjectsContent(); + m_stack->addWidget(m_projectsContent); + + vLayout->addWidget(m_stack); + + connect(m_createNewProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleNewProjectButton); + connect(m_addExistingProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleAddProjectButton); + } + + QFrame* ProjectsScreen::CreateFirstTimeContent() + { + QFrame* frame = new QFrame(this); + frame->setObjectName("firstTimeContent"); + { + QVBoxLayout* layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->setAlignment(Qt::AlignTop); + frame->setLayout(layout); + + QLabel* titleLabel = new QLabel(tr("Ready. Set. Create."), this); + titleLabel->setObjectName("titleLabel"); + layout->addWidget(titleLabel); + + QLabel* introLabel = new QLabel(this); + introLabel->setObjectName("introLabel"); + introLabel->setText(tr("Welcome to O3DE! Start something new by creating a project. Not sure what to create? \nExplore what's " + "available by downloading our sample project.")); + layout->addWidget(introLabel); + + QHBoxLayout* buttonLayout = new QHBoxLayout(this); + buttonLayout->setAlignment(Qt::AlignLeft); + buttonLayout->setSpacing(s_spacerSize); + + // use a newline to force the text up + QPushButton* createProjectButton = new QPushButton(tr("Create a Project\n"), this); + createProjectButton->setObjectName("createProjectButton"); + buttonLayout->addWidget(createProjectButton); + + QPushButton* addProjectButton = new QPushButton(tr("Add a Project\n"), this); + addProjectButton->setObjectName("addProjectButton"); + buttonLayout->addWidget(addProjectButton); + + connect(createProjectButton, &QPushButton::clicked, this, &ProjectsScreen::HandleNewProjectButton); + connect(addProjectButton, &QPushButton::clicked, this, &ProjectsScreen::HandleAddProjectButton); + + layout->addLayout(buttonLayout); + } + + return frame; + } + + QFrame* ProjectsScreen::CreateProjectsContent() + { + QFrame* frame = new QFrame(this); + frame->setObjectName("projectsContent"); + { + QVBoxLayout* layout = new QVBoxLayout(); + layout->setAlignment(Qt::AlignTop); + layout->setContentsMargins(0, 0, 0, 0); + frame->setLayout(layout); + + QFrame* header = new QFrame(this); + QHBoxLayout* headerLayout = new QHBoxLayout(); + { + QLabel* titleLabel = new QLabel(tr("My Projects"), this); + titleLabel->setObjectName("titleLabel"); + headerLayout->addWidget(titleLabel); + + QMenu* newProjectMenu = new QMenu(this); + m_createNewProjectAction = newProjectMenu->addAction("Create New Project"); + m_addExistingProjectAction = newProjectMenu->addAction("Add Existing Project"); + + connect(m_createNewProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleNewProjectButton); + connect(m_addExistingProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleAddProjectButton); + + QPushButton* newProjectMenuButton = new QPushButton(tr("New Project..."), this); + newProjectMenuButton->setObjectName("newProjectButton"); + newProjectMenuButton->setMenu(newProjectMenu); + newProjectMenuButton->setDefault(true); + headerLayout->addWidget(newProjectMenuButton); + } + header->setLayout(headerLayout); + + layout->addWidget(header); + + // Get all projects and create a horizontal scrolling list of them + auto projectsResult = PythonBindingsInterface::Get()->GetProjects(); + if (projectsResult.IsSuccess() && !projectsResult.GetValue().isEmpty()) + { + QScrollArea* projectsScrollArea = new QScrollArea(this); + QWidget* scrollWidget = new QWidget(); + + FlowLayout* flowLayout = new FlowLayout(0, s_spacerSize, s_spacerSize); + scrollWidget->setLayout(flowLayout); + + projectsScrollArea->setWidget(scrollWidget); + projectsScrollArea->setWidgetResizable(true); + +#ifndef DISPLAY_PROJECT_DEV_DATA + for (auto project : projectsResult.GetValue()) +#else + ProjectInfo project = projectsResult.GetValue().at(0); + for (int i = 0; i < 15; i++) +#endif + { + ProjectButton* projectButton; + QString projectPreviewPath = project.m_path + m_projectPreviewImagePath; + QFileInfo doesPreviewExist(projectPreviewPath); + if (doesPreviewExist.exists() && doesPreviewExist.isFile()) + { + projectButton = new ProjectButton(project.m_projectName, projectPreviewPath, this); + } + else + { + projectButton = new ProjectButton(project.m_projectName, this); + } + + flowLayout->addWidget(projectButton); + + connect(projectButton, &ProjectButton::OpenProject, this, &ProjectsScreen::HandleOpenProject); + connect(projectButton, &ProjectButton::EditProject, this, &ProjectsScreen::HandleEditProject); + + #ifdef DISPLAY_PROJECT_DEV_DATA + connect(projectButton, &ProjectButton::EditProjectGems, this, &ProjectsScreen::HandleEditProjectGems); + connect(projectButton, &ProjectButton::CopyProject, this, &ProjectsScreen::HandleCopyProject); + connect(projectButton, &ProjectButton::RemoveProject, this, &ProjectsScreen::HandleRemoveProject); + connect(projectButton, &ProjectButton::DeleteProject, this, &ProjectsScreen::HandleDeleteProject); + #endif + } + + layout->addWidget(projectsScrollArea); + } + } + + return frame; + } + + ProjectManagerScreen ProjectsScreen::GetScreenEnum() + { + return ProjectManagerScreen::Projects; + } + + bool ProjectsScreen::IsTab() + { + return true; + } + + QString ProjectsScreen::GetTabText() + { + return tr("Projects"); + } + + void ProjectsScreen::paintEvent([[maybe_unused]] QPaintEvent* event) + { + // we paint the background here because qss does not support background cover scaling + QPainter painter(this); + + auto winSize = size(); + auto pixmapRatio = (float)m_background.width() / m_background.height(); + auto windowRatio = (float)winSize.width() / winSize.height(); + + if (pixmapRatio > windowRatio) + { + auto newWidth = (int)(winSize.height() * pixmapRatio); + auto offset = (newWidth - winSize.width()) / -2; + painter.drawPixmap(offset, 0, newWidth, winSize.height(), m_background); + } + else + { + auto newHeight = (int)(winSize.width() / pixmapRatio); + painter.drawPixmap(0, 0, winSize.width(), newHeight, m_background); + } + } + + void ProjectsScreen::HandleNewProjectButton() + { + emit ResetScreenRequest(ProjectManagerScreen::CreateProject); + emit ChangeScreenRequest(ProjectManagerScreen::CreateProject); + } + void ProjectsScreen::HandleAddProjectButton() + { + // Do nothing for now + } + void ProjectsScreen::HandleOpenProject(const QString& projectPath) + { + if (!projectPath.isEmpty()) + { + AZ::IO::FixedMaxPath executableDirectory = AZ::Utils::GetExecutableDirectory(); + AZStd::string executableFilename = "Editor"; + AZ::IO::FixedMaxPath editorExecutablePath = executableDirectory / (executableFilename + AZ_TRAIT_OS_EXECUTABLE_EXTENSION); + auto cmdPath = AZ::IO::FixedMaxPathString::format("%s -regset=\"/Amazon/AzCore/Bootstrap/project_path=%s\"", editorExecutablePath.c_str(), projectPath.toStdString().c_str()); + + AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; + processLaunchInfo.m_commandlineParameters = cmdPath; + bool launchSucceeded = AzFramework::ProcessLauncher::LaunchUnwatchedProcess(processLaunchInfo); + if (!launchSucceeded) + { + AZ_Error("ProjectManager", false, "Failed to launch editor"); + QMessageBox::critical( this, tr("Error"), tr("Failed to launch the Editor, please verify the project settings are valid.")); + } + else + { + // prevent the user from accidentally pressing the button while the editor is launching + // and let them know what's happening + ProjectButton* button = qobject_cast(sender()); + if (button) + { + button->SetButtonEnabled(false); + button->SetButtonOverlayText(tr("Opening Editor...")); + } + + // enable the button after 3 seconds + constexpr int waitTimeInMs = 3000; + QTimer::singleShot(waitTimeInMs, this, [this, button] { + if (button) + { + button->SetButtonEnabled(true); + } + }); + } + } + else + { + AZ_Error("ProjectManager", false, "Cannot open editor because an empty project path was provided"); + QMessageBox::critical( this, tr("Error"), tr("Failed to launch the Editor because the project path is invalid.")); + } + + } + void ProjectsScreen::HandleEditProject(const QString& projectPath) + { + emit NotifyCurrentProject(projectPath); + emit ResetScreenRequest(ProjectManagerScreen::UpdateProject); + emit ChangeScreenRequest(ProjectManagerScreen::UpdateProject); + } + void ProjectsScreen::HandleEditProjectGems(const QString& projectPath) + { + emit NotifyCurrentProject(projectPath); + emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog); + } + void ProjectsScreen::HandleCopyProject([[maybe_unused]] const QString& projectPath) + { + // Open file dialog and choose location for copied project then register copy with O3DE + } + void ProjectsScreen::HandleRemoveProject([[maybe_unused]] const QString& projectPath) + { + // Unregister Project from O3DE + } + void ProjectsScreen::HandleDeleteProject([[maybe_unused]] const QString& projectPath) + { + // Remove project from 03DE and delete from disk + ProjectsScreen::HandleRemoveProject(projectPath); + } + + void ProjectsScreen::NotifyCurrentScreen() + { + if (ShouldDisplayFirstTimeContent()) + { + m_stack->setCurrentWidget(m_firstTimeContent); + } + else + { + m_stack->setCurrentWidget(m_projectsContent); + } + } + + bool ProjectsScreen::ShouldDisplayFirstTimeContent() + { + auto projectsResult = PythonBindingsInterface::Get()->GetProjects(); + if (!projectsResult.IsSuccess() || projectsResult.GetValue().isEmpty()) + { + return true; + } + + QSettings settings; + bool displayFirstTimeContent = settings.value("displayFirstTimeContent", true).toBool(); + if (displayFirstTimeContent) + { + settings.setValue("displayFirstTimeContent", false); + } + + return displayFirstTimeContent; + } + +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectsHomeScreen.h b/Code/Tools/ProjectManager/Source/ProjectsScreen.h similarity index 69% rename from Code/Tools/ProjectManager/Source/ProjectsHomeScreen.h rename to Code/Tools/ProjectManager/Source/ProjectsScreen.h index e8d1ac4fb5..d88ba8398d 100644 --- a/Code/Tools/ProjectManager/Source/ProjectsHomeScreen.h +++ b/Code/Tools/ProjectManager/Source/ProjectsScreen.h @@ -15,16 +15,26 @@ #include #endif +QT_FORWARD_DECLARE_CLASS(QPaintEvent) +QT_FORWARD_DECLARE_CLASS(QFrame) +QT_FORWARD_DECLARE_CLASS(QStackedWidget) + namespace O3DE::ProjectManager { - class ProjectsHomeScreen + class ProjectsScreen : public ScreenWidget { public: - explicit ProjectsHomeScreen(QWidget* parent = nullptr); - ~ProjectsHomeScreen() = default; + explicit ProjectsScreen(QWidget* parent = nullptr); + ~ProjectsScreen() = default; + ProjectManagerScreen GetScreenEnum() override; + QString GetTabText() override; + bool IsTab() override; + + protected: + void NotifyCurrentScreen() override; protected slots: void HandleNewProjectButton(); @@ -36,16 +46,24 @@ namespace O3DE::ProjectManager void HandleRemoveProject(const QString& projectPath); void HandleDeleteProject(const QString& projectPath); + void paintEvent(QPaintEvent* event) override; + private: + QFrame* CreateFirstTimeContent(); + QFrame* CreateProjectsContent(); + bool ShouldDisplayFirstTimeContent(); + QAction* m_createNewProjectAction; QAction* m_addExistingProjectAction; + QPixmap m_background; + QFrame* m_firstTimeContent; + QFrame* m_projectsContent; + QStackedWidget* m_stack; const QString m_projectPreviewImagePath = "/preview.png"; + inline constexpr static int s_contentMargins = 80; inline constexpr static int s_spacerSize = 20; - inline constexpr static int s_projectButtonRowCount = 4; - inline constexpr static int s_newProjectButtonWidth = 156; - }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ScreenDefs.h b/Code/Tools/ProjectManager/Source/ScreenDefs.h index 13289e2481..46d243f677 100644 --- a/Code/Tools/ProjectManager/Source/ScreenDefs.h +++ b/Code/Tools/ProjectManager/Source/ScreenDefs.h @@ -17,11 +17,10 @@ namespace O3DE::ProjectManager { Invalid = -1, Empty, - FirstTimeUse, CreateProject, NewProjectSettings, GemCatalog, - ProjectsHome, + Projects, UpdateProject, ProjectSettings, EngineSettings diff --git a/Code/Tools/ProjectManager/Source/ScreenFactory.cpp b/Code/Tools/ProjectManager/Source/ScreenFactory.cpp index d37ccdb59f..b2b4376e14 100644 --- a/Code/Tools/ProjectManager/Source/ScreenFactory.cpp +++ b/Code/Tools/ProjectManager/Source/ScreenFactory.cpp @@ -11,12 +11,11 @@ */ #include -#include #include #include #include #include -#include +#include #include #include @@ -28,9 +27,6 @@ namespace O3DE::ProjectManager switch(screen) { - case (ProjectManagerScreen::FirstTimeUse): - newScreen = new FirstTimeUseScreen(parent); - break; case (ProjectManagerScreen::CreateProject): newScreen = new CreateProjectCtrl(parent); break; @@ -40,8 +36,8 @@ namespace O3DE::ProjectManager case (ProjectManagerScreen::GemCatalog): newScreen = new GemCatalogScreen(parent); break; - case (ProjectManagerScreen::ProjectsHome): - newScreen = new ProjectsHomeScreen(parent); + case (ProjectManagerScreen::Projects): + newScreen = new ProjectsScreen(parent); break; case (ProjectManagerScreen::UpdateProject): newScreen = new UpdateProjectCtrl(parent); diff --git a/Code/Tools/ProjectManager/Source/ScreenHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/ScreenHeaderWidget.cpp new file mode 100644 index 0000000000..29b1eb6ff6 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/ScreenHeaderWidget.cpp @@ -0,0 +1,62 @@ +/* +* 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 + +namespace O3DE::ProjectManager +{ + ScreenHeader::ScreenHeader(QWidget* parent) + : QFrame(parent) + { + setObjectName("header"); + + QHBoxLayout* layout = new QHBoxLayout(); + layout->setAlignment(Qt::AlignLeft); + layout->setContentsMargins(0,0,0,0); + + m_backButton = new QPushButton(); + m_backButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + layout->addWidget(m_backButton); + + QVBoxLayout* titleLayout = new QVBoxLayout(); + m_title = new QLabel(); + m_title->setObjectName("headerTitle"); + titleLayout->addWidget(m_title); + + m_subTitle = new QLabel(); + m_subTitle->setObjectName("headerSubTitle"); + titleLayout->addWidget(m_subTitle); + + layout->addLayout(titleLayout); + + setLayout(layout); + } + + void ScreenHeader::setTitle(const QString& text) + { + m_title->setText(text); + } + + void ScreenHeader::setSubTitle(const QString& text) + { + m_subTitle->setText(text); + } + + QPushButton* ScreenHeader::backButton() + { + return m_backButton; + } + +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ScreenHeaderWidget.h b/Code/Tools/ProjectManager/Source/ScreenHeaderWidget.h new file mode 100644 index 0000000000..c5fdb56195 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/ScreenHeaderWidget.h @@ -0,0 +1,42 @@ +/* +* 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 + +#if !defined(Q_MOC_RUN) +#include +#endif + +QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QPushButton) + +namespace O3DE::ProjectManager +{ + class ScreenHeader + : public QFrame + { + Q_OBJECT // AUTOMOC + + public: + ScreenHeader(QWidget* parent = nullptr); + + void setTitle(const QString& text); + void setSubTitle(const QString& text); + + QPushButton* backButton(); + + private: + QLabel* m_title; + QLabel* m_subTitle; + QPushButton* m_backButton; + }; +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ScreenWidget.h b/Code/Tools/ProjectManager/Source/ScreenWidget.h index e80747d67b..2ad6d30201 100644 --- a/Code/Tools/ProjectManager/Source/ScreenWidget.h +++ b/Code/Tools/ProjectManager/Source/ScreenWidget.h @@ -41,12 +41,27 @@ namespace O3DE::ProjectManager { return true; } + virtual bool IsTab() + { + return false; + } + virtual QString GetTabText() + { + return tr("Missing"); + } + + //! Notify this screen it is the current screen + virtual void NotifyCurrentScreen() + { + + } signals: void ChangeScreenRequest(ProjectManagerScreen screen); void GotoPreviousScreenRequest(); void ResetScreenRequest(ProjectManagerScreen screen); void NotifyCurrentProject(const QString& projectPath); + }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ScreensCtrl.cpp b/Code/Tools/ProjectManager/Source/ScreensCtrl.cpp index a77c434026..7d31d02f6c 100644 --- a/Code/Tools/ProjectManager/Source/ScreensCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/ScreensCtrl.cpp @@ -14,6 +14,7 @@ #include #include +#include #include namespace O3DE::ProjectManager @@ -21,17 +22,19 @@ namespace O3DE::ProjectManager ScreensCtrl::ScreensCtrl(QWidget* parent) : QWidget(parent) { + setObjectName("ScreensCtrl"); + QVBoxLayout* vLayout = new QVBoxLayout(); - vLayout->setMargin(0); - vLayout->setSpacing(0); vLayout->setContentsMargins(0, 0, 0, 0); setLayout(vLayout); m_screenStack = new QStackedWidget(); vLayout->addWidget(m_screenStack); - //Track the bottom of the stack - m_screenVisitOrder.push(ProjectManagerScreen::Invalid); + // add a tab widget at the bottom of the stack + m_tabWidget = new QTabWidget(); + m_screenStack->addWidget(m_tabWidget); + connect(m_tabWidget, &QTabWidget::currentChanged, this, &ScreensCtrl::TabChanged); } void ScreensCtrl::BuildScreens(QVector screens) @@ -57,7 +60,14 @@ namespace O3DE::ProjectManager ScreenWidget* ScreensCtrl::GetCurrentScreen() { - return reinterpret_cast(m_screenStack->currentWidget()); + if (m_screenStack->currentWidget() == m_tabWidget) + { + return reinterpret_cast(m_tabWidget->currentWidget()); + } + else + { + return reinterpret_cast(m_screenStack->currentWidget()); + } } bool ScreensCtrl::ChangeToScreen(ProjectManagerScreen screen) @@ -79,13 +89,28 @@ namespace O3DE::ProjectManager if (iterator != m_screenMap.end()) { ScreenWidget* currentScreen = GetCurrentScreen(); - if (currentScreen != iterator.value()) + ScreenWidget* newScreen = iterator.value(); + + if (currentScreen != newScreen) { if (addVisit) { - m_screenVisitOrder.push(currentScreen->GetScreenEnum()); + ProjectManagerScreen oldScreen = currentScreen->GetScreenEnum(); + m_screenVisitOrder.push(oldScreen); } - m_screenStack->setCurrentWidget(iterator.value()); + + if (newScreen->IsTab()) + { + m_tabWidget->setCurrentWidget(newScreen); + m_screenStack->setCurrentWidget(m_tabWidget); + } + else + { + m_screenStack->setCurrentWidget(newScreen); + } + + newScreen->NotifyCurrentScreen(); + return true; } } @@ -95,23 +120,46 @@ namespace O3DE::ProjectManager bool ScreensCtrl::GotoPreviousScreen() { - // Don't go back if we are on the first set screen - if (m_screenVisitOrder.top() != ProjectManagerScreen::Invalid) + if (!m_screenVisitOrder.isEmpty()) { // We do not check with screen if we can go back, we should always be able to go back - return ForceChangeToScreen(m_screenVisitOrder.pop(), false); + ProjectManagerScreen previousScreen = m_screenVisitOrder.pop(); + return ForceChangeToScreen(previousScreen, false); } return false; } void ScreensCtrl::ResetScreen(ProjectManagerScreen screen) { + bool shouldRestoreCurrentScreen = false; + if (GetCurrentScreen() && GetCurrentScreen()->GetScreenEnum() == screen) + { + shouldRestoreCurrentScreen = true; + } + // Delete old screen if it exists to start fresh DeleteScreen(screen); // Add new screen ScreenWidget* newScreen = BuildScreen(this, screen); - m_screenStack->addWidget(newScreen); + if (newScreen->IsTab()) + { + m_tabWidget->addTab(newScreen, newScreen->GetTabText()); + if (shouldRestoreCurrentScreen) + { + m_tabWidget->setCurrentWidget(newScreen); + m_screenStack->setCurrentWidget(m_tabWidget); + } + } + else + { + m_screenStack->addWidget(newScreen); + if (shouldRestoreCurrentScreen) + { + m_screenStack->setCurrentWidget(newScreen); + } + } + m_screenMap.insert(screen, newScreen); connect(newScreen, &ScreenWidget::ChangeScreenRequest, this, &ScreensCtrl::ChangeToScreen); @@ -134,8 +182,21 @@ namespace O3DE::ProjectManager const auto iter = m_screenMap.find(screen); if (iter != m_screenMap.end()) { - m_screenStack->removeWidget(iter.value()); - iter.value()->deleteLater(); + ScreenWidget* screenToDelete = iter.value(); + if (screenToDelete->IsTab()) + { + int tabIndex = m_tabWidget->indexOf(screenToDelete); + if (tabIndex > -1) + { + m_tabWidget->removeTab(tabIndex); + } + } + else + { + // if the screen we delete is the current widget, a new one will + // be selected automatically (randomly?) + m_screenStack->removeWidget(screenToDelete); + } // Erase does not cause a rehash so interators remain valid m_screenMap.erase(iter); @@ -150,4 +211,12 @@ namespace O3DE::ProjectManager } } + void ScreensCtrl::TabChanged([[maybe_unused]] int index) + { + ScreenWidget* screen = reinterpret_cast(m_tabWidget->currentWidget()); + if (screen) + { + screen->NotifyCurrentScreen(); + } + } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ScreensCtrl.h b/Code/Tools/ProjectManager/Source/ScreensCtrl.h index a9d1023b4b..935fc78e25 100644 --- a/Code/Tools/ProjectManager/Source/ScreensCtrl.h +++ b/Code/Tools/ProjectManager/Source/ScreensCtrl.h @@ -18,6 +18,8 @@ #include #endif +QT_FORWARD_DECLARE_CLASS(QTabWidget) + namespace O3DE::ProjectManager { class ScreenWidget; @@ -46,11 +48,13 @@ namespace O3DE::ProjectManager void ResetAllScreens(); void DeleteScreen(ProjectManagerScreen screen); void DeleteAllScreens(); + void TabChanged(int index); private: QStackedWidget* m_screenStack; QHash m_screenMap; QStack m_screenVisitOrder; + QTabWidget* m_tabWidget; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index 84e3d8359d..b3180966ce 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -108,7 +108,7 @@ namespace O3DE::ProjectManager auto result = PythonBindingsInterface::Get()->UpdateProject(m_projectInfo); if (result) { - emit ChangeScreenRequest(ProjectManagerScreen::ProjectsHome); + emit ChangeScreenRequest(ProjectManagerScreen::Projects); } else { diff --git a/Code/Tools/ProjectManager/Source/main.cpp b/Code/Tools/ProjectManager/Source/main.cpp index 3d8bb71a0c..cbeacbaf65 100644 --- a/Code/Tools/ProjectManager/Source/main.cpp +++ b/Code/Tools/ProjectManager/Source/main.cpp @@ -35,7 +35,6 @@ int main(int argc, char* argv[]) QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware); - AZ::AllocatorInstance::Create(); int runSuccess = 0; { @@ -55,6 +54,12 @@ int main(int argc, char* argv[]) O3DE::ProjectManager::ProjectManagerWindow window(nullptr, engineRootPath); window.show(); + // somethings is preventing us from moving the window to the center of the + // primary screen - likely an Az style or component helper + constexpr int width = 1200; + constexpr int height = 800; + window.resize(width, height); + runSuccess = app.exec(); } AZ::AllocatorInstance::Destroy(); diff --git a/Code/Tools/ProjectManager/project_manager_files.cmake b/Code/Tools/ProjectManager/project_manager_files.cmake index a41ddad21e..223465f3c8 100644 --- a/Code/Tools/ProjectManager/project_manager_files.cmake +++ b/Code/Tools/ProjectManager/project_manager_files.cmake @@ -21,8 +21,6 @@ set(FILES Source/ScreenWidget.h Source/EngineInfo.h Source/EngineInfo.cpp - Source/FirstTimeUseScreen.h - Source/FirstTimeUseScreen.cpp Source/FormLineEditWidget.h Source/FormLineEditWidget.cpp Source/FormBrowseEditWidget.h @@ -33,7 +31,6 @@ set(FILES Source/ProjectManagerWindow.cpp Source/ProjectTemplateInfo.h Source/ProjectTemplateInfo.cpp - Source/ProjectManagerWindow.ui Source/PythonBindings.h Source/PythonBindings.cpp Source/PythonBindingsInterface.h @@ -45,8 +42,8 @@ set(FILES Source/CreateProjectCtrl.cpp Source/UpdateProjectCtrl.h Source/UpdateProjectCtrl.cpp - Source/ProjectsHomeScreen.h - Source/ProjectsHomeScreen.cpp + Source/ProjectsScreen.h + Source/ProjectsScreen.cpp Source/ProjectSettingsScreen.h Source/ProjectSettingsScreen.cpp Source/ProjectSettingsScreen.ui @@ -54,6 +51,8 @@ set(FILES Source/EngineSettingsScreen.cpp Source/ProjectButtonWidget.h Source/ProjectButtonWidget.cpp + Source/ScreenHeaderWidget.h + Source/ScreenHeaderWidget.cpp Source/LinkWidget.h Source/LinkWidget.cpp Source/TagWidget.h diff --git a/Code/Tools/SerializeContextTools/SliceConverter.h b/Code/Tools/SerializeContextTools/SliceConverter.h index 8dba6a0e55..a977095f02 100644 --- a/Code/Tools/SerializeContextTools/SliceConverter.h +++ b/Code/Tools/SerializeContextTools/SliceConverter.h @@ -52,7 +52,7 @@ namespace AZ static bool ConvertNestedSlices( SliceComponent* sliceComponent, AzToolsFramework::Prefab::Instance* sourceInstance, AZ::SerializeContext* serializeContext, bool isDryRun); - static bool SliceConverter::ConvertSliceInstance( + static bool ConvertSliceInstance( AZ::SliceComponent::SliceInstance& instance, AZ::Data::Asset& sliceAsset, AzToolsFramework::Prefab::TemplateReference nestedTemplate, AzToolsFramework::Prefab::Instance* topLevelInstance); static void PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.cpp index 04b015a66f..bf584c4d63 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.cpp @@ -108,11 +108,11 @@ namespace ImageProcessingAtomEditor { readableString = "PC"; } - else if (platformStrLowerCase == "es3") + else if (platformStrLowerCase == "android") { readableString = "Android"; } - else if (platformStrLowerCase == "osx_gl") + else if (platformStrLowerCase == "mac") { readableString = "macOS"; } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Platform/Mac/ImageProcessing_Traits_Mac.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Platform/Mac/ImageProcessing_Traits_Mac.h index 28c1e78bb6..ef0e7f9619 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Platform/Mac/ImageProcessing_Traits_Mac.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Platform/Mac/ImageProcessing_Traits_Mac.h @@ -12,7 +12,7 @@ #pragma once #define AZ_TRAIT_IMAGEPROCESSING_BESSEL_FUNCTION_FIRST_ORDER j1 -#define AZ_TRAIT_IMAGEPROCESSING_DEFAULT_PLATFORM "osx_gl" +#define AZ_TRAIT_IMAGEPROCESSING_DEFAULT_PLATFORM "mac" #define AZ_TRAIT_IMAGEPROCESSING_DEFINE_DIRECT3D_CONSTANTS 1 #define AZ_TRAIT_IMAGEPROCESSING_PVRTEXLIB_USE_WINDLL_IMPORT 0 #define AZ_TRAIT_IMAGEPROCESSING_SQUISH_DO_NOT_USE_FASTCALL 1 diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Platform/iOS/ImageProcessing_Traits_iOS.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Platform/iOS/ImageProcessing_Traits_iOS.h index 28c1e78bb6..ef0e7f9619 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Platform/iOS/ImageProcessing_Traits_iOS.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Platform/iOS/ImageProcessing_Traits_iOS.h @@ -12,7 +12,7 @@ #pragma once #define AZ_TRAIT_IMAGEPROCESSING_BESSEL_FUNCTION_FIRST_ORDER j1 -#define AZ_TRAIT_IMAGEPROCESSING_DEFAULT_PLATFORM "osx_gl" +#define AZ_TRAIT_IMAGEPROCESSING_DEFAULT_PLATFORM "mac" #define AZ_TRAIT_IMAGEPROCESSING_DEFINE_DIRECT3D_CONSTANTS 1 #define AZ_TRAIT_IMAGEPROCESSING_PVRTEXLIB_USE_WINDLL_IMPORT 0 #define AZ_TRAIT_IMAGEPROCESSING_SQUISH_DO_NOT_USE_FASTCALL 1 diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/1024x1024_24bit.tif.exportsettings b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/1024x1024_24bit.tif.exportsettings index 0417122033..7bce3041b9 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/1024x1024_24bit.tif.exportsettings +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/1024x1024_24bit.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /bumptype=none /M=62,18,32,83,50,50 /preset=Diffuse_highQ /mipgentype=kaiser /reduce="es3:0,ios:3,osx_gl:0,pc:4,provo:1" /ser=0 +/autooptimizefile=0 /bumptype=none /M=62,18,32,83,50,50 /preset=Diffuse_highQ /mipgentype=kaiser /reduce="android:0,ios:3,mac:0,pc:4,provo:1" /ser=0 diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Albedo.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Albedo.preset index 0b68493198..3a5122f18e 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Albedo.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Albedo.preset @@ -25,7 +25,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{08A95286-ADB2-41E4-96EB-DB48F4726D6A}", "Name": "Albedo", "RGB_Weight": "CIEXYZ", @@ -67,7 +67,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{08A95286-ADB2-41E4-96EB-DB48F4726D6A}", "Name": "Albedo", "RGB_Weight": "CIEXYZ", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithCoverage.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithCoverage.preset index 3773857e0a..692ef99b1c 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithCoverage.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithCoverage.preset @@ -23,7 +23,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{57ED16B1-407B-4E29-BCFC-D3BAE60F2C85}", "Name": "AlbedoWithCoverage", "RGB_Weight": "CIEXYZ", @@ -61,7 +61,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{57ED16B1-407B-4E29-BCFC-D3BAE60F2C85}", "Name": "AlbedoWithCoverage", "RGB_Weight": "CIEXYZ", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithGenericAlpha.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithGenericAlpha.preset index 530e36038d..4ebe773f0e 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithGenericAlpha.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithGenericAlpha.preset @@ -23,7 +23,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{5D9ECB52-4CD9-4CB8-80E3-10CAE5EFB8A2}", "Name": "AlbedoWithGenericAlpha", "RGB_Weight": "CIEXYZ", @@ -61,7 +61,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{5D9ECB52-4CD9-4CB8-80E3-10CAE5EFB8A2}", "Name": "AlbedoWithGenericAlpha", "RGB_Weight": "CIEXYZ", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithOpacity.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithOpacity.preset index 6d6c156683..6049ef5bd4 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithOpacity.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithOpacity.preset @@ -23,7 +23,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{7BB7BC6C-D3DA-4184-AC42-BCD8C57DE565}", "Name": "AlbedoWithOpacity", "RGB_Weight": "CIEXYZ", @@ -61,7 +61,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{7BB7BC6C-D3DA-4184-AC42-BCD8C57DE565}", "Name": "AlbedoWithOpacity", "RGB_Weight": "CIEXYZ", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/AmbientOcclusion.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/AmbientOcclusion.preset index 4e69ae67f2..56dec20f3e 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/AmbientOcclusion.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/AmbientOcclusion.preset @@ -17,7 +17,7 @@ "PixelFormat": "BC4" }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{02ED0ECE-B198-49D9-85BC-CEBA6C28546C}", "Name": "AmbientOcclusion", "SourceColor": "Linear", @@ -43,7 +43,7 @@ ], "PixelFormat": "EAC_R11" }, - "osx_gl": { + "mac": { "UUID": "{02ED0ECE-B198-49D9-85BC-CEBA6C28546C}", "Name": "AmbientOcclusion", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/CloudShadows.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/CloudShadows.preset index f37acd2f9d..2280a06302 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/CloudShadows.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/CloudShadows.preset @@ -11,7 +11,7 @@ "IsPowerOf2": true }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{884B5F7C-44AC-4E9E-8B8A-559D098BE2C7}", "Name": "CloudShadows", "DestColor": "Linear", @@ -25,7 +25,7 @@ "PixelFormat": "EAC_R11", "IsPowerOf2": true }, - "osx_gl": { + "mac": { "UUID": "{884B5F7C-44AC-4E9E-8B8A-559D098BE2C7}", "Name": "CloudShadows", "DestColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/ColorChart.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/ColorChart.preset index 46327e87ed..5f0480cee7 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/ColorChart.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/ColorChart.preset @@ -15,7 +15,7 @@ "IsColorChart": true }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{0A17A85F-07EE-48A0-8BF8-D42F0A5E0B3C}", "Name": "ColorChart", "SourceColor": "Linear", @@ -37,7 +37,7 @@ "PixelFormat": "R8G8B8X8", "IsColorChart": true }, - "osx_gl": { + "mac": { "UUID": "{0A17A85F-07EE-48A0-8BF8-D42F0A5E0B3C}", "Name": "ColorChart", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/ConvolvedCubemap.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/ConvolvedCubemap.preset index fe87f49426..abdf6501be 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/ConvolvedCubemap.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/ConvolvedCubemap.preset @@ -30,7 +30,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{2174E04B-73BB-4DF1-8961-4900DC3C9D72}", "Name": "ConvolvedCubemap", "SourceColor": "Linear", @@ -82,7 +82,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{2174E04B-73BB-4DF1-8961-4900DC3C9D72}", "Name": "ConvolvedCubemap", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Decal_AlbedoWithOpacity.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Decal_AlbedoWithOpacity.preset index 2c47f9eaed..f1e43e74b1 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Decal_AlbedoWithOpacity.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Decal_AlbedoWithOpacity.preset @@ -18,7 +18,7 @@ "NumberResidentMips": 255 }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{E06B5087-2640-49B6-B9BA-D40048162B90}", "Name": "Decal_AlbedoWithOpacity", "FileMasks": [ @@ -46,7 +46,7 @@ // Decal Texture Arrays need all mips available immediately for packing. "NumberResidentMips": 255 }, - "osx_gl": { + "mac": { "UUID": "{E06B5087-2640-49B6-B9BA-D40048162B90}", "Name": "Decal_AlbedoWithOpacity", "FileMasks": [ diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness.preset index 23ec2347cd..991692c5cc 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness.preset @@ -18,7 +18,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{5096FC7B-0B2D-4466-9943-AD59922968E8}", "Name": "Detail_MergedAlbedoNormalsSmoothness", "SourceColor": "Linear", @@ -46,7 +46,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{5096FC7B-0B2D-4466-9943-AD59922968E8}", "Name": "Detail_MergedAlbedoNormalsSmoothness", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness_Lossless.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness_Lossless.preset index 3145c5cf8a..fec11218e8 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness_Lossless.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness_Lossless.preset @@ -17,7 +17,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{B6FC1AEF-907C-4157-9A1A-D9960F0E5B9A}", "Name": "Detail_MergedAlbedoNormalsSmoothness_Lossless", "SourceColor": "Linear", @@ -43,7 +43,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{B6FC1AEF-907C-4157-9A1A-D9960F0E5B9A}", "Name": "Detail_MergedAlbedoNormalsSmoothness_Lossless", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Displacement.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Displacement.preset index 86ba9d74c0..520e4ae193 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Displacement.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Displacement.preset @@ -28,7 +28,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{D7B4BEA6-6427-4295-B61B-62776D0056DE}", "Name": "Displacement", "SourceColor": "Linear", @@ -77,7 +77,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{D7B4BEA6-6427-4295-B61B-62776D0056DE}", "Name": "Displacement", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Emissive.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Emissive.preset index 5a98d2cd30..ffb16482fd 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Emissive.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Emissive.preset @@ -18,7 +18,7 @@ "DiscardAlpha": true }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{07041D83-E0C3-4726-8735-CA0FE550C9A0}", "Name": "Emissive", "RGB_Weight": "CIEXYZ", @@ -46,7 +46,7 @@ "PixelFormat": "ASTC_6x6", "DiscardAlpha": true }, - "osx_gl": { + "mac": { "UUID": "{07041D83-E0C3-4726-8735-CA0FE550C9A0}", "Name": "Emissive", "RGB_Weight": "CIEXYZ", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Gradient.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Gradient.preset index 9cf32093d1..33d7babf00 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Gradient.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Gradient.preset @@ -11,7 +11,7 @@ "IsPowerOf2": true }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{0D26B387-2FBA-456D-AB8E-613020BCC7F8}", "Name": "Gradient", "SourceColor": "Linear", @@ -25,7 +25,7 @@ "DestColor": "Linear", "IsPowerOf2": true }, - "osx_gl": { + "mac": { "UUID": "{0D26B387-2FBA-456D-AB8E-613020BCC7F8}", "Name": "Gradient", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Greyscale.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Greyscale.preset index c77c77b988..f06682be42 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Greyscale.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Greyscale.preset @@ -18,7 +18,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{B6B04FD3-BD7B-44AC-AD93-6FECD2BD4D76}", "Name": "Greyscale", "SourceColor": "Linear", @@ -46,7 +46,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{B6B04FD3-BD7B-44AC-AD93-6FECD2BD4D76}", "Name": "Greyscale", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLDiffuse.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLDiffuse.preset index fb4155a974..8bd6b348d1 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLDiffuse.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLDiffuse.preset @@ -28,7 +28,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}", "Name": "IBLDiffuse", "FileMasks": [ @@ -74,7 +74,7 @@ "SubId": 3000 } }, - "osx_gl": { + "mac": { "UUID": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}", "Name": "IBLDiffuse", "FileMasks": [ diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLSkybox.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLSkybox.preset index 530eb3d048..402fc470eb 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLSkybox.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLSkybox.preset @@ -26,7 +26,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{E6441EAC-9843-484B-8EFC-C03B2935B48D}", "Name": "IBLSkybox", "FileMasks": [ @@ -68,7 +68,7 @@ "IBLDiffusePreset": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}" } }, - "osx_gl": { + "mac": { "UUID": "{E6441EAC-9843-484B-8EFC-C03B2935B48D}", "Name": "IBLSkybox", "FileMasks": [ diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLSpecular.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLSpecular.preset index db5a9276bd..d940f425c2 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLSpecular.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLSpecular.preset @@ -30,7 +30,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}", "Name": "IBLSpecular", "FileMasks": [ @@ -80,7 +80,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}", "Name": "IBLSpecular", "FileMasks": [ diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/ImageBuilder.settings b/Gems/Atom/Asset/ImageProcessingAtom/Config/ImageBuilder.settings index c8d921a8ff..82a57dd614 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/ImageBuilder.settings +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/ImageBuilder.settings @@ -5,7 +5,7 @@ "ClassData": { "AnalysisFingerprint": "2", "BuildSettings": { - "es3": { + "android": { "GlossScale": 16.0, "GlossBias": 0.0, "Streaming": false, @@ -17,7 +17,7 @@ "Streaming": false, "Enable": true }, - "osx_gl": { + "mac": { "GlossScale": 16.0, "GlossBias": 0.0, "Streaming": false, diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_R32F.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_R32F.preset new file mode 100644 index 0000000000..1bb23c6e96 --- /dev/null +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_R32F.preset @@ -0,0 +1,45 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "MultiplatformPresetSettings", + "ClassData": { + "DefaultPreset": { + "UUID": "{10D4D7D8-23E2-4FC5-BE6A-DA9949D2C603}", + "Name": "LUT_R32F", + "FileMasks": ["_lutr32f"], + "SourceColor": "Linear", + "DestColor": "Linear", + "PixelFormat": "R32F" + }, + "PlatformsPresets": { + "es3": { + "UUID": "{10D4D7D8-23E2-4FC5-BE6A-DA9949D2C603}", + "Name": "LUT_R32F", + "SourceColor": "Linear", + "DestColor": "Linear", + "PixelFormat": "R32F" + }, + "ios": { + "UUID": "{10D4D7D8-23E2-4FC5-BE6A-DA9949D2C603}", + "Name": "LUT_R32F", + "SourceColor": "Linear", + "DestColor": "Linear", + "PixelFormat": "R32F" + }, + "osx_gl": { + "UUID": "{10D4D7D8-23E2-4FC5-BE6A-DA9949D2C603}", + "Name": "LUT_R32F", + "SourceColor": "Linear", + "DestColor": "Linear", + "PixelFormat": "R32F" + }, + "provo": { + "UUID": "{10D4D7D8-23E2-4FC5-BE6A-DA9949D2C603}", + "Name": "LUT_R32F", + "SourceColor": "Linear", + "DestColor": "Linear", + "PixelFormat": "R32F" + } + } + } +} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RG16.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RG16.preset index 6bfb697a5e..183653d111 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RG16.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RG16.preset @@ -11,7 +11,7 @@ "PixelFormat": "R16G16" }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{D55CBCD3-AF2D-4515-98AB-E278F6B3B5F6}", "Name": "LUT_RG16", "SourceColor": "Linear", @@ -25,7 +25,7 @@ "DestColor": "Linear", "PixelFormat": "R16G16" }, - "osx_gl": { + "mac": { "UUID": "{D55CBCD3-AF2D-4515-98AB-E278F6B3B5F6}", "Name": "LUT_RG16", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RG32F.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RG32F.preset index a010d26a9c..2cf0c6ca0a 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RG32F.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RG32F.preset @@ -12,7 +12,7 @@ "PixelFormat": "R32G32F" }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{52470B8B-0798-4E03-B0D3-039D5141CFEC}", "Name": "LUT_RG32F", "SourceColor": "Linear", @@ -26,7 +26,7 @@ "DestColor": "Linear", "PixelFormat": "R32G32F" }, - "osx_gl": { + "mac": { "UUID": "{52470B8B-0798-4E03-B0D3-039D5141CFEC}", "Name": "LUT_RG32F", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RG8.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RG8.preset index ca636f486a..9838d532b2 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RG8.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RG8.preset @@ -14,7 +14,7 @@ "PixelFormat": "R8G8" }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{3791319D-043B-4011-8B6F-3DE96D0C4309}", "Name": "LUT_RG8", "SourceColor": "Linear", @@ -34,7 +34,7 @@ ], "PixelFormat": "R8G8" }, - "osx_gl": { + "mac": { "UUID": "{3791319D-043B-4011-8B6F-3DE96D0C4309}", "Name": "LUT_RG8", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA16.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA16.preset new file mode 100644 index 0000000000..f36d566d7e --- /dev/null +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA16.preset @@ -0,0 +1,59 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "MultiplatformPresetSettings", + "ClassData": { + "DefaultPreset": { + "UUID": "{ABDFCED1-0565-4B7B-9BC1-82C473BCEEA2}", + "Name": "LUT_RGBA16", + "SourceColor": "Linear", + "DestColor": "Linear", + "FileMasks": [ + "_lutrgba16" + ], + "PixelFormat": "R16G16B16A16" + }, + "PlatformsPresets": { + "es3": { + "UUID": "{ABDFCED1-0565-4B7B-9BC1-82C473BCEEA2}", + "Name": "LUT_RGBA16", + "SourceColor": "Linear", + "DestColor": "Linear", + "FileMasks": [ + "_lutrgba16" + ], + "PixelFormat": "R16G16B16A16" + }, + "ios": { + "UUID": "{ABDFCED1-0565-4B7B-9BC1-82C473BCEEA2}", + "Name": "LUT_RGBA16", + "SourceColor": "Linear", + "DestColor": "Linear", + "FileMasks": [ + "_lutrgba16" + ], + "PixelFormat": "R16G16B16A16" + }, + "osx_gl": { + "UUID": "{ABDFCED1-0565-4B7B-9BC1-82C473BCEEA2}", + "Name": "LUT_RGBA16", + "SourceColor": "Linear", + "DestColor": "Linear", + "FileMasks": [ + "_lutrgba16" + ], + "PixelFormat": "R16G16B16A16" + }, + "provo": { + "UUID": "{ABDFCED1-0565-4B7B-9BC1-82C473BCEEA2}", + "Name": "LUT_RGBA16", + "SourceColor": "Linear", + "DestColor": "Linear", + "FileMasks": [ + "_lutrgba16" + ], + "PixelFormat": "R16G16B16A16" + } + } + } +} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA16F.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA16F.preset new file mode 100644 index 0000000000..367c5101b3 --- /dev/null +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA16F.preset @@ -0,0 +1,59 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "MultiplatformPresetSettings", + "ClassData": { + "DefaultPreset": { + "UUID": "{6D75F093-C826-437A-AD94-8631A5A4E8A2}", + "Name": "LUT_RGBA16F", + "SourceColor": "Linear", + "DestColor": "Linear", + "FileMasks": [ + "_lutrgba16f" + ], + "PixelFormat": "R16G16B16A16F" + }, + "PlatformsPresets": { + "es3": { + "UUID": "{6D75F093-C826-437A-AD94-8631A5A4E8A2}", + "Name": "LUT_RGBA16F", + "SourceColor": "Linear", + "DestColor": "Linear", + "FileMasks": [ + "_lutrgba16f" + ], + "PixelFormat": "R16G16B16A16F" + }, + "ios": { + "UUID": "{6D75F093-C826-437A-AD94-8631A5A4E8A2}", + "Name": "LUT_RGBA16F", + "SourceColor": "Linear", + "DestColor": "Linear", + "FileMasks": [ + "_lutrgba16f" + ], + "PixelFormat": "R16G16B16A16F" + }, + "osx_gl": { + "UUID": "{6D75F093-C826-437A-AD94-8631A5A4E8A2}", + "Name": "LUT_RGBA16F", + "SourceColor": "Linear", + "DestColor": "Linear", + "FileMasks": [ + "_lutrgba16f" + ], + "PixelFormat": "R16G16B16A16F" + }, + "provo": { + "UUID": "{6D75F093-C826-437A-AD94-8631A5A4E8A2}", + "Name": "LUT_RGBA16F", + "SourceColor": "Linear", + "DestColor": "Linear", + "FileMasks": [ + "_lutrgba16f" + ], + "PixelFormat": "R16G16B16A16F" + } + } + } +} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA32F.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA32F.preset index 717ece058d..3a456825bf 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA32F.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA32F.preset @@ -12,7 +12,7 @@ "PixelFormat": "R32G32B32A32F" }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{AC4C49D4-2C70-425A-8DBF-E7FB2C61CF8D}", "Name": "LUT_RGBA32F", "SourceColor": "Linear", @@ -26,7 +26,7 @@ "DestColor": "Linear", "PixelFormat": "R32G32B32A32F" }, - "osx_gl": { + "mac": { "UUID": "{AC4C49D4-2C70-425A-8DBF-E7FB2C61CF8D}", "Name": "LUT_RGBA32F", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA8.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA8.preset index 6dbb29f830..49bf33dd84 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA8.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LUT_RGBA8.preset @@ -10,7 +10,7 @@ "DestColor": "Linear" }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{3A6BB297-B610-4EA5-8DA4-610FB12B9EC0}", "Name": "LUT_RGBA8", "SourceColor": "Linear", @@ -22,7 +22,7 @@ "SourceColor": "Linear", "DestColor": "Linear" }, - "osx_gl": { + "mac": { "UUID": "{3A6BB297-B610-4EA5-8DA4-610FB12B9EC0}", "Name": "LUT_RGBA8", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LayerMask.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LayerMask.preset index 9c57f80709..5ce06aaea2 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LayerMask.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LayerMask.preset @@ -15,7 +15,7 @@ "PixelFormat": "R8G8B8X8" }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{B1AC2F76-CB1A-46A8-B92D-B8DFBB564FCF}", "Name": "LayerMask", "SourceColor": "Linear", @@ -37,7 +37,7 @@ ], "PixelFormat": "R8G8B8X8" }, - "osx_gl": { + "mac": { "UUID": "{B1AC2F76-CB1A-46A8-B92D-B8DFBB564FCF}", "Name": "LayerMask", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LensOptics.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LensOptics.preset index 84294dfbcc..9f4b5bf68d 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LensOptics.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LensOptics.preset @@ -9,7 +9,7 @@ "PixelFormat": "BC1" }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{3000A993-0A04-4E08-A813-DFB1A47A0980}", "Name": "LensOptics", "PixelFormat": "ETC2" @@ -19,7 +19,7 @@ "Name": "LensOptics", "PixelFormat": "ASTC_4x4" }, - "osx_gl": { + "mac": { "UUID": "{3000A993-0A04-4E08-A813-DFB1A47A0980}", "Name": "LensOptics", "PixelFormat": "BC1" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LightProjector.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LightProjector.preset index 8c98394d36..ede264a78e 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LightProjector.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LightProjector.preset @@ -14,7 +14,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{1DFEF41A-D97F-40FB-99D3-C142A3E5225E}", "Name": "LightProjector", "DestColor": "Linear", @@ -34,7 +34,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{1DFEF41A-D97F-40FB-99D3-C142A3E5225E}", "Name": "LightProjector", "DestColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LoadingScreen.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LoadingScreen.preset index f64c48eb95..ad0e2ddf06 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LoadingScreen.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LoadingScreen.preset @@ -9,7 +9,7 @@ "PixelFormat": "R8G8B8X8" }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{9ED87726-12AB-4BE0-9397-AD62AE56D9E2}", "Name": "LoadingScreen", "PixelFormat": "R8G8B8X8" @@ -19,7 +19,7 @@ "Name": "LoadingScreen", "PixelFormat": "R8G8B8X8" }, - "osx_gl": { + "mac": { "UUID": "{9ED87726-12AB-4BE0-9397-AD62AE56D9E2}", "Name": "LoadingScreen", "PixelFormat": "R8G8B8X8" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Minimap.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Minimap.preset index a402a2636c..9370de063d 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Minimap.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Minimap.preset @@ -15,7 +15,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{0D2F4C31-A665-4862-9C63-9E49A58E9A37}", "Name": "Minimap", "SuppressEngineReduce": true, @@ -37,7 +37,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{0D2F4C31-A665-4862-9C63-9E49A58E9A37}", "Name": "Minimap", "SuppressEngineReduce": true, diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/MuzzleFlash.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/MuzzleFlash.preset index f5ecc58d1a..459cd5b1fb 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/MuzzleFlash.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/MuzzleFlash.preset @@ -14,7 +14,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{8BCC23A5-D08E-458E-B0B3-087C65FA1D31}", "Name": "MuzzleFlash", "SuppressEngineReduce": true, @@ -34,7 +34,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{8BCC23A5-D08E-458E-B0B3-087C65FA1D31}", "Name": "MuzzleFlash", "SuppressEngineReduce": true, diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Normals.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Normals.preset index 104f3b4a39..04307eada4 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Normals.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Normals.preset @@ -27,7 +27,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{508B21D5-5250-4003-97EC-1CF28D571ACF}", "Name": "Normals", "SourceColor": "Linear", @@ -75,7 +75,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{508B21D5-5250-4003-97EC-1CF28D571ACF}", "Name": "Normals", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsFromDisplacement.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsFromDisplacement.preset index c513720b68..46e97c3443 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsFromDisplacement.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsFromDisplacement.preset @@ -19,7 +19,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{8AE5D8D7-ECF8-4B7D-91DE-8F787E3B4210}", "Name": "NormalsFromDisplacement", "SourceColor": "Linear", @@ -49,7 +49,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{8AE5D8D7-ECF8-4B7D-91DE-8F787E3B4210}", "Name": "NormalsFromDisplacement", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness.preset index e773f7d910..b8f6e38ac1 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness.preset @@ -25,7 +25,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{6EE749F4-846E-4F7A-878C-F211F85EA59F}", "Name": "NormalsWithSmoothness", "SourceColor": "Linear", @@ -67,7 +67,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{6EE749F4-846E-4F7A-878C-F211F85EA59F}", "Name": "NormalsWithSmoothness", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness_Legacy.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness_Legacy.preset index 4cf7af6f29..58bb02cd72 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness_Legacy.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness_Legacy.preset @@ -22,7 +22,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{A92541B8-2E70-4EF1-BA88-1DC1EA2A2341}", "Name": "NormalsWithSmoothness_Legacy", "SourceColor": "Linear", @@ -58,7 +58,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{A92541B8-2E70-4EF1-BA88-1DC1EA2A2341}", "Name": "NormalsWithSmoothness_Legacy", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Opacity.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Opacity.preset index 265379d053..bbd7fd5db9 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Opacity.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Opacity.preset @@ -27,7 +27,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{F3D5E572-A3CF-435A-A2AB-75D2B6907847}", "Name": "Opacity", "SourceColor": "Linear", @@ -73,7 +73,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{F3D5E572-A3CF-435A-A2AB-75D2B6907847}", "Name": "Opacity", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage.preset index 03744dee9e..e51848a116 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage.preset @@ -8,7 +8,7 @@ "Name": "ReferenceImage" }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{C659D222-F56B-4B61-A2F8-C1FA547F3C39}", "Name": "ReferenceImage" }, @@ -16,7 +16,7 @@ "UUID": "{C659D222-F56B-4B61-A2F8-C1FA547F3C39}", "Name": "ReferenceImage" }, - "osx_gl": { + "mac": { "UUID": "{C659D222-F56B-4B61-A2F8-C1FA547F3C39}", "Name": "ReferenceImage" }, diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage_HDRLinear.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage_HDRLinear.preset index 4d75e7ae1d..d9b9c17d07 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage_HDRLinear.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage_HDRLinear.preset @@ -13,7 +13,7 @@ "DiscardAlpha": true }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{46D9F30F-793C-4449-BCEF-12A396E61B2C}", "Name": "ReferenceImage_HDRLinear", "SourceColor": "Linear", @@ -31,7 +31,7 @@ "PixelFormat": "R9G9B9E5", "DiscardAlpha": true }, - "osx_gl": { + "mac": { "UUID": "{46D9F30F-793C-4449-BCEF-12A396E61B2C}", "Name": "ReferenceImage_HDRLinear", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage_HDRLinearUncompressed.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage_HDRLinearUncompressed.preset index 8344102425..8a5a83afa3 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage_HDRLinearUncompressed.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage_HDRLinearUncompressed.preset @@ -13,7 +13,7 @@ "DiscardAlpha": true }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{EEF24422-C8F0-4ECE-B32A-C70DB8129466}", "Name": "ReferenceImage_HDRLinearUncompressed", "SourceColor": "Linear", @@ -31,7 +31,7 @@ "PixelFormat": "R16G16B16A16F", "DiscardAlpha": true }, - "osx_gl": { + "mac": { "UUID": "{EEF24422-C8F0-4ECE-B32A-C70DB8129466}", "Name": "ReferenceImage_HDRLinearUncompressed", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage_Linear.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage_Linear.preset index 515e9b0512..bf72f21b06 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage_Linear.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReferenceImage_Linear.preset @@ -11,7 +11,7 @@ "SuppressEngineReduce": true }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{02C3D9F5-3637-49BA-A48A-D68D629A4D14}", "Name": "ReferenceImage_Linear", "SourceColor": "Linear", @@ -25,7 +25,7 @@ "DestColor": "Linear", "SuppressEngineReduce": true }, - "osx_gl": { + "mac": { "UUID": "{02C3D9F5-3637-49BA-A48A-D68D629A4D14}", "Name": "ReferenceImage_Linear", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance.preset index 58e283add7..1844e0186e 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance.preset @@ -34,7 +34,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}", "Name": "Reflectance", "SourceColor": "Linear", @@ -92,7 +92,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}", "Name": "Reflectance", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReflectanceWithSmoothness_Legacy.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReflectanceWithSmoothness_Legacy.preset index e386d08a35..e51cc7122b 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReflectanceWithSmoothness_Legacy.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReflectanceWithSmoothness_Legacy.preset @@ -16,7 +16,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{851128B5-7454-42C4-83CE-FCFE071834C5}", "Name": "ReflectanceWithSmoothness_Legacy", "FileMasks": [ @@ -40,7 +40,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{851128B5-7454-42C4-83CE-FCFE071834C5}", "Name": "ReflectanceWithSmoothness_Legacy", "FileMasks": [ diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance_Linear.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance_Linear.preset index 767b0b67eb..07cc39c955 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance_Linear.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance_Linear.preset @@ -18,7 +18,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{9B2114F5-118A-4B3A-9CFE-97FA01EC8CFE}", "Name": "Reflectance_Linear", "DestColor": "Linear", @@ -46,7 +46,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{9B2114F5-118A-4B3A-9CFE-97FA01EC8CFE}", "Name": "Reflectance_Linear", "DestColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Font.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Font.preset index b2bbf905db..f76741148c 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Font.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Font.preset @@ -12,7 +12,7 @@ "IsPowerOf2": true }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{F34E3711-5F34-4DBC-8F5D-6340D3989F4B}", "Name": "SF_Font", "SourceColor": "Linear", @@ -28,7 +28,7 @@ "SuppressEngineReduce": true, "IsPowerOf2": true }, - "osx_gl": { + "mac": { "UUID": "{F34E3711-5F34-4DBC-8F5D-6340D3989F4B}", "Name": "SF_Font", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Gradient.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Gradient.preset index 41ba10f55c..aff25dc83d 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Gradient.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Gradient.preset @@ -12,7 +12,7 @@ "IsPowerOf2": true }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{E7F9DF56-DCB0-4683-96EE-F04DA547BE24}", "Name": "SF_Gradient", "SourceColor": "Linear", @@ -28,7 +28,7 @@ "SuppressEngineReduce": true, "IsPowerOf2": true }, - "osx_gl": { + "mac": { "UUID": "{E7F9DF56-DCB0-4683-96EE-F04DA547BE24}", "Name": "SF_Gradient", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image.preset index e36e42860d..46a32ce5d4 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image.preset @@ -13,7 +13,7 @@ "IsPowerOf2": true }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{189A42CB-AEE3-4B80-B276-0FDB0ECA140C}", "Name": "SF_Image", "SourceColor": "Linear", @@ -31,7 +31,7 @@ "PixelFormat": "PVRTC4", "IsPowerOf2": true }, - "osx_gl": { + "mac": { "UUID": "{189A42CB-AEE3-4B80-B276-0FDB0ECA140C}", "Name": "SF_Image", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image_nonpower2.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image_nonpower2.preset index fa2fe2ae72..0ba70d2ca3 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image_nonpower2.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image_nonpower2.preset @@ -12,7 +12,7 @@ "PixelFormat": "BC1" }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{C456B8AB-C360-4822-BCDD-225252D0E697}", "Name": "SF_Image_nonpower2", "SourceColor": "Linear", @@ -28,7 +28,7 @@ "SuppressEngineReduce": true, "PixelFormat": "PVRTC4" }, - "osx_gl": { + "mac": { "UUID": "{C456B8AB-C360-4822-BCDD-225252D0E697}", "Name": "SF_Image_nonpower2", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Skybox.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Skybox.preset index 9102bd53bb..4f71855ecf 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Skybox.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Skybox.preset @@ -21,7 +21,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{F359CD3B-37E6-4627-B4F6-2DFC2C0E3C1C}", "Name": "Skybox", "FileMasks": [ @@ -55,7 +55,7 @@ "RequiresConvolve": false } }, - "osx_gl": { + "mac": { "UUID": "{F359CD3B-37E6-4627-B4F6-2DFC2C0E3C1C}", "Name": "Skybox", "FileMasks": [ diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo.preset index 19881f93d7..84a70935f1 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo.preset @@ -16,7 +16,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{88D07159-2FC0-4CBE-82CC-A9DC258C9351}", "Name": "Terrain_Albedo", "SourceColor": "Linear", @@ -40,7 +40,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{88D07159-2FC0-4CBE-82CC-A9DC258C9351}", "Name": "Terrain_Albedo", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo_HighPassed.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo_HighPassed.preset index 2fcbb012d4..1d83737ef9 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo_HighPassed.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo_HighPassed.preset @@ -15,7 +15,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{7827AA52-0A7B-43E7-8CD4-55E0BC513AF1}", "Name": "Terrain_Albedo_HighPassed", "SourceColor": "Linear", @@ -37,7 +37,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{7827AA52-0A7B-43E7-8CD4-55E0BC513AF1}", "Name": "Terrain_Albedo_HighPassed", "SourceColor": "Linear", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Uncompressed.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Uncompressed.preset index d0dbbcba6f..6e28cafe11 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Uncompressed.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Uncompressed.preset @@ -13,7 +13,7 @@ } }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{E996A696-991C-4FFC-B270-F5AD408B0618}", "Name": "Uncompressed", "PixelFormat": "R8G8B8X8", @@ -31,7 +31,7 @@ "MipGenType": "Box" } }, - "osx_gl": { + "mac": { "UUID": "{E996A696-991C-4FFC-B270-F5AD408B0618}", "Name": "Uncompressed", "PixelFormat": "R8G8B8X8", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Compressed.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Compressed.preset index 01595a3425..6f70e8f14f 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Compressed.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Compressed.preset @@ -13,7 +13,7 @@ "FileMasks": [ "_ui" ] }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{2828FBFE-BDF9-45A7-9370-F93822719CCF}", "Name": "UserInterface_Compressed", "SuppressEngineReduce": true, @@ -25,7 +25,7 @@ "SuppressEngineReduce": true, "PixelFormat": "ASTC_6x6" }, - "osx_gl": { + "mac": { "UUID": "{2828FBFE-BDF9-45A7-9370-F93822719CCF}", "Name": "UserInterface_Compressed", "SuppressEngineReduce": true, diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Lossless.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Lossless.preset index 78c63790ab..39066b242b 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Lossless.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Lossless.preset @@ -13,7 +13,7 @@ "FileMasks": [ "_ui" ] }, "PlatformsPresets": { - "es3": { + "android": { "UUID": "{83003128-F63E-422B-AEC2-68F0A947225F}", "Name": "UserInterface_Lossless", "SuppressEngineReduce": true, @@ -25,7 +25,7 @@ "SuppressEngineReduce": true, "PixelFormat": "R8G8B8A8" }, - "osx_gl": { + "mac": { "UUID": "{83003128-F63E-422B-AEC2-68F0A947225F}", "Name": "UserInterface_Lossless", "SuppressEngineReduce": true, diff --git a/Gems/Atom/Asset/Shader/Code/CMakeLists.txt b/Gems/Atom/Asset/Shader/Code/CMakeLists.txt index a06aa79d24..dd8afec534 100644 --- a/Gems/Atom/Asset/Shader/Code/CMakeLists.txt +++ b/Gems/Atom/Asset/Shader/Code/CMakeLists.txt @@ -101,3 +101,36 @@ ly_add_target( 3rdParty::SPIRVCross 3rdParty::azslc ) + +################################################################################ +# Tests +################################################################################ +if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) + + ly_add_target( + NAME Atom_Asset_Shader.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} + NAMESPACE Gem + FILES_CMAKE + atom_asset_shader_builders_tests_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + . + Source/Editor + Tests + BUILD_DEPENDENCIES + PRIVATE + AZ::AtomCore + AZ::AzTest + AZ::AzFramework + AZ::AzToolsFramework + Legacy::CryCommon + Gem::Atom_RPI.Public + Gem::Atom_RHI.Public + Gem::Atom_RPI.Edit + Gem::Atom_Asset_Shader.Static + ) + ly_add_googletest( + NAME Gem::Atom_Asset_Shader.Tests + ) + +endif() diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp index 1e471f8644..14193d774f 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/Preprocessor.cpp @@ -60,33 +60,31 @@ namespace AZ void PreprocessorOptions::RemovePredefinedMacros(const AZStd::vector& macroNames) { + for (const auto& macroName : macroNames) + { m_predefinedMacros.erase( AZStd::remove_if( m_predefinedMacros.begin(), m_predefinedMacros.end(), - [&](const AZStd::string& predefinedMacro) - { - for (const auto& macroName : macroNames) + [&](const AZStd::string& predefinedMacro) { + // Haystack, needle, bCaseSensitive + if (!AzFramework::StringFunc::StartsWith(predefinedMacro, macroName, true)) { - // Haystack, needle, bCaseSensitive - if (!AzFramework::StringFunc::StartsWith(predefinedMacro, macroName, true)) - { - return false; - } - // If found, let's make sure it is not just a substring. - if (predefinedMacro.size() == macroName.size()) - { - return true; - } - // The predefinedMacro can be a string like "macro=value". If we find '=' it is a match. - if (predefinedMacro.c_str()[macroName.size()] == '=') - { - return true; - } return false; } + // If found, let's make sure it is not just a substring. + if (predefinedMacro.size() == macroName.size()) + { + return true; + } + // The predefinedMacro can be a string like "macro=value". If we find '=' it is a match. + if (predefinedMacro.c_str()[macroName.size()] == '=') + { + return true; + } return false; }), m_predefinedMacros.end()); + } } //! Binder helper to Matsui C-Pre-Processor library diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder2.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder2.cpp index 1668b57866..5758db1da2 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder2.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder2.cpp @@ -344,8 +344,7 @@ namespace AZ AZStd::string prependedAzslFilePath = RHI::PrependFile(args); if (prependedAzslFilePath == azslFullPath) { - // For some reason the combined azsl file was not created in the temporary - // directory assigned to this job. + // The specific error is already reported by RHI::PrependFile(). response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed; return; } diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp index 89ca76bd01..0db53456e0 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp @@ -736,13 +736,13 @@ namespace AZ { platformId = AzFramework::PlatformId::PC; } - else if (platformIdentifier == "osx_gl") + else if (platformIdentifier == "mac") { - platformId = AzFramework::PlatformId::OSX; + platformId = AzFramework::PlatformId::MAC; } - else if (platformIdentifier == "es3") + else if (platformIdentifier == "android") { - platformId = AzFramework::PlatformId::ES3; + platformId = AzFramework::PlatformId::ANDROID_ID; } else if (platformIdentifier == "ios") { @@ -788,13 +788,13 @@ namespace AZ { platformId = AzFramework::PlatformId::PC; } - else if (platform == "osx_gl") + else if (platform == "mac") { - platformId = AzFramework::PlatformId::OSX; + platformId = AzFramework::PlatformId::MAC; } - else if (platform == "es3") + else if (platform == "android") { - platformId = AzFramework::PlatformId::ES3; + platformId = AzFramework::PlatformId::ANDROID_ID; } else if (platform == "ios") { diff --git a/Gems/Atom/Asset/Shader/Code/Tests/Common/ShaderBuilderTestFixture.cpp b/Gems/Atom/Asset/Shader/Code/Tests/Common/ShaderBuilderTestFixture.cpp new file mode 100644 index 0000000000..276c225e05 --- /dev/null +++ b/Gems/Atom/Asset/Shader/Code/Tests/Common/ShaderBuilderTestFixture.cpp @@ -0,0 +1,41 @@ +/* +* 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 "ShaderBuilderTestFixture.h" + +#include +#include + +namespace UnitTest +{ + void ShaderBuilderTestFixture::SetUp() + { + AllocatorsTestFixture::SetUp(); + + AZ::AllocatorInstance::Create(); + AZ::AllocatorInstance::Create(); + + AZ::NameDictionary::Create(); + } + + void ShaderBuilderTestFixture::TearDown() + { + AZ::NameDictionary::Destroy(); + + AZ::AllocatorInstance::Destroy(); + AZ::AllocatorInstance::Destroy(); + + AllocatorsTestFixture::TearDown(); + } + +} + diff --git a/Gems/Atom/Asset/Shader/Code/Tests/Common/ShaderBuilderTestFixture.h b/Gems/Atom/Asset/Shader/Code/Tests/Common/ShaderBuilderTestFixture.h new file mode 100644 index 0000000000..450cc6bde5 --- /dev/null +++ b/Gems/Atom/Asset/Shader/Code/Tests/Common/ShaderBuilderTestFixture.h @@ -0,0 +1,34 @@ +/* +* 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 UnitTest +{ + /** + * Unit test fixture for setting up memory allocation pools and the AZ::Name dictionary. + * In the future will be extended as needed. + */ + class ShaderBuilderTestFixture + : public AllocatorsTestFixture + { + protected: + /////////////////////////////////////////////////////////////////////// + // AllocatorsTestFixture overrides + void SetUp() override; + void TearDown() override; + /////////////////////////////////////////////////////////////////////// + }; +} // namespace UnitTest + diff --git a/Gems/Atom/Asset/Shader/Code/Tests/SupervariantCmdArgumentTests.cpp b/Gems/Atom/Asset/Shader/Code/Tests/SupervariantCmdArgumentTests.cpp new file mode 100644 index 0000000000..2e5ee3fc09 --- /dev/null +++ b/Gems/Atom/Asset/Shader/Code/Tests/SupervariantCmdArgumentTests.cpp @@ -0,0 +1,523 @@ +/* +* 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 "Common/ShaderBuilderTestFixture.h" + +namespace UnitTest +{ + using namespace AZ; + + struct KeyValueView + { + AZStd::string_view m_key; + AZStd::string_view m_value; + }; + + class SupervariantCmdArgumentTests : public ShaderBuilderTestFixture + { + protected: + static constexpr char MCPP_MACRO1[] = "MACRO1"; + static constexpr char MCPP_VALUE1[] = "VALUE1a"; + static constexpr char MCPP_NEW_VALUE1[] = "VALUE1b"; // Missing A is not a typo + + static constexpr char MCPP_MACRO2[] = "MACRO2"; + static constexpr char MCPP_VALUE2[] = "VALUE2"; + + static constexpr char MCPP_MACRO3[] = "MACRO3"; + static constexpr char MCPP_VALUE3[] = "VALUE3a"; + static constexpr char MCPP_NEW_VALUE3[] = "VALUE3b"; + + static constexpr char MCPP_MACRO4[] = "MACRO4"; + + static constexpr char MCPP_MACRO5[] = "MACRO5"; + + static constexpr char MCPP_MACRO6[] = "MACRO6"; + static constexpr char MCPP_VALUE6[] = "VALUE6"; + + static constexpr char AZSLC_ARG1[] = "--azsl1"; + + static constexpr char AZSLC_ARG2[] = "--azsl2"; + static constexpr char AZSLC_VAL2[] = "open,source"; + static constexpr char AZSLC_NEW_VAL2a[] = "closed,binary"; + static constexpr char AZSLC_NEW_VAL2b[] = "closed,source"; + + static constexpr char AZSLC_ARG3[] = "--azsl3"; + static constexpr char AZSLC_VAL3[] = "blue"; + + static constexpr char AZSLC_ARG4[] = "-azsl4"; + + static constexpr char AZSLC_ARG5[] = "--azsl5"; + static constexpr char AZSLC_VAL5[] = "smith,wick,john,45,-1,-1"; + static constexpr char AZSLC_NEW_VAL5[] = "apple,seed,crisp,-1,2,0"; + + static constexpr char AZSLC_ARG6[] = "--azsl6"; + + static constexpr char AZSLC_ARG7[] = "--azsl7"; + + //! Helper function. + //! Given an input list of {Key, Value} pairs returns a list of strings where each string is of the form: "Key=Value". + AZStd::vector CreateListOfStringsFromListOfKeyValues(AZStd::array_view listOfKeyValues) const + { + AZStd::vector listOfStrings; + for (const auto& keyValue : listOfKeyValues) + { + if (keyValue.m_value.empty()) + { + listOfStrings.push_back(keyValue.m_key); + } + else + { + listOfStrings.push_back(AZStd::string::format("%s=%s", keyValue.m_key.data(), keyValue.m_value.data())); + } + } + return listOfStrings; + } + + //! Helper function. + //! Given an input list of {Key, Value} pairs returns a list of strings where each string is of the form: "Key1", "Value1", "Key2", "Value2". + AZStd::vector CreateListOfSingleStringsFromListOfKeyValues(AZStd::array_view listOfKeyValues) const + { + AZStd::vector listOfStrings; + for (const auto& keyValue : listOfKeyValues) + { + listOfStrings.push_back(keyValue.m_key); + if (!keyValue.m_value.empty()) + { + listOfStrings.push_back(keyValue.m_value); + } + } + return listOfStrings; + } + + //! Helper function. + //! @param outputString: [out] The string " @argName" gets appended to it (The space is intentional). + //! Alternatively, if @argValue is NOT empty, then the string " @argName=@argValue" is + //! appended to it. + //! @param argName: A typical command line argument. "-p" or "--some". + //! @param argValue: A string representing the value that should be appended to @argName. + void AppendCmdLineArgument(AZStd::string& outputString, AZStd::string_view argName, AZStd::string_view argValue) const + { + if (argValue.empty()) + { + outputString += AZStd::string::format(" %s", argName.data()); + } + else + { + outputString += AZStd::string::format(" %s=%s", argName.data(), argValue.data()); + } + } + + //! Helper function. + //! Similar to above, but assumes that @argName refers to just the name of a macro definition so the appended string will always start + //! with "-D". + void AppendMacroDefinitionArgument(AZStd::string& outputString, AZStd::string_view argName, AZStd::string_view argValue) const + { + AppendCmdLineArgument(outputString, AZStd::string::format("-D%s", argName.data()), argValue); + } + + //! A helper made of helpers. + //! Returns a command line string that results of concatenating the input list of {Key, Value} pairs (with '='). + //! Example of a returned string: + //! "key1=value1 key2 key3 key4=value" + AZStd::string CreateCmdLineStringFromListOfKeyValues(AZStd::array_view listOfKeyValues) const + { + AZStd::string cmdLineString; + for (const auto& keyValueView : listOfKeyValues) + { + AppendCmdLineArgument(cmdLineString, keyValueView.m_key, keyValueView.m_value); + } + return cmdLineString; + } + + //! A helper made of helpers. + //! Returns a command line string of macro definitions that results of concatenating the input list of {Key, Value} pairs. + //! Example of a returned string: + //! "-Dkey1=value1 -Dkey2 -Dkey3 -Dkey4=value" + AZStd::string CreateMacroDefinitionCmdLineStringFromListOfKeyValues(AZStd::array_view listOfKeyValues) const + { + AZStd::string cmdLineString; + for (const auto& keyValueView : listOfKeyValues) + { + AppendMacroDefinitionArgument(cmdLineString, keyValueView.m_key, keyValueView.m_value); + } + return cmdLineString; + } + + //! @param includePaths A List of folder paths + //! @param predefinedMacros A List of strings with format: "name[=value]" + ShaderBuilder::PreprocessorOptions CreatePreprocessorOptions( + AZStd::array_view includePaths, AZStd::array_view predefinedMacros) const + { + ShaderBuilder::PreprocessorOptions preprocessorOptions; + + preprocessorOptions.m_projectIncludePaths.reserve(includePaths.size()); + for (const auto& path : includePaths) + { + preprocessorOptions.m_projectIncludePaths.push_back(path); + } + + preprocessorOptions.m_predefinedMacros.reserve(predefinedMacros.size()); + for (const auto& macro : predefinedMacros) + { + preprocessorOptions.m_predefinedMacros.push_back(macro); + } + + return preprocessorOptions; + } + + //! @param azslcAdditionalFreeArguments: A string representing series of command line arguments for AZSLc. + //! @param dxcAdditionalFreeArguments: A string representing series of command line arguments for DXC. + RHI::ShaderCompilerArguments CreateShaderCompilerArguments( + AZStd::string_view azslcAdditionalFreeArguments, AZStd::string_view dxcAdditionalFreeArguments) const + { + RHI::ShaderCompilerArguments shaderCompilerArguments; + shaderCompilerArguments.m_azslcWarningLevel = 1; + shaderCompilerArguments.m_azslcAdditionalFreeArguments = azslcAdditionalFreeArguments; + shaderCompilerArguments.m_defaultMatrixOrder = RHI::MatrixOrder::Row; + shaderCompilerArguments.m_dxcAdditionalFreeArguments = dxcAdditionalFreeArguments; + + return shaderCompilerArguments; + } + + + //! @param includePaths A List of folder paths + //! @param predefinedMacros A List of strings with format: "name[=value]" + //! @param azslcAdditionalFreeArguments A string representing series of command line arguments for AZSLc. + //! @param dxcAdditionalFreeArguments: A string representing series of command line arguments for DXC. + ShaderBuilder::GlobalBuildOptions CreateGlobalBuildOptions( + AZStd::array_view includePaths, + AZStd::array_view predefinedMacros, + AZStd::string_view azslcAdditionalFreeArguments, + AZStd::string_view dxcAdditionalFreeArguments) const + { + ShaderBuilder::GlobalBuildOptions globalBuildOptions; + globalBuildOptions.m_preprocessorSettings = CreatePreprocessorOptions(includePaths, predefinedMacros); + globalBuildOptions.m_compilerArguments = + CreateShaderCompilerArguments(azslcAdditionalFreeArguments, dxcAdditionalFreeArguments); + return globalBuildOptions; + } + + //! @param name Name of the supervariant. + //! @param plusArguments A string with command line arguments that contains both C-preprocessor macro definitions + //! and other command line arguments for AZSLc. + //! @param minusArguments A string with command line arguments that should be removed from the finalized command line arguments. + //! it can contain both, C-preprocessor macro definitions and other command line arguments for AZSLc. + RPI::ShaderSourceData::SupervariantInfo CreateSupervariantInfo( + AZStd::string_view name, AZStd::string_view plusArguments, AZStd::string_view minusArguments) const + { + RPI::ShaderSourceData::SupervariantInfo supervariantInfo; + supervariantInfo.m_name = name; + supervariantInfo.m_plusArguments = plusArguments; + supervariantInfo.m_minusArguments = minusArguments; + return supervariantInfo; + } + + bool StringContainsAllSubstrings(AZStd::string_view haystack, AZStd::array_view substrings) + { + return AZStd::all_of(AZ_BEGIN_END(substrings), + [&](AZStd::string_view needle) -> bool + { + return (haystack.find(needle) != AZStd::string::npos); + } + ); + } + + bool StringDoesNotContainAnyOneOfTheSubstrings(AZStd::string_view haystack, AZStd::array_view substrings) + { + return AZStd::all_of(AZ_BEGIN_END(substrings), [&](AZStd::string_view needle) -> bool { + return (haystack.find(needle) == AZStd::string::npos); + }); + } + + //! @returns: True if all strings in @substring appear in @vectorOfString. + //! @remark: Keep in mind that this is not the same as saying that all strings in @vectorOfStrings appear in @substrings. + bool VectorContainsAllSubstrings( + AZStd::array_view vectorOfStrings, AZStd::array_view substrings) + { + return AZStd::all_of( + AZ_BEGIN_END(substrings), + [&](AZStd::string_view needle) -> bool { + bool res = AZStd::any_of(AZ_BEGIN_END(vectorOfStrings), + [&](AZStd::string_view haystack) -> bool + { + return haystack.find(needle) != AZStd::string::npos; + } + ); + return res; + } + ); + } + + //! @returns: True only if None of the strings in @vectorOfStrings contains any of the strings in @substrings. + bool VectorDoesNotContainAnyOneOfTheSubstrings(AZStd::array_view vectorOfStrings, AZStd::array_view substrings) + { + return AZStd::all_of(AZ_BEGIN_END(vectorOfStrings), [&](AZStd::string_view haystack) -> bool { + return StringDoesNotContainAnyOneOfTheSubstrings(haystack, substrings); + }); + } + + }; // class SupervariantCmdArgumentTests + + + TEST_F(SupervariantCmdArgumentTests, CommandLineArgumentUtils_ValidateHelperFunctions) + { + // In this test the idea is to validate the static helper functions in AZ::RHI::ShaderCompilerArguments class + // that are useful for command line argument manipulation, etc. + AZStd::vector argumentList = { + {AZSLC_ARG1, ""}, {AZSLC_ARG2, AZSLC_VAL2}, {AZSLC_ARG3, AZSLC_VAL3}, {AZSLC_ARG4, ""}, {AZSLC_ARG5, AZSLC_VAL5}, + }; + + auto argumentsAsString = CreateCmdLineStringFromListOfKeyValues(argumentList); + auto listOfArgumentNames = AZ::RHI::CommandLineArgumentUtils::GetListOfArgumentNames(argumentsAsString); + + EXPECT_TRUE(AZStd::all_of(AZ_BEGIN_END(argumentList), [&](const KeyValueView& needle) -> bool { + return (AZStd::find(AZ_BEGIN_END(listOfArgumentNames), needle.m_key) != listOfArgumentNames.end()) && + // Make sure the values did not make into the expected list of keys. + (AZStd::find(AZ_BEGIN_END(listOfArgumentNames), needle.m_value) == listOfArgumentNames.end()); + })); + + AZStd::vector listOfArgumentsToRemove = { AZSLC_ARG4, AZSLC_ARG2 }; + auto stringWithRemovedArguments = + AZ::RHI::CommandLineArgumentUtils::RemoveArgumentsFromCommandLineString(listOfArgumentsToRemove, argumentsAsString); + EXPECT_TRUE(AZStd::all_of(AZ_BEGIN_END(listOfArgumentsToRemove), [&](const AZStd::string& needle) -> bool { + return stringWithRemovedArguments.find(needle) == AZStd::string::npos; + })); + + AZStd::vector listOfSurvivingArguments = {AZSLC_ARG1, AZSLC_ARG3, AZSLC_ARG5}; + EXPECT_TRUE(AZStd::all_of(AZ_BEGIN_END(listOfSurvivingArguments), [&](const AZStd::string& needle) -> bool { + return stringWithRemovedArguments.find(needle) != AZStd::string::npos; + })); + + auto stringWithoutExtraSpaces = + AZ::RHI::CommandLineArgumentUtils::RemoveExtraSpaces(" --arg1 -arg2 --arg3=foo --arg4=bar "); + EXPECT_EQ(stringWithoutExtraSpaces, AZStd::string("--arg1 -arg2 --arg3=foo --arg4=bar")); + + auto stringAsMergedArguments = + AZ::RHI::CommandLineArgumentUtils::MergeCommandLineArguments("--arg1 -arg2 --arg3=foo", "--arg3=bar --arg4"); + EXPECT_EQ(stringAsMergedArguments, AZStd::string("--arg1 -arg2 --arg3=bar --arg4")); + + EXPECT_TRUE(AZ::RHI::CommandLineArgumentUtils::HasMacroDefinitions("-DMACRO")); + EXPECT_TRUE(AZ::RHI::CommandLineArgumentUtils::HasMacroDefinitions("-D MACRO")); + EXPECT_TRUE(AZ::RHI::CommandLineArgumentUtils::HasMacroDefinitions("--help -D MACRO")); + EXPECT_TRUE(AZ::RHI::CommandLineArgumentUtils::HasMacroDefinitions("--help -p -DMACRO --more")); + EXPECT_TRUE(AZ::RHI::CommandLineArgumentUtils::HasMacroDefinitions("--help -p -D MACRO=VALUE --more")); + EXPECT_FALSE(AZ::RHI::CommandLineArgumentUtils::HasMacroDefinitions("--help -p --more")); + EXPECT_FALSE(AZ::RHI::CommandLineArgumentUtils::HasMacroDefinitions("--help -p --more --DFAKE")); + EXPECT_FALSE(AZ::RHI::CommandLineArgumentUtils::HasMacroDefinitions("--DFAKE1 --help -p --more --D FAKE2")); + } + + TEST_F(SupervariantCmdArgumentTests, ShaderCompilerArguments_ValidateCommandLineArgumentsMerge) + { + // In this test we validate that AZ::RHI::ShaderCompilerArguments::Merge() works as expected + // by merging AZSLC & DXC arguments giving higher priority to the arguments in the "right". + + auto shaderCompilerArgumentsLeft = CreateShaderCompilerArguments( + "--azsl1 --azsl2=avalue2a -azsl3 --azsl4=avalue4a", + "--dxc1=dvalue1a -dxc2 --dxc3=dvalue3a --dxc4"); + auto shaderCompilerArgumentsRight = CreateShaderCompilerArguments( + "--azsl1 --azsl2=avalue2b -azsl3 --azsl4=avalue4a --azsl5", + "--dxc1=dvalue1a -dxc2 --dxc3=dvalue3b --dxc4 --dxc5=dvalue5a"); + + shaderCompilerArgumentsLeft.Merge(shaderCompilerArgumentsRight); + EXPECT_EQ(shaderCompilerArgumentsLeft.m_azslcAdditionalFreeArguments, "--azsl1 --azsl2=avalue2b -azsl3 --azsl4=avalue4a --azsl5"); + EXPECT_EQ(shaderCompilerArgumentsLeft.m_dxcAdditionalFreeArguments, "--dxc1=dvalue1a -dxc2 --dxc3=dvalue3b --dxc4 --dxc5=dvalue5a"); + } + + + TEST_F(SupervariantCmdArgumentTests, SupervariantInfo_ValidateMemberFunctions) + { + // In this test all member functions of the ShaderSourceData::SupervariantInfo class + // are validated. + + AZStd::vector mcppMacrosList = { + {MCPP_MACRO1, MCPP_VALUE1}, + {MCPP_MACRO2, MCPP_VALUE2}, + {MCPP_MACRO3, MCPP_VALUE3}, + {MCPP_MACRO4, ""}, + }; + + AZStd::string argumentsToAddOrReplace; + AppendMacroDefinitionArgument(argumentsToAddOrReplace, MCPP_MACRO3, MCPP_NEW_VALUE3); + AppendCmdLineArgument(argumentsToAddOrReplace, AZSLC_ARG2, AZSLC_NEW_VAL2a); + AppendMacroDefinitionArgument(argumentsToAddOrReplace, MCPP_MACRO1, MCPP_NEW_VALUE1); + AppendCmdLineArgument(argumentsToAddOrReplace, AZSLC_ARG5, AZSLC_NEW_VAL5); + AppendMacroDefinitionArgument(argumentsToAddOrReplace, MCPP_MACRO5, ""); + AppendCmdLineArgument(argumentsToAddOrReplace, AZSLC_ARG6, ""); + + AZStd::string argumentsToRemove; + AppendCmdLineArgument(argumentsToRemove, AZSLC_ARG3, ""); + AppendMacroDefinitionArgument(argumentsToRemove, MCPP_MACRO2, ""); + AppendCmdLineArgument(argumentsToRemove, AZSLC_ARG4, ""); + AppendMacroDefinitionArgument(argumentsToRemove, MCPP_MACRO4, ""); + + auto supervariantInfo = CreateSupervariantInfo("Dummy", argumentsToAddOrReplace, argumentsToRemove); + + auto macroListToRemove = supervariantInfo.GetCombinedListOfMacroDefinitionNamesToRemove(); + AZStd::vector macroNamesToRemoveThatMustBePresent = { MCPP_MACRO1, MCPP_MACRO2, MCPP_MACRO3, MCPP_MACRO4, MCPP_MACRO5 }; + EXPECT_EQ(macroListToRemove.size(), macroNamesToRemoveThatMustBePresent.size()); + EXPECT_TRUE( + VectorContainsAllSubstrings(macroListToRemove, macroNamesToRemoveThatMustBePresent) + ); + + auto macroListToAdd = supervariantInfo.GetMacroDefinitionsToAdd(); + AZStd::vector macroNamesToAddThatMustBePresent = {MCPP_MACRO1, MCPP_MACRO3, MCPP_MACRO5}; + EXPECT_EQ(macroListToAdd.size(), macroNamesToAddThatMustBePresent.size()); + EXPECT_TRUE(VectorContainsAllSubstrings(macroListToAdd, macroNamesToAddThatMustBePresent)); + + // The result of GetCustomizedArgumentsForAzslc() is the most important value to test + AZStd::vector freeAzslcArgumentList = { + {AZSLC_ARG1, ""}, {AZSLC_ARG2, AZSLC_VAL2}, {AZSLC_ARG3, AZSLC_VAL3}, {AZSLC_ARG4, ""}, {AZSLC_ARG5, AZSLC_VAL5}, + }; + AZStd::string azslcArgs = CreateCmdLineStringFromListOfKeyValues(freeAzslcArgumentList); + AZStd::string customizedAzslcArgs = supervariantInfo.GetCustomizedArgumentsForAzslc(azslcArgs); + + AZStd::vector stringsThatMustBePresent = { + AZSLC_ARG1, AZSLC_ARG2, AZSLC_NEW_VAL2a, AZSLC_ARG5, AZSLC_NEW_VAL5, AZSLC_ARG6}; + EXPECT_TRUE(StringContainsAllSubstrings(customizedAzslcArgs, stringsThatMustBePresent)); + + AZStd::vector stringsThatCanNotBePresent = { AZSLC_ARG3, AZSLC_VAL3, AZSLC_ARG4, + // Because GetCustomizedArgumentsForAzslc() only returns arguments for AZSLc, none of the macro related + // arguments can be present + MCPP_MACRO1, MCPP_VALUE1, MCPP_NEW_VALUE1, + MCPP_MACRO2, MCPP_VALUE2, + MCPP_MACRO3, MCPP_VALUE3, MCPP_NEW_VALUE3, + MCPP_MACRO4, + MCPP_MACRO5 + }; + + EXPECT_TRUE( + StringDoesNotContainAnyOneOfTheSubstrings(customizedAzslcArgs, stringsThatCanNotBePresent) + ); + } + + + TEST_F(SupervariantCmdArgumentTests, ShaderAssetBuilder_ValidateInfluenceOfSupervariantInfoOnGlobalBuildOptions) + { + // In this test we validate how the ShaderAssetBuilder configure the commmand line arguments it passes + // to MCPP, AZSLc & DXC. It basically starts with a GlobalBuildOptions, that gets further customized by + // the ShaderCompilerArguments from ShaderSourceData(.shader file) and later further customized + // by each SupervariantInfo in ShaderSourceData. + + // The first step is to define the initial values of the GlobalBuildOptions. + AZStd::vector globalMcppMacrosList = { + {MCPP_MACRO1, MCPP_VALUE1}, + {MCPP_MACRO2, MCPP_VALUE2}, + {MCPP_MACRO3, MCPP_VALUE3}, + {MCPP_MACRO4, ""}, + }; + + AZStd::vector globalAzslArguments = { + {AZSLC_ARG1, ""}, + {AZSLC_ARG2, AZSLC_VAL2}, + {AZSLC_ARG3, AZSLC_VAL3}, + {AZSLC_ARG4, ""}, + {AZSLC_ARG5, AZSLC_VAL5}, + }; + + auto globalBuildOptions = CreateGlobalBuildOptions( + AZStd::vector(), CreateListOfStringsFromListOfKeyValues(globalMcppMacrosList), + CreateCmdLineStringFromListOfKeyValues(globalAzslArguments), + "" /* Don't care about DXC in this test */); + + // The second step is to load the Shader Compiler Arguments from the .shader file. + // These arguments will be merged in @globalBuildOptions, but the .shader arguments have + // higher priority. + AZStd::vector shaderAzslArguments = { + {AZSLC_ARG2, AZSLC_NEW_VAL2a}, + {AZSLC_ARG6, ""}, + }; + auto shaderCompilerArguments = CreateShaderCompilerArguments( + CreateCmdLineStringFromListOfKeyValues(shaderAzslArguments), "" /* Don't care about DXC in this test */); + globalBuildOptions.m_compilerArguments.Merge(shaderCompilerArguments); + + // Let's create the dummy supervariant. It will have some MCPP & AZSLc arguments to be added/replaced AND other MCPP & AZSLc arguments to be removed. + AZStd::vector supervariantAzslArgumentsToAdd = { + {AZSLC_ARG2, AZSLC_NEW_VAL2b}, + {AZSLC_ARG7, ""}, + }; + AZStd::vector supervariantMacroDefinitionsToAdd = { + {MCPP_MACRO1, MCPP_NEW_VALUE1}, + {MCPP_MACRO3, MCPP_NEW_VALUE3}, + {MCPP_MACRO5, ""}, + }; + auto supervariantArgumentsToAdd = CreateCmdLineStringFromListOfKeyValues(supervariantAzslArgumentsToAdd) + + CreateMacroDefinitionCmdLineStringFromListOfKeyValues(supervariantMacroDefinitionsToAdd); + + AZStd::vector supervariantAzslArgumentsToRemove = { + {AZSLC_ARG4, ""}, + {AZSLC_ARG1, ""}, + }; + AZStd::vector supervariantMacrosToRemove = { + {MCPP_MACRO2, ""}, + {MCPP_MACRO4, ""}, + }; + auto supervariantArgumentsToRemove = CreateCmdLineStringFromListOfKeyValues(supervariantAzslArgumentsToRemove) + + CreateMacroDefinitionCmdLineStringFromListOfKeyValues(supervariantMacrosToRemove); + + //CreateMacroDefinitionCmdLineStringFromListOfKeyValues + auto supervariantInfo = CreateSupervariantInfo("Dummy", + supervariantArgumentsToAdd, // These arguments will be added or replace existing ones. + supervariantArgumentsToRemove); // These arguments must be removed. + + AZStd::vector macroDefinitionNamesToRemove = supervariantInfo.GetCombinedListOfMacroDefinitionNamesToRemove(); + globalBuildOptions.m_preprocessorSettings.RemovePredefinedMacros(macroDefinitionNamesToRemove); + AZStd::vector macroDefinitionsToAdd = supervariantInfo.GetMacroDefinitionsToAdd(); + globalBuildOptions.m_preprocessorSettings.m_predefinedMacros.insert( + globalBuildOptions.m_preprocessorSettings.m_predefinedMacros.end(), macroDefinitionsToAdd.begin(), macroDefinitionsToAdd.end()); + + // Validate macro definitions that must be present. + EXPECT_TRUE( + VectorContainsAllSubstrings( + globalBuildOptions.m_preprocessorSettings.m_predefinedMacros, + AZStd::vector({MCPP_MACRO1, MCPP_NEW_VALUE1, MCPP_MACRO3, MCPP_NEW_VALUE3, MCPP_MACRO5})) + ); + + // Validate macro definitions that can't be present. + EXPECT_TRUE( + VectorDoesNotContainAnyOneOfTheSubstrings( + globalBuildOptions.m_preprocessorSettings.m_predefinedMacros, + AZStd::vector({MCPP_MACRO2, MCPP_VALUE3, MCPP_MACRO4})) + ); + + AZStd::string azslcArgsFromGlobalBuildOptions = globalBuildOptions.m_compilerArguments.MakeAdditionalAzslcCommandLineString(); + + // The result of GetCustomizedArgumentsForAzslc() is the most important value to test + AZStd::string customizedAzslcArgs = supervariantInfo.GetCustomizedArgumentsForAzslc(azslcArgsFromGlobalBuildOptions); + + EXPECT_TRUE( + StringContainsAllSubstrings(customizedAzslcArgs, CreateListOfSingleStringsFromListOfKeyValues(supervariantAzslArgumentsToAdd)) + ); + + EXPECT_TRUE( + StringDoesNotContainAnyOneOfTheSubstrings(customizedAzslcArgs, CreateListOfSingleStringsFromListOfKeyValues(supervariantAzslArgumentsToRemove)) + ); + + EXPECT_TRUE( + StringContainsAllSubstrings(customizedAzslcArgs, AZStd::vector({AZSLC_ARG3, AZSLC_VAL3, AZSLC_ARG5, AZSLC_VAL5})) + ); + } + + +} //namespace UnitTest + +AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); + diff --git a/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake b/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake new file mode 100644 index 0000000000..9f22f9f632 --- /dev/null +++ b/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.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(FILES + Tests/Common/ShaderBuilderTestFixture.h + Tests/Common/ShaderBuilderTestFixture.cpp + Tests/SupervariantCmdArgumentTests.cpp +) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl index db99ee7e24..644473fef9 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl @@ -77,10 +77,9 @@ PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) if(ShouldHandleParallaxInDepthShaders()) { - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, 1); + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index a91e88afad..440bb97c4e 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -117,19 +117,12 @@ VSOutput EnhancedPbr_ForwardPassVS(VSInput IN) PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth) { // ------- Tangents & Bitangets ------- + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - - if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering && MaterialSrg::m_parallaxUvIndex != 0) - || (o_normal_useTexture && MaterialSrg::m_normalMapUvIndex != 0) - || (o_clearCoat_enabled && o_clearCoat_normal_useTexture && MaterialSrg::m_clearCoatNormalMapUvIndex != 0) - || (o_detail_normal_useTexture && MaterialSrg::m_detail_allMapsUvIndex != 0)) + if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering) || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture) || o_detail_normal_useTexture) { - // Generate the tangent/bitangent for UV[1+] - const int startIndex = 1; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, startIndex); + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); } // ------- Depth & Parallax ------- @@ -260,7 +253,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // Convert the angle from [0..1] = [0 .. 180 degrees] to radians [0 .. PI] const float anisotropyAngle = MaterialSrg::m_anisotropicAngle * PI; const float anisotropyFactor = MaterialSrg::m_anisotropicFactor; - surface.anisotropy.Init(surface.normal, tangents[0], bitangents[0], anisotropyAngle, anisotropyFactor, surface.roughnessA); + surface.anisotropy.Init(surface.normal, IN.m_tangent, IN.m_bitangent, anisotropyAngle, anisotropyFactor, surface.roughnessA); } // ------- Lighting Data ------- diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl index 80aedcd6f4..7f6be252e2 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl @@ -80,10 +80,10 @@ PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) { static const float ShadowMapDepthBias = 0.000001; - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, 1); + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; + + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index 456d7cbabe..4fe1f2b364 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -180,17 +180,12 @@ PbrLightingOutput SkinPS_Common(VSOutput IN) float3x3 uvMatrix = CreateIdentity3x3(); // ------- Tangents & Bitangets ------- + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - - if ( (o_normal_useTexture && MaterialSrg::m_normalMapUvIndex != 0) || - (o_detail_normal_useTexture && MaterialSrg::m_detail_allMapsUvIndex != 0)) + if (o_normal_useTexture || o_detail_normal_useTexture) { - // Generate the tangent/bitangent for UV[1+] - const int startIndex = 1; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, startIndex); + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); } Surface surface; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index a2854e8902..274cb4dcb5 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -3,11 +3,6 @@ "propertyLayout": { "version": 3, "groups": [ - { - "id": "general", - "displayName": "General", - "description": "General settings." - }, { "id": "blend", "displayName": "Blend Settings", @@ -29,6 +24,11 @@ "displayName": "Irradiance", "description": "Properties for configuring the irradiance used in global illumination." }, + { + "id": "general", + "displayName": "General", + "description": "General settings." + }, //############################################################################################## // Layer 1 Groups //############################################################################################## @@ -74,8 +74,8 @@ }, { "id": "layer1_parallax", - "displayName": "Layer 1: Parallax Mapping", - "description": "Properties for parallax effect produced by depthmap." + "displayName": "Layer 1: Displacement", + "description": "Properties for surface displacement, which can be used for displacement-based blending and/or a parallax effect." }, { "id": "layer1_uv", @@ -127,8 +127,8 @@ }, { "id": "layer2_parallax", - "displayName": "Layer 2: Parallax Mapping", - "description": "Properties for parallax effect produced by depthmap." + "displayName": "Layer 2: Displacement", + "description": "Properties for surface displacement, which can be used for displacement-based blending and/or a parallax effect." }, { "id": "layer2_uv", @@ -180,8 +180,8 @@ }, { "id": "layer3_parallax", - "displayName": "Layer 3: Parallax Mapping", - "description": "Properties for parallax effect produced by depthmap." + "displayName": "Layer 3: Displacement", + "description": "Properties for surface displacement, which can be used for displacement-based blending and/or a parallax effect." }, { "id": "layer3_uv", @@ -194,18 +194,6 @@ // General Properties //############################################################################################## "general": [ - { - "id": "debugDrawMode", - "displayName": "Debug Draw Mode", - "description": "Enables various debug view features.", - "type": "Enum", - "enumValues": [ "None", "BlendSource", "DepthMaps" ], - "defaultValue": "None", - "connection": { - "type": "ShaderOption", - "id": "o_debugDrawMode" - } - }, { "id": "applySpecularAA", "displayName": "Apply Specular AA", @@ -322,16 +310,16 @@ "displayName": "Blend Source", "description": "The source to use for defining the blend mask. Note VertexColors mode will still use the texture as a fallback if the mesh does not have a COLOR0 stream.", "type": "Enum", - "enumValues": ["TextureMap", "VertexColors"], - "defaultValue": "TextureMap", + "enumValues": ["BlendMaskTexture", "BlendMaskVertexColors", "Displacement", "Displacement_With_BlendMaskTexture", "Displacement_With_BlendMaskVertexColors"], + "defaultValue": "BlendMaskTexture", "connection": { "type": "ShaderOption", - "id": "o_blendSource" + "id": "o_layerBlendSource" } }, { "id": "textureMap", - "displayName": "Blend Mask", + "displayName": "Blend Mask Texture", "description": "RGB image where each channel is the blend mask for one of the three available layers.", "type": "Image", "defaultValue": "Textures/DefaultBlendMask_layers.png", @@ -351,6 +339,32 @@ "type": "ShaderInput", "id": "m_blendMaskUvIndex" } + }, + { + "id": "displacementBlendDistance", + "displayName": "Blend Distance", + "description": "Adjusts how smoothly to transition between layers when displacement blending is enabled.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "softMax": 0.1, + "step": 0.001, + "connection": { + "type": "ShaderInput", + "id": "m_displacementBlendDistance" + } + }, + { + "id": "debugDrawMode", + "displayName": "Debug Draw Mode", + "description": "Enables various debug view features.", + "type": "Enum", + "enumValues": [ "None", "BlendMask", "Displacement", "FinalBlendWeights" ], + "defaultValue": "None", + "connection": { + "type": "ShaderOption", + "id": "o_debugDrawMode" + } } ], "parallax": [ @@ -359,7 +373,11 @@ "displayName": "Enable", "description": "Whether to enable the parallax feature for this material.", "type": "Bool", - "defaultValue": false + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "id": "o_parallax_feature_enabled" + } }, { "id": "parallaxUv", @@ -1090,27 +1108,38 @@ } ], "layer1_parallax": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the parallax feature.", - "type": "Bool", - "defaultValue": false - }, { "id": "textureMap", "displayName": "Texture Map", - "description": "Depthmap to create parallax effect.", + "description": "Displacement texture map, which can be used for layer blending and/or a parallax effect.", "type": "Image", "connection": { "type": "ShaderInput", "id": "m_layer1_m_depthMap" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "invert", + "displayName": "Invert", + "description": "Invert the displacement map", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_depthInverted" + } + }, { "id": "factor", - "displayName": "Heightmap Scale", - "description": "The total height of the heightmap in local model units.", + "displayName": "Scale", + "description": "The total height of the displacement texture map in local model units.", "type": "Float", "defaultValue": 0.0, "min": 0.0, @@ -1132,17 +1161,6 @@ "type": "ShaderInput", "id": "m_layer1_m_depthOffset" } - }, - { - "id": "invert", - "displayName": "Invert", - "description": "Invert to depthmap if the texture is heightmap", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderInput", - "id": "m_layer1_m_depthInverted" - } } ], "layer1_uv": [ @@ -1796,27 +1814,38 @@ } ], "layer2_parallax": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the parallax feature.", - "type": "Bool", - "defaultValue": false - }, { "id": "textureMap", "displayName": "Texture Map", - "description": "Depthmap to create parallax effect.", + "description": "Displacement texture map, which can be used for layer blending and/or a parallax effect.", "type": "Image", "connection": { "type": "ShaderInput", "id": "m_layer2_m_depthMap" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "invert", + "displayName": "Invert", + "description": "Invert the displacement map", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_depthInverted" + } + }, { "id": "factor", - "displayName": "Heightmap Scale", - "description": "The total height of the heightmap in local model units.", + "displayName": "Scale", + "description": "The total height of the displacement texture map in local model units.", "type": "Float", "defaultValue": 0.0, "min": 0.0, @@ -1838,17 +1867,6 @@ "type": "ShaderInput", "id": "m_layer2_m_depthOffset" } - }, - { - "id": "invert", - "displayName": "Invert", - "description": "Invert to depthmap if the texture is heightmap", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderInput", - "id": "m_layer2_m_depthInverted" - } } ], "layer2_uv": [ @@ -2502,27 +2520,38 @@ } ], "layer3_parallax": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the parallax feature.", - "type": "Bool", - "defaultValue": false - }, { "id": "textureMap", "displayName": "Texture Map", - "description": "Depthmap to create parallax effect.", + "description": "Displacement texture map, which can be used for layer blending and/or a parallax effect.", "type": "Image", "connection": { "type": "ShaderInput", "id": "m_layer3_m_depthMap" } }, + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "invert", + "displayName": "Invert", + "description": "Invert the displacement map", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_depthInverted" + } + }, { "id": "factor", - "displayName": "Heightmap Scale", - "description": "The total height of the heightmap in local model units.", + "displayName": "Scale", + "description": "The total height of the displacement texture map in local model units.", "type": "Float", "defaultValue": 0.0, "min": 0.0, @@ -2544,17 +2573,6 @@ "type": "ShaderInput", "id": "m_layer3_m_depthOffset" } - }, - { - "id": "invert", - "displayName": "Invert", - "description": "Invert to depthmap if the texture is heightmap", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderInput", - "id": "m_layer3_m_depthInverted" - } } ], "layer3_uv": [ @@ -2699,7 +2717,7 @@ { "type": "Lua", "args": { - "file": "StandardMultilayerPBR_Parallax.lua" + "file": "StandardMultilayerPBR_Displacement.lua" } }, //############################################################################################## @@ -2816,12 +2834,12 @@ } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardMultilayerPBR_ParallaxPerLayer.lua", - "propertyNamePrefix": "layer1_", - "srgNamePrefix": "m_layer1_", - "optionsNamePrefix": "o_layer1_" + "textureProperty": "layer1_parallax.textureMap", + "useTextureProperty": "layer1_parallax.useTexture", + "dependentProperties": ["layer1_parallax.factor", "layer1_parallax.invert"], + "shaderOption": "o_layer1_o_useDepthMap" } }, { @@ -2953,12 +2971,12 @@ } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardMultilayerPBR_ParallaxPerLayer.lua", - "propertyNamePrefix": "layer2_", - "srgNamePrefix": "m_layer2_", - "optionsNamePrefix": "o_layer2_" + "textureProperty": "layer2_parallax.textureMap", + "useTextureProperty": "layer2_parallax.useTexture", + "dependentProperties": ["layer2_parallax.factor", "layer2_parallax.invert"], + "shaderOption": "o_layer2_o_useDepthMap" } }, { @@ -3090,14 +3108,14 @@ } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardMultilayerPBR_ParallaxPerLayer.lua", - "propertyNamePrefix": "layer3_", - "srgNamePrefix": "m_layer3_", - "optionsNamePrefix": "o_layer3_" + "textureProperty": "layer3_parallax.textureMap", + "useTextureProperty": "layer3_parallax.useTexture", + "dependentProperties": ["layer3_parallax.factor", "layer3_parallax.invert"], + "shaderOption": "o_layer3_o_useDepthMap" } - }, + }, { // Maps 2D scale, offset, and rotate properties into a float3x3 transform matrix. "type": "Transform2D", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli index d2314efefe..c20a90c00b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli @@ -15,6 +15,7 @@ #include #include #include +#include #include "MaterialInputs/BaseColorInput.azsli" #include "MaterialInputs/RoughnessInput.azsli" @@ -42,9 +43,19 @@ COMMON_SRG_INPUTS_PARALLAX(prefix) ShaderResourceGroup MaterialSrg : SRG_PerMaterial { - Texture2D m_blendMaskTexture; + Texture2D m_blendMaskTexture; uint m_blendMaskUvIndex; + // When parallax mapping is used, these limit the heightmap intersection search range to the narrowest band possible, to give the best quality result. + // These are also support other calculations related to displacement-based blending, even when parallax is not used. + float m_displacementMin; // The lowest displacement value possible from all layers combined (negative values are below the surface) + float m_displacementMax; // The highest displacement value possible from all layers combined (negative values are below the surface) + + // When displacement-based blending is used, this is the height range where the surface properties of different layers will be blended together. + // We use an absolute value rather than a relative factor because disconnecting this property from the influence of other properties makes per-layer + // displacement adjustments feel more natural if they don't impact the blend distance. + float m_displacementBlendDistance; + // Auto-generate material SRG fields for common inputs for each layer DEFINE_LAYER_SRG_INPUTS(m_layer1_) DEFINE_LAYER_SRG_INPUTS(m_layer2_) @@ -61,10 +72,6 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial uint m_parallaxUvIndex; - // These are used to limit the heightmap intersection search range to the narrowest band possible, to give the best quality result. - float m_displacementMin; // The lowest displacement value possible from all layers combined - float m_displacementMax; // The highest displacement value possible from all layers combined - float3x3 m_uvMatrix; float4 m_pad4; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. float3x3 m_uvMatrixInverse; @@ -98,11 +105,11 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial option bool o_layer2_enabled; option bool o_layer3_enabled; -enum class DebugDrawMode { None, BlendSource, DepthMaps }; +enum class DebugDrawMode { None, BlendMask, Displacement, FinalBlendWeights }; option DebugDrawMode o_debugDrawMode; -enum class BlendMaskSource { TextureMap, VertexColors, Fallback }; -option BlendMaskSource o_blendSource; +enum class LayerBlendSource { BlendMaskTexture, BlendMaskVertexColors, Displacement, Displacement_With_BlendMaskTexture, Displacement_With_BlendMaskVertexColors, Fallback }; +option LayerBlendSource o_layerBlendSource; // Indicates whether the vertex input struct's "m_optional_blendMask" is bound. If false, it is not safe to read from m_optional_blendMask. // This option gets set automatically by the system at runtime; there is a soft naming convention that associates it with m_optional_blendMask. @@ -111,53 +118,83 @@ option BlendMaskSource o_blendSource; option bool o_blendMask_isBound; // ------ Blend Utilities ---------------------------------------- - // This is mainly used to pass extra data to the GetDepth callback function during the parallax depth search. // But since we have it, we use it in some other functions as well rather than passing it around. static float3 s_blendMaskFromVertexStream; -//! Returns the BlendMaskSource that will actually be used when rendering (not necessarily the same BlendMaskSource specified by the user) -BlendMaskSource GetFinalBlendMaskSource() +// TODO: Consider storing the result of GetFinalLayerBlendSource() in a static similar to s_blendMaskFromVertexStream. That might give better performance when variants aren't used. + +//! Returns the LayerBlendSource that will actually be used when rendering (not necessarily the same LayerBlendSource specified by the user) +LayerBlendSource GetFinalLayerBlendSource() { - if(o_blendSource == BlendMaskSource::TextureMap) + if(o_layerBlendSource == LayerBlendSource::BlendMaskTexture) { - return BlendMaskSource::TextureMap; + return o_layerBlendSource; } - else if(o_blendSource == BlendMaskSource::VertexColors) + else if(o_layerBlendSource == LayerBlendSource::BlendMaskVertexColors) { if(o_blendMask_isBound) { - return BlendMaskSource::VertexColors; + return o_layerBlendSource; } else { - return BlendMaskSource::TextureMap; + return LayerBlendSource::Fallback; + } + } + else if(o_layerBlendSource == LayerBlendSource::Displacement) + { + return o_layerBlendSource; + } + else if(o_layerBlendSource == LayerBlendSource::Displacement_With_BlendMaskTexture) + { + return o_layerBlendSource; + } + else if(o_layerBlendSource == LayerBlendSource::Displacement_With_BlendMaskVertexColors) + { + if(o_blendMask_isBound) + { + return o_layerBlendSource; + } + else + { + return LayerBlendSource::Displacement; } } else { - return BlendMaskSource::Fallback; + return LayerBlendSource::Fallback; } } -//! Return the raw blend source values directly from the blend mask or vertex colors, depending on the available data and configuration. +//! Return the applicable blend mask values from the blend mask texture or vertex colors, and filters out any that don't apply. //! layer1 is an implicit base layer -//! layer2 is weighted by r -//! layer3 is weighted by g +//! layer2 mask is in the r channel +//! layer3 mask is in the g channel //! b is reserved for perhaps a dedicated puddle layer -float3 GetBlendSourceValues(float2 uv) +//! @param blendSource indicates where to get the blend mask from +//! @param blendMaskUv for sampling a blend mask texture, if that's the blend source +//! @param blendMaskVertexColors the vertex color values to use for the blend mask, if that's the blend source +//! @return the blend mask values, or 0 if there is no blend mask +float3 GetApplicableBlendMaskValues(LayerBlendSource blendSource, float2 blendMaskUv, float3 blendMaskVertexColors) { float3 blendSourceValues = float3(0,0,0); if(o_layer2_enabled || o_layer3_enabled) { - switch(GetFinalBlendMaskSource()) + switch(blendSource) { - case BlendMaskSource::TextureMap: - blendSourceValues = MaterialSrg::m_blendMaskTexture.Sample(MaterialSrg::m_sampler, uv).rgb; + case LayerBlendSource::Displacement: + // In this case the blend mask has no effect, returning (1,1,1) disables any impact of the mask. + blendSourceValues = float3(1,1,1); break; - case BlendMaskSource::VertexColors: - blendSourceValues = s_blendMaskFromVertexStream; + case LayerBlendSource::BlendMaskTexture: + case LayerBlendSource::Displacement_With_BlendMaskTexture: + blendSourceValues = MaterialSrg::m_blendMaskTexture.Sample(MaterialSrg::m_sampler, blendMaskUv).rgb; + break; + case LayerBlendSource::BlendMaskVertexColors: + case LayerBlendSource::Displacement_With_BlendMaskVertexColors: + blendSourceValues = blendMaskVertexColors; break; } @@ -175,29 +212,96 @@ float3 GetBlendSourceValues(float2 uv) return blendSourceValues; } -//! Return the final blend mask values to be used for rendering, based on the available data and configuration. +//! When dealing with masks for displacement-based blending, we sometimes need to push the value below the min displacement to make it disappear. +float GetSubMinDisplacement() +{ + return MaterialSrg::m_displacementMin - 0.001; + //return MaterialSrg::m_displacementMin - max(MaterialSrg::m_displacementBlendDistance, 0.001); +} + +float3 ApplyBlendMaskToDepthValues(float3 blendMaskValues, float3 layerDepthValues, float zeroMaskDisplacement); + +//! Return the final blend weights to be used for rendering, based on the available data and configuration. +//! @param blendSource - indicates where to get the blend mask from +//! @param blendMaskValues - blend mask values as returned by GetApplicableBlendMaskValues() +//! @param layerDepthValues - the depth values for each layer, used if the blend source includes displacement. See GetLayerDepthValues(). +//! Note the blendMaskValues will not be applied here, those should have already been applied to layerDepthValues. +//! @param layerDepthBlendDistance - controls how smoothly to blend layers 2 and 3 with the base layer, when the blend source includes displacement. +//! When layers are close together their weights will be blended together, otherwise the highest layer will have the full weight. //! @return The blend weights for each layer. -//! Even though layer1 not explicitly specified in the blend source data, it is explicitly included with the returned values. +//! Even though layer1 not explicitly specified in the blend mask data, it is explicitly included with the returned values. //! layer1 = r //! layer2 = g //! layer3 = b -float3 GetBlendWeights(float2 uv) +float3 GetBlendWeights(LayerBlendSource blendSource, float3 blendMaskValues, float3 layerDepthValues, float layerDepthBlendDistance) { float3 blendWeights; if(o_layer2_enabled || o_layer3_enabled) { - float3 blendSourceValues = GetBlendSourceValues(uv); + if(LayerBlendSource::Displacement == blendSource || + LayerBlendSource::Displacement_With_BlendMaskTexture == blendSource || + LayerBlendSource::Displacement_With_BlendMaskVertexColors == blendSource) + { + // Calculate the blend weights based on displacement values... - // Calculate blend weights such that multiplying and adding them with layer data is equivalent - // to lerping between each layer. - // final = lerp(final, layer1, blendWeights.r) - // final = lerp(final, layer2, blendWeights.g) - // final = lerp(final, layer3, blendWeights.b) + // The inputs are depth values, but we change them to height values to make the code a bit more intuitive. + float3 layerHeightValues = -layerDepthValues; + + float highestPoint = layerHeightValues.x; + if(o_layer2_enabled) + { + highestPoint = max(highestPoint, layerHeightValues.y); + } + if(o_layer3_enabled) + { + highestPoint = max(highestPoint, layerHeightValues.z); + } + + if(layerDepthBlendDistance > 0.0001) + { + float lowestVisiblePoint = highestPoint - layerDepthBlendDistance; + blendWeights = smoothstep(lowestVisiblePoint, highestPoint, layerHeightValues); + + if(!o_layer2_enabled) + { + blendWeights.y = 0.0; + } + + if(!o_layer3_enabled) + { + blendWeights.z = 0.0; + } + } + else + { + blendWeights = float3(layerHeightValues.x >= highestPoint ? 1.0 : 0.0, + layerHeightValues.y >= highestPoint && o_layer2_enabled ? 1.0 : 0.0, + layerHeightValues.z >= highestPoint && o_layer3_enabled ? 1.0 : 0.0); + } + + // Calculate blend weights such that multiplying and adding them with layer data is equivalent + // to lerping between each layer. + // final = lerp(final, layer1, blendWeights.r) + // final = lerp(final, layer2, blendWeights.g) + // final = lerp(final, layer3, blendWeights.b) + + blendWeights.y = (1 - blendWeights.z) * blendWeights.y; + blendWeights.x = 1 - blendWeights.y - blendWeights.z; + } + else + { + // Calculate blend weights such that multiplying and adding them with layer data is equivalent + // to lerping between each layer. + // final = lerp(final, layer1, blendWeights.r) + // final = lerp(final, layer2, blendWeights.g) + // final = lerp(final, layer3, blendWeights.b) + + blendWeights.b = blendMaskValues.g; + blendWeights.g = (1.0 - blendMaskValues.g) * blendMaskValues.r; + blendWeights.r = (1.0 - blendMaskValues.g) * (1.0 - blendMaskValues.r); + } - blendWeights.b = blendSourceValues.g; - blendWeights.g = (1.0 - blendSourceValues.g) * blendSourceValues.r; - blendWeights.r = (1.0 - blendSourceValues.g) * (1.0 - blendSourceValues.r); } else { @@ -207,6 +311,38 @@ float3 GetBlendWeights(float2 uv) return blendWeights; } +float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy); + +//! Return the final blend weights to be used for rendering, based on the available data and configuration. +//! Note this will sample the displacement maps in the case of LayerBlendSource::Displacement. If you have already +//! the layer depth values, use the GetBlendWeights() overload that takes layerDepthValues instead. +float3 GetBlendWeights(LayerBlendSource blendSource, float2 uv, float3 blendMaskVertexColors) +{ + float3 layerDepthValues = float3(0,0,0); + + float3 blendMaskValues = GetApplicableBlendMaskValues(blendSource, uv, blendMaskVertexColors); + + if(blendSource == LayerBlendSource::Displacement || + blendSource == LayerBlendSource::Displacement_With_BlendMaskTexture || + blendSource == LayerBlendSource::Displacement_With_BlendMaskVertexColors) + { + bool useBlendMask = + LayerBlendSource::Displacement_With_BlendMaskTexture == blendSource || + LayerBlendSource::Displacement_With_BlendMaskVertexColors == blendSource; + + layerDepthValues = GetLayerDepthValues(uv, ddx_fine(uv), ddy_fine(uv)); + + if(useBlendMask) + { + // Unlike the GetDepth() callback used for parallax, we don't just shift the values toward GetSubMinDisplacement(), + // we shift extra to ensure that completely masked-out layers are not blended onto upper layers. + layerDepthValues = ApplyBlendMaskToDepthValues(blendMaskValues, layerDepthValues, GetSubMinDisplacement() - MaterialSrg::m_displacementBlendDistance); + } + } + + return GetBlendWeights(blendSource, blendMaskValues, layerDepthValues, MaterialSrg::m_displacementBlendDistance); +} + float BlendLayers(float layer1, float layer2, float layer3, float3 blendWeights) { return dot(float3(layer1, layer2, layer3), blendWeights); @@ -236,55 +372,127 @@ bool ShouldHandleParallaxInDepthShaders() return ShouldHandleParallax() && o_parallax_enablePixelDepthOffset; } -// Callback function for ParallaxMapping.azsli -DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) +//! Returns the depth values for each layer. +float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy) { float3 layerDepthValues = float3(0,0,0); - - if(o_layer1_o_useDepthMap) + + // layer1 { - float2 layerUv = uv; - if(MaterialSrg::m_parallaxUvIndex == 0) + if(o_layer1_o_useDepthMap) { - layerUv = mul(MaterialSrg::m_layer1_m_uvMatrix, float3(uv, 1.0)).xy; + float2 layerUv = uv; + if(MaterialSrg::m_parallaxUvIndex == 0) + { + layerUv = mul(MaterialSrg::m_layer1_m_uvMatrix, float3(uv, 1.0)).xy; + } + + layerDepthValues.r = SampleDepthOrHeightMap(MaterialSrg::m_layer1_m_depthInverted, MaterialSrg::m_layer1_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; + layerDepthValues.r *= MaterialSrg::m_layer1_m_depthFactor; } - layerDepthValues.r = SampleDepthOrHeightMap(MaterialSrg::m_layer1_m_depthInverted, MaterialSrg::m_layer1_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; - layerDepthValues.r *= MaterialSrg::m_layer1_m_depthFactor; layerDepthValues.r -= MaterialSrg::m_layer1_m_depthOffset; } - if(o_layer2_enabled && o_layer2_o_useDepthMap) + if(o_layer2_enabled) { - float2 layerUv = uv; - if(MaterialSrg::m_parallaxUvIndex == 0) + if(o_layer2_o_useDepthMap) { - layerUv = mul(MaterialSrg::m_layer2_m_uvMatrix, float3(uv, 1.0)).xy; + float2 layerUv = uv; + if(MaterialSrg::m_parallaxUvIndex == 0) + { + layerUv = mul(MaterialSrg::m_layer2_m_uvMatrix, float3(uv, 1.0)).xy; + } + + layerDepthValues.g = SampleDepthOrHeightMap(MaterialSrg::m_layer2_m_depthInverted, MaterialSrg::m_layer2_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; + layerDepthValues.g *= MaterialSrg::m_layer2_m_depthFactor; } - layerDepthValues.g = SampleDepthOrHeightMap(MaterialSrg::m_layer2_m_depthInverted, MaterialSrg::m_layer2_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; - layerDepthValues.g *= MaterialSrg::m_layer2_m_depthFactor; layerDepthValues.g -= MaterialSrg::m_layer2_m_depthOffset; + } - if(o_layer3_enabled && o_layer3_o_useDepthMap) + if(o_layer3_enabled) { - float2 layerUv = uv; - if(MaterialSrg::m_parallaxUvIndex == 0) + if(o_layer3_o_useDepthMap) { - layerUv = mul(MaterialSrg::m_layer3_m_uvMatrix, float3(uv, 1.0)).xy; + float2 layerUv = uv; + if(MaterialSrg::m_parallaxUvIndex == 0) + { + layerUv = mul(MaterialSrg::m_layer3_m_uvMatrix, float3(uv, 1.0)).xy; + } + + layerDepthValues.b = SampleDepthOrHeightMap(MaterialSrg::m_layer3_m_depthInverted, MaterialSrg::m_layer3_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; + layerDepthValues.b *= MaterialSrg::m_layer3_m_depthFactor; } - layerDepthValues.b = SampleDepthOrHeightMap(MaterialSrg::m_layer3_m_depthInverted, MaterialSrg::m_layer3_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth; - layerDepthValues.b *= MaterialSrg::m_layer3_m_depthFactor; layerDepthValues.b -= MaterialSrg::m_layer3_m_depthOffset; + } - // Note, when the blend source is BlendMaskSource::VertexColors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values - // for every UV position when searching for the intersection. This leads to smearing artifacts at the transition point, but these won't be so noticeable as long as - // you have a small depth factor relative to the size of the blend transition. - float3 blendWeights = GetBlendWeights(uv); + return layerDepthValues; +} + + +//! Uses a layer blend mask to further displace each layer's surface so that it disappears beyond the other surfaces. +//! Note the blend mask does not apply to the first layer, it is the implicit base layer. Layers 2 and 3 are masked by the r and g channels of the mask. +//! @param blendMaskValues layer mask values as returned by GetApplicableBlendMaskValues() +//! @param layerDepthValues layer depth values as returned by GetLayerDepthValues() +//! @param zeroMaskDisplacement the target displacement value that corresponds to a mask value of 0 +//! @return new layer depth values that have been adjusted according to the layerMaskValues +float3 ApplyBlendMaskToDepthValues(float3 blendMaskValues, float3 layerDepthValues, float zeroMaskDisplacement) +{ + if(o_layer2_enabled || o_layer3_enabled) + { + // We add to the depth value rather than lerp toward m_displacementMin to avoid squashing the topology, but instead lower it out of sight. + + if(o_layer2_enabled) + { + float dropoffRange = MaterialSrg::m_layer2_m_depthOffset - zeroMaskDisplacement; + layerDepthValues.g += dropoffRange * (1-blendMaskValues.r); + } + + if(o_layer3_enabled) + { + float dropoffRange = MaterialSrg::m_layer3_m_depthOffset - zeroMaskDisplacement; + layerDepthValues.b += dropoffRange * (1-blendMaskValues.g); + } + } + + return layerDepthValues; +} + +//! Callback function for ParallaxMapping.azsli +DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy) +{ + LayerBlendSource blendSource = GetFinalLayerBlendSource(); + + float3 layerDepthValues = GetLayerDepthValues(uv, uv_ddx, uv_ddy); + + // Note, when the blend source uses the blend mask from the vertex colors, parallax will not be able to blend correctly between layers. It will end up using the same blend mask values + // for every UV position when searching for the intersection. This leads to smearing artifacts at the transition point, but these won't be as noticeable if + // you have a small depth factor relative to the size of the blend transition. + float3 blendMaskValues = GetApplicableBlendMaskValues(blendSource, uv, s_blendMaskFromVertexStream); + + bool useBlendMask = + LayerBlendSource::Displacement_With_BlendMaskTexture == blendSource || + LayerBlendSource::Displacement_With_BlendMaskVertexColors == blendSource; + + if(useBlendMask) + { + // Regarding GetSubMinDisplacement(), when a mask of 0 pushes the surface all the way to the bottom, we want that + // to go a little below the min so it will disappear if there is something else right at the min. + + layerDepthValues = ApplyBlendMaskToDepthValues(blendMaskValues, layerDepthValues, GetSubMinDisplacement()); + } + + // When blending the depth together, we don't use MaterialSrg::m_displacementBlendDistance. The intention is that m_displacementBlendDistance + // is for transitioning the appearance of the surface itself, but we still want a distinct change in the heightmap. If someday we want to + // support smoothly blending the depth as well, there is a bit more work to do to get it to play nice with the blend mask code in GetLayerDepthValues(). + float layerDepthBlendDistance = 0.0f; + float3 blendWeightValues = GetBlendWeights(blendSource, blendMaskValues, layerDepthValues, layerDepthBlendDistance); + + float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeightValues); - float depth = BlendLayers(layerDepthValues.r, layerDepthValues.g, layerDepthValues.b, blendWeights); return DepthResultAbsolute(depth); } diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl index 178deca8a2..cf4d53e805 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl @@ -84,7 +84,7 @@ VSDepthOutput MainVS(VSInput IN) } else { - OUT.m_blendMask = float3(1,1,1); + OUT.m_blendMask = float3(0,0,0); } return OUT; @@ -103,11 +103,11 @@ PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) if(ShouldHandleParallaxInDepthShaders()) { - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, 1); - + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; + + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); + s_blendMaskFromVertexStream = IN.m_blendMask; float depth; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua new file mode 100644 index 0000000000..34a067577d --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua @@ -0,0 +1,147 @@ +-------------------------------------------------------------------------------------- +-- +-- 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 functor handles general parallax properties that affect the entire material. + +function GetMaterialPropertyDependencies() + return { + "blend.blendSource", + "blend.enableLayer2", + "blend.enableLayer3", + "parallax.enable", + "layer1_parallax.textureMap", + "layer2_parallax.textureMap", + "layer3_parallax.textureMap", + "layer1_parallax.useTexture", + "layer2_parallax.useTexture", + "layer3_parallax.useTexture", + "layer1_parallax.factor", + "layer2_parallax.factor", + "layer3_parallax.factor", + "layer1_parallax.offset", + "layer2_parallax.offset", + "layer3_parallax.offset" + } +end + +-- These values must align with LayerBlendSource in StandardMultilayerPBR_Common.azsli. +LayerBlendSource_BlendMaskTexture = 0 +LayerBlendSource_BlendMaskVertexColors = 1 +LayerBlendSource_Displacement = 2 +LayerBlendSource_Displacement_With_BlendMaskTexture = 3 +LayerBlendSource_Displacement_With_BlendMaskVertexColors = 4 + +function BlendSourceUsesDisplacement(context) + local blendSource = context:GetMaterialPropertyValue_enum("blend.blendSource") + local blendSourceIncludesDisplacement = (blendSource == LayerBlendSource_Displacement or + blendSource == LayerBlendSource_Displacement_With_BlendMaskTexture or + blendSource == LayerBlendSource_Displacement_With_BlendMaskVertexColors) + return blendSourceIncludesDisplacement +end + +-- Calculates the min and max displacement height values encompassing all enabled layers. +-- @return a table with two values {min,max}. Negative values are below the surface and positive values are above the surface. +function CalcOverallHeightRange(context) + + local heightMinMax = {nil, nil} + + local function GetMergedHeightRange(heightMinMax, offset, factor) + top = offset + bottom = offset - factor + + if(heightMinMax[1] == nil) then + heightMinMax[1] = top + else + heightMinMax[1] = math.max(heightMinMax[1], top) + end + + if(heightMinMax[0] == nil) then + heightMinMax[0] = bottom + else + heightMinMax[0] = math.min(heightMinMax[0], bottom) + end + end + + local enableParallax = context:GetMaterialPropertyValue_bool("parallax.enable") + + if(enableParallax or BlendSourceUsesDisplacement(context)) then + local hasTextureLayer1 = nil ~= context:GetMaterialPropertyValue_Image("layer1_parallax.textureMap") + local hasTextureLayer2 = nil ~= context:GetMaterialPropertyValue_Image("layer2_parallax.textureMap") + local hasTextureLayer3 = nil ~= context:GetMaterialPropertyValue_Image("layer3_parallax.textureMap") + + local useTextureLayer1 = context:GetMaterialPropertyValue_bool("layer1_parallax.useTexture") + local useTextureLayer2 = context:GetMaterialPropertyValue_bool("layer2_parallax.useTexture") + local useTextureLayer3 = context:GetMaterialPropertyValue_bool("layer3_parallax.useTexture") + + local factorLayer1 = context:GetMaterialPropertyValue_float("layer1_parallax.factor") + local factorLayer2 = context:GetMaterialPropertyValue_float("layer2_parallax.factor") + local factorLayer3 = context:GetMaterialPropertyValue_float("layer3_parallax.factor") + + if not hasTextureLayer1 or not useTextureLayer1 then factorLayer1 = 0 end + if not hasTextureLayer2 or not useTextureLayer2 then factorLayer2 = 0 end + if not hasTextureLayer3 or not useTextureLayer3 then factorLayer3 = 0 end + + local offsetLayer1 = context:GetMaterialPropertyValue_float("layer1_parallax.offset") + local offsetLayer2 = context:GetMaterialPropertyValue_float("layer2_parallax.offset") + local offsetLayer3 = context:GetMaterialPropertyValue_float("layer3_parallax.offset") + + local enableLayer2 = context:GetMaterialPropertyValue_bool("blend.enableLayer2") + local enableLayer3 = context:GetMaterialPropertyValue_bool("blend.enableLayer3") + + GetMergedHeightRange(heightMinMax, offsetLayer1, factorLayer1) + if(enableLayer2) then GetMergedHeightRange(heightMinMax, offsetLayer2, factorLayer2) end + if(enableLayer3) then GetMergedHeightRange(heightMinMax, offsetLayer3, factorLayer3) end + + else + heightMinMax = {0,0} + end + + return heightMinMax +end + +function Process(context) + local heightMinMax = CalcOverallHeightRange(context) + context:SetShaderConstant_float("m_displacementMin", heightMinMax[0]) + context:SetShaderConstant_float("m_displacementMax", heightMinMax[1]) +end + +function ProcessEditor(context) + local enable = context:GetMaterialPropertyValue_bool("parallax.enable") + + local visibility = MaterialPropertyVisibility_Enabled + if(not enable) then + visibility = MaterialPropertyVisibility_Hidden + end + + context:SetMaterialPropertyVisibility("parallax.parallaxUv", visibility) + context:SetMaterialPropertyVisibility("parallax.algorithm", visibility) + context:SetMaterialPropertyVisibility("parallax.quality", visibility) + context:SetMaterialPropertyVisibility("parallax.pdo", visibility) + context:SetMaterialPropertyVisibility("parallax.showClipping", visibility) + + if BlendSourceUsesDisplacement(context) then + context:SetMaterialPropertyVisibility("blend.displacementBlendDistance", MaterialPropertyVisibility_Enabled) + else + context:SetMaterialPropertyVisibility("blend.displacementBlendDistance", MaterialPropertyVisibility_Hidden) + end + + -- We set the displacementBlendDistance slider range to match the range of displacement, so the slider will feel good + -- regardless of how big the overall displacement is. Using a soft max allows the user to exceed the limit if desired, + -- but the main reason for the *soft* max is to avoid impacting the value of displacementBlendDistance which could + -- otherwise lead to edge cases. + local heightMinMax = CalcOverallHeightRange(context) + local totalDisplacementRange = heightMinMax[1] - heightMinMax[0] + context:SetMaterialPropertySoftMaxValue_float("blend.displacementBlendDistance", math.max(totalDisplacementRange, 0.001)) +end + diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl index 580e5206ab..19efc60a1e 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -116,7 +116,7 @@ VSOutput ForwardPassVS(VSInput IN) } else { - OUT.m_blendMask = float3(1,1,1); + OUT.m_blendMask = float3(0,0,0); } // Shadow coords will be calculated in the pixel shader in this case @@ -310,38 +310,45 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float s_blendMaskFromVertexStream = IN.m_blendMask; + LayerBlendSource blendSource = GetFinalLayerBlendSource(); + // ------- Tangents & Bitangets ------- + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - - if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering && MaterialSrg::m_parallaxUvIndex != 0) - || (o_layer1_o_normal_useTexture && MaterialSrg::m_layer1_m_normalMapUvIndex != 0) - || (o_layer2_o_normal_useTexture && MaterialSrg::m_layer2_m_normalMapUvIndex != 0) - || (o_layer3_o_normal_useTexture && MaterialSrg::m_layer3_m_normalMapUvIndex != 0) - || (o_layer1_o_clearCoat_normal_useTexture && MaterialSrg::m_layer1_m_clearCoatNormalMapUvIndex != 0) - || (o_layer2_o_clearCoat_normal_useTexture && MaterialSrg::m_layer2_m_clearCoatNormalMapUvIndex != 0) - || (o_layer3_o_clearCoat_normal_useTexture && MaterialSrg::m_layer3_m_clearCoatNormalMapUvIndex != 0) + if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering) + || o_layer1_o_normal_useTexture + || o_layer2_o_normal_useTexture + || o_layer3_o_normal_useTexture + || o_layer1_o_clearCoat_normal_useTexture + || o_layer2_o_clearCoat_normal_useTexture + || o_layer3_o_clearCoat_normal_useTexture ) { - // Generate the tangent/bitangent for UV[1+] - const int startIndex = 1; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, startIndex); + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); } // ------- Debug Modes ------- - if(o_debugDrawMode == DebugDrawMode::BlendSource) + if(o_debugDrawMode == DebugDrawMode::BlendMask) { - float3 blendSource = GetBlendSourceValues(IN.m_uv[MaterialSrg::m_blendMaskUvIndex]); - return DebugOutput(blendSource); + float3 blendMaskValues = GetApplicableBlendMaskValues(blendSource, IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendMask); + return DebugOutput(blendMaskValues); } - if(o_debugDrawMode == DebugDrawMode::DepthMaps) + if(o_debugDrawMode == DebugDrawMode::Displacement) { - float depth = GetNormalizedDepth(-MaterialSrg::m_displacementMax, -MaterialSrg::m_displacementMin, IN.m_uv[MaterialSrg::m_parallaxUvIndex], float2(0,0), float2(0,0)); - return DebugOutput(float3(depth,depth,depth)); + float startDepth = -MaterialSrg::m_displacementMax; + float stopDepth = -MaterialSrg::m_displacementMin; + float depth = GetNormalizedDepth(startDepth, stopDepth, IN.m_uv[MaterialSrg::m_parallaxUvIndex], float2(0,0), float2(0,0)); + float height = 1 - saturate(depth); + return DebugOutput(float3(height,height,height)); + } + + if(o_debugDrawMode == DebugDrawMode::FinalBlendWeights) + { + float3 blendWeights = GetBlendWeights(blendSource, IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendMask); + return DebugOutput(blendWeights); } // ------- Parallax ------- @@ -373,21 +380,27 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Calculate Layer Blend Mask Values ------- // Now that any parallax has been calculated, we calculate the blend factors for any layers that are impacted by the parallax. - float3 blendWeights = GetBlendWeights(IN.m_uv[MaterialSrg::m_blendMaskUvIndex]); + float3 blendWeights = GetBlendWeights(blendSource, IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendMask); // ------- Layer 1 (base layer) ----------- ProcessedMaterialInputs lightingInputLayer1; + if(blendWeights.r > 0) { StandardMaterialInputs inputs; FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer1_, o_layer1_, blendWeights.r) lightingInputLayer1 = ProcessStandardMaterialInputs(inputs); } + else + { + lightingInputLayer1.InitializeToZero(); + blendWeights.r = 0; + } // ----------- Layer 2 ----------- ProcessedMaterialInputs lightingInputLayer2; - if(o_layer2_enabled) + if(o_layer2_enabled && blendWeights.g > 0) { StandardMaterialInputs inputs; FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer2_, o_layer2_, blendWeights.g) @@ -396,12 +409,13 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float else { lightingInputLayer2.InitializeToZero(); + blendWeights.g = 0; } // ----------- Layer 3 ----------- ProcessedMaterialInputs lightingInputLayer3; - if(o_layer3_enabled) + if(o_layer3_enabled && blendWeights.b > 0) { StandardMaterialInputs inputs; FILL_STANDARD_MATERIAL_INPUTS(inputs, MaterialSrg::m_layer3_, o_layer3_, blendWeights.b) @@ -410,6 +424,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float else { lightingInputLayer3.InitializeToZero(); + blendWeights.b = 0; } // ------- Combine all layers --------- @@ -420,12 +435,16 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Combine Normals --------- - float3 normalTS = lightingInputLayer1.m_normalTS; - if(o_layer2_enabled) + float3 normalTS = float3(0,0,1); + if(blendWeights.r > 0) + { + normalTS = lightingInputLayer1.m_normalTS; + } + if(o_layer2_enabled && blendWeights.g > 0) { normalTS = ReorientTangentSpaceNormal(normalTS, lightingInputLayer2.m_normalTS); } - if(o_layer3_enabled) + if(o_layer3_enabled && blendWeights.b > 0) { normalTS = ReorientTangentSpaceNormal(normalTS, lightingInputLayer3.m_normalTS); } diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua deleted file mode 100644 index 8880a4b842..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Parallax.lua +++ /dev/null @@ -1,97 +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. --- --- ----------------------------------------------------------------------------------------------------- - --- This functor handles general parallax properties that affect the entire material. - -function GetMaterialPropertyDependencies() - return { - "parallax.enable", - "layer1_parallax.enable", - "layer2_parallax.enable", - "layer3_parallax.enable", - "layer1_parallax.factor", - "layer2_parallax.factor", - "layer3_parallax.factor", - "layer1_parallax.offset", - "layer2_parallax.offset", - "layer3_parallax.offset" - } -end - -function GetShaderOptionDependencies() - return {"o_parallax_feature_enabled"} -end - -function MergeRange(heightMinMax, offset, factor) - top = offset - bottom = offset - factor - - if(heightMinMax[1] == nil) then - heightMinMax[1] = top - else - heightMinMax[1] = math.max(heightMinMax[1], top) - end - - if(heightMinMax[0] == nil) then - heightMinMax[0] = bottom - else - heightMinMax[0] = math.min(heightMinMax[0], bottom) - end -end - -function Process(context) - local enableParallax = context:GetMaterialPropertyValue_bool("parallax.enable") - local enable1 = context:GetMaterialPropertyValue_bool("layer1_parallax.enable") - local enable2 = context:GetMaterialPropertyValue_bool("layer2_parallax.enable") - local enable3 = context:GetMaterialPropertyValue_bool("layer3_parallax.enable") - enableParallax = enableParallax and (enable1 or enable2 or enable3) - context:SetShaderOptionValue_bool("o_parallax_feature_enabled", enableParallax) - - if(enableParallax) then - local factorLayer1 = context:GetMaterialPropertyValue_float("layer1_parallax.factor") - local factorLayer2 = context:GetMaterialPropertyValue_float("layer2_parallax.factor") - local factorLayer3 = context:GetMaterialPropertyValue_float("layer3_parallax.factor") - - local offsetLayer1 = context:GetMaterialPropertyValue_float("layer1_parallax.offset") - local offsetLayer2 = context:GetMaterialPropertyValue_float("layer2_parallax.offset") - local offsetLayer3 = context:GetMaterialPropertyValue_float("layer3_parallax.offset") - - local heightMinMax = {nil, nil} - if(enable1) then MergeRange(heightMinMax, offsetLayer1, factorLayer1) end - if(enable2) then MergeRange(heightMinMax, offsetLayer2, factorLayer2) end - if(enable3) then MergeRange(heightMinMax, offsetLayer3, factorLayer3) end - - if(heightMinMax[1] - heightMinMax[0] < 0.0001) then - context:SetShaderOptionValue_bool("o_parallax_feature_enabled", false) - else - context:SetShaderConstant_float("m_displacementMin", heightMinMax[0]) - context:SetShaderConstant_float("m_displacementMax", heightMinMax[1]) - end - end -end - -function ProcessEditor(context) - local enable = context:GetMaterialPropertyValue_bool("parallax.enable") - - local visibility = MaterialPropertyVisibility_Enabled - if(not enable) then - visibility = MaterialPropertyVisibility_Hidden - end - - context:SetMaterialPropertyVisibility("parallax.parallaxUv", visibility) - context:SetMaterialPropertyVisibility("parallax.algorithm", visibility) - context:SetMaterialPropertyVisibility("parallax.quality", visibility) - context:SetMaterialPropertyVisibility("parallax.pdo", visibility) - context:SetMaterialPropertyVisibility("parallax.showClipping", visibility) -end diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua deleted file mode 100644 index bd56292229..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua +++ /dev/null @@ -1,49 +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. --- --- ----------------------------------------------------------------------------------------------------- - --- This functor handles parallax properties that are specific to a single layer. - -function GetMaterialPropertyDependencies() - return {"parallax.enable", "parallax.textureMap"} -end - -function GetShaderOptionDependencies() - return {"o_useDepthMap"} -end - -function Process(context) - local enable = context:GetMaterialPropertyValue_bool("parallax.enable") - local textureMap = context:GetMaterialPropertyValue_Image("parallax.textureMap") - context:SetShaderOptionValue_bool("o_useDepthMap", enable and textureMap ~= nil) -end - -function ProcessEditor(context) - local enable = context:GetMaterialPropertyValue_bool("parallax.enable") - - if enable then - context:SetMaterialPropertyVisibility("parallax.textureMap", MaterialPropertyVisibility_Enabled) - else - context:SetMaterialPropertyVisibility("parallax.textureMap", MaterialPropertyVisibility_Hidden) - end - - local textureMap = context:GetMaterialPropertyValue_Image("parallax.textureMap") - local visibility = MaterialPropertyVisibility_Enabled - if(not enable or textureMap == nil) then - visibility = MaterialPropertyVisibility_Hidden - end - - context:SetMaterialPropertyVisibility("parallax.factor", visibility) - context:SetMaterialPropertyVisibility("parallax.offset", visibility) - context:SetMaterialPropertyVisibility("parallax.invert", visibility) -end diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl index 02ccd78735..6c80dc874b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl @@ -83,7 +83,7 @@ VertexOutput MainVS(VertexInput IN) } else { - OUT.m_blendMask = float3(1,1,1); + OUT.m_blendMask = float3(0,0,0); } return OUT; @@ -102,10 +102,10 @@ PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) if(ShouldHandleParallaxInDepthShaders()) { - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, 1); + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; + + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); s_blendMaskFromVertexStream = IN.m_blendMask; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl index 28708c12d5..afc93f060e 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl @@ -78,10 +78,10 @@ PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) if(ShouldHandleParallaxInDepthShaders()) { - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, 1); + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; + + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl index bf1ec96b79..2667c8123b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl @@ -110,19 +110,12 @@ VSOutput StandardPbr_ForwardPassVS(VSInput IN) PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depthNDC) { // ------- Tangents & Bitangets ------- + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - - if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering && MaterialSrg::m_parallaxUvIndex != 0) - || (o_normal_useTexture && MaterialSrg::m_normalMapUvIndex != 0) - || (o_clearCoat_enabled && o_clearCoat_normal_useTexture && MaterialSrg::m_clearCoatNormalMapUvIndex != 0) - ) + if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering) || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture)) { - // Generate the tangent/bitangent for UV[1+] - const int startIndex = 1; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, startIndex); + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); } // ------- Depth & Parallax ------- diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl index 7f24b29700..533df3bb92 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Shadowmap_WithPS.azsl @@ -81,10 +81,9 @@ PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace) { static const float ShadowMapDepthBias = 0.000001; - // We support two UV streams, but only a single stream of tangent/bitangent. So for UV[1+] we generated the tangent/bitangent in screen-space. - float3 tangents[UvSetCount] = { IN.m_tangent.xyz, float3(0, 0, 0) }; - float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, float3(0, 0, 0) }; - PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, 1); + float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz }; + float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz }; + PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents); float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3(); diff --git a/Gems/Atom/Feature/Common/Assets/Textures/PostProcessing/AreaTex.dds.assetinfo b/Gems/Atom/Feature/Common/Assets/Textures/PostProcessing/AreaTex.dds.assetinfo index 53dbfb2623..72a7948174 100644 --- a/Gems/Atom/Feature/Common/Assets/Textures/PostProcessing/AreaTex.dds.assetinfo +++ b/Gems/Atom/Feature/Common/Assets/Textures/PostProcessing/AreaTex.dds.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/Atom/Feature/Common/Assets/Textures/PostProcessing/SearchTex.dds.assetinfo b/Gems/Atom/Feature/Common/Assets/Textures/PostProcessing/SearchTex.dds.assetinfo index 3ae9447621..86d698d24e 100644 --- a/Gems/Atom/Feature/Common/Assets/Textures/PostProcessing/SearchTex.dds.assetinfo +++ b/Gems/Atom/Feature/Common/Assets/Textures/PostProcessing/SearchTex.dds.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/PaperMill_E_3k.exr.assetinfo b/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/PaperMill_E_3k.exr.assetinfo index da00149fb0..16cb0dd668 100644 --- a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/PaperMill_E_3k.exr.assetinfo +++ b/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/PaperMill_E_3k.exr.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake index f1d8fa81be..841cdf67c8 100644 --- a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake +++ b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake @@ -33,11 +33,11 @@ set(FILES Materials/Types/StandardMultilayerPBR_Common.azsli Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.shader + Materials/Types/StandardMultilayerPBR_Displacement.lua Materials/Types/StandardMultilayerPBR_ForwardPass.azsl Materials/Types/StandardMultilayerPBR_ForwardPass.shader Materials/Types/StandardMultilayerPBR_ForwardPass_EDS.shader - Materials/Types/StandardMultilayerPBR_Parallax.lua - Materials/Types/StandardMultilayerPBR_ParallaxPerLayer.lua + Materials/Types/StandardMultilayerPBR_LayerEnable.lua Materials/Types/StandardMultilayerPBR_ShaderEnable.lua Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.shader diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessorInterface.h index 15b416597d..73ce175d99 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessorInterface.h @@ -14,6 +14,9 @@ #include #include +#include +#include +#include namespace AZ { @@ -23,6 +26,57 @@ namespace AZ using DiffuseProbeGridHandle = AZStd::shared_ptr; + enum class DiffuseProbeGridMode : uint8_t + { + RealTime, + Baked, + AutoSelect + }; + + enum class DiffuseProbeGridTextureNotificationType + { + None, + Ready, + Error + }; + + struct DiffuseProbeGridTexture + { + const AZStd::shared_ptr> m_data; + RHI::Format m_format; + RHI::Size m_size; + }; + + static const char* DiffuseProbeGridIrradianceFileName = "Irradiance_lutrgba16.dds"; + static const char* DiffuseProbeGridDistanceFileName = "Distance_lutrg32f.dds"; + static const char* DiffuseProbeGridRelocationFileName = "Relocation_lutrgba16f.dds"; + static const char* DiffuseProbeGridClassificationFileName = "Classification_lutr32f.dds"; + + using DiffuseProbeGridBakeTexturesCallback = AZStd::function; + + struct DiffuseProbeGridBakedTextures + { + // irradiance and distance images can be used directly + Data::Instance m_irradianceImage; + AZStd::string m_irradianceImageRelativePath; + + Data::Instance m_distanceImage; + AZStd::string m_distanceImageRelativePath; + + // relocation and classification images need to be recreated as RW textures + RHI::ImageDescriptor m_relocationImageDescriptor; + AZStd::array_view m_relocationImageData; + AZStd::string m_relocationImageRelativePath; + + RHI::ImageDescriptor m_classificationImageDescriptor; + AZStd::array_view m_classificationImageData; + AZStd::string m_classificationImageRelativePath; + }; + // DiffuseProbeGridFeatureProcessorInterface provides an interface to the feature processor for code outside of Atom class DiffuseProbeGridFeatureProcessorInterface : public RPI::FeatureProcessor @@ -44,6 +98,29 @@ namespace AZ virtual void Enable(const DiffuseProbeGridHandle& probeGrid, bool enable) = 0; virtual void SetGIShadows(const DiffuseProbeGridHandle& probeGrid, bool giShadows) = 0; virtual void SetUseDiffuseIbl(const DiffuseProbeGridHandle& probeGrid, bool useDiffuseIbl) = 0; + virtual void SetMode(const DiffuseProbeGridHandle& probeGrid, DiffuseProbeGridMode mode) = 0; + virtual void SetBakedTextures(const DiffuseProbeGridHandle& probeGrid, const DiffuseProbeGridBakedTextures& bakedTextures) = 0; + + virtual void BakeTextures( + const DiffuseProbeGridHandle& probeGrid, + DiffuseProbeGridBakeTexturesCallback callback, + const AZStd::string& irradianceTextureRelativePath, + const AZStd::string& distanceTextureRelativePath, + const AZStd::string& relocationTextureRelativePath, + const AZStd::string& classificationTextureRelativePath) = 0; + + // check for and retrieve a new baked texture asset (does not apply to hot-reloaded assets, only initial bakes) + virtual bool CheckTextureAssetNotification( + const AZStd::string& relativePath, + Data::Asset& outTextureAsset, + DiffuseProbeGridTextureNotificationType& outNotificationType) = 0; + + virtual bool AreBakedTexturesReferenced( + const AZStd::string& irradianceTextureRelativePath, + const AZStd::string& distanceTextureRelativePath, + const AZStd::string& relocationTextureRelativePath, + const AZStd::string& classificationTextureRelativePath) = 0; + }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/EditorRenderComponentAdapter.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/EditorRenderComponentAdapter.h index 101387205f..be761d8e7b 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/EditorRenderComponentAdapter.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/EditorRenderComponentAdapter.h @@ -1,14 +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. -* -*/ + * 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 @@ -26,14 +26,15 @@ namespace AZ , public AzToolsFramework::EditorEntityVisibilityNotificationBus::Handler { public: - using BaseClass = AzToolsFramework::Components::EditorComponentAdapter; - AZ_RTTI((EditorRenderComponentAdapter, "{AAF38BE4-EA2F-408B-9C44-63C7FBAC6B33}", TController, TRuntimeComponent, TConfiguration), BaseClass); + AZ_RTTI( + (EditorRenderComponentAdapter, "{AAF38BE4-EA2F-408B-9C44-63C7FBAC6B33}", TController, TRuntimeComponent, TConfiguration), + BaseClass); static void Reflect(AZ::ReflectContext* context); EditorRenderComponentAdapter() = default; - EditorRenderComponentAdapter(const TConfiguration& config); + explicit EditorRenderComponentAdapter(const TConfiguration& config); // AzToolsFramework::Components::EditorComponentAdapter overrides void Activate() override; @@ -50,7 +51,8 @@ namespace AZ // Convert pre-existing EditorCompnentAdapter based serialized data to EditorRenderComponentAdapter template - static bool ConvertToEditorRenderComponentAdapter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement); + static bool ConvertToEditorRenderComponentAdapter( + AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement); }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/EditorRenderComponentAdapter.inl b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/EditorRenderComponentAdapter.inl index e3f7ccd44d..633ec0e0ca 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/EditorRenderComponentAdapter.inl +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/EditorRenderComponentAdapter.inl @@ -1,14 +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. -* -*/ + * 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 @@ -19,11 +19,12 @@ namespace AZ { template template - bool EditorRenderComponentAdapter::ConvertToEditorRenderComponentAdapter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) + bool EditorRenderComponentAdapter::ConvertToEditorRenderComponentAdapter( + AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) { if (classElement.GetVersion() < TVersion) { - // Get the and remove the EditorComponentAdapter base class data that was previpously serialized + // Get the and remove the EditorComponentAdapter base class data that was previously serialized AzToolsFramework::Components::EditorComponentAdapter oldBaseClassData; if (!classElement.FindSubElementAndGetData(AZ_CRC("BaseClass1", 0xd4925735), oldBaseClassData)) @@ -41,8 +42,8 @@ namespace AZ // Replace the old base class data with EditorRenderComponentAdapter EditorRenderComponentAdapter newBaseClassData; - AZ::SerializeContext::DataElementNode& newBaseClassElement = classElement.GetSubElement( - classElement.AddElementWithData(context, "BaseClass1", newBaseClassData)); + AZ::SerializeContext::DataElementNode& newBaseClassElement = + classElement.GetSubElement(classElement.AddElementWithData(context, "BaseClass1", newBaseClassData)); // Overwrite EditorRenderComponentAdapter base class data with retrieved EditorComponentAdapter base class data if (!newBaseClassElement.RemoveElementByName(AZ_CRC("BaseClass1", 0xd4925735))) @@ -62,25 +63,24 @@ namespace AZ { BaseClass::Reflect(context); - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + if (auto serializeContext = azrtti_cast(context)) { - serializeContext->Class() - ->Version(0) - ; + serializeContext->Class()->Version(0); if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { - editContext->Class( - "EditorRenderComponentAdapter", "") + // clang-format off + editContext->Class("EditorRenderComponentAdapter", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ; + ->Attribute(AZ::Edit::Attributes::AutoExpand, true); + // clang-format on } } } template - EditorRenderComponentAdapter::EditorRenderComponentAdapter(const TConfiguration& config) + EditorRenderComponentAdapter::EditorRenderComponentAdapter( + const TConfiguration& config) : BaseClass(config) { } @@ -103,7 +103,8 @@ namespace AZ bool EditorRenderComponentAdapter::IsVisible() const { bool visible = true; - AzToolsFramework::EditorEntityInfoRequestBus::EventResult(visible, this->GetEntityId(), &AzToolsFramework::EditorEntityInfoRequestBus::Events::IsVisible); + AzToolsFramework::EditorEntityInfoRequestBus::EventResult( + visible, this->GetEntityId(), &AzToolsFramework::EditorEntityInfoRequestBus::Events::IsVisible); return visible; } @@ -114,15 +115,16 @@ namespace AZ } template - void EditorRenderComponentAdapter::OnEntityVisibilityChanged([[maybe_unused]] bool visibility) + void EditorRenderComponentAdapter::OnEntityVisibilityChanged( + [[maybe_unused]] bool visibility) { this->m_controller.Deactivate(); if (this->ShouldActivateController()) { - this->m_controller.Activate(this->GetEntityId()); + AzFramework::Components::ComponentActivateHelper::Activate( + this->m_controller, AZ::EntityComponentIdPair(this->GetEntityId(), this->GetId())); } } - } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp index 5be1303434..a55d8fc78c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,11 @@ namespace AZ { namespace Render { + DiffuseProbeGrid::DiffuseProbeGrid() + : m_textureReadback(this) + { + } + DiffuseProbeGrid::~DiffuseProbeGrid() { m_scene->GetCullingScene()->UnregisterCullable(m_cullable); @@ -166,6 +172,84 @@ namespace AZ m_updateRenderObjectSrg = true; } + void DiffuseProbeGrid::SetMode(DiffuseProbeGridMode mode) + { + // handle auto-select + if (mode == DiffuseProbeGridMode::AutoSelect) + { + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + m_mode = (device->GetFeatures().m_rayTracing) ? DiffuseProbeGridMode::RealTime : DiffuseProbeGridMode::Baked; + } + else + { + m_mode = mode; + } + + m_updateTextures = true; + } + + void DiffuseProbeGrid::SetBakedTextures(const DiffuseProbeGridBakedTextures& bakedTextures) + { + AZ_Assert(bakedTextures.m_irradianceImage.get(), "Invalid Irradiance image passed to SetBakedTextures"); + AZ_Assert(bakedTextures.m_distanceImage.get(), "Invalid Distance image passed to SetBakedTextures"); + AZ_Assert(bakedTextures.m_relocationImageData.size() > 0, "Invalid Relocation image data passed to SetBakedTextures"); + AZ_Assert(bakedTextures.m_classificationImageData.size() > 0, "Invalid Classification image data passed to SetBakedTextures"); + + m_bakedIrradianceImage = bakedTextures.m_irradianceImage; + m_bakedDistanceImage = bakedTextures.m_distanceImage; + + m_bakedIrradianceRelativePath = bakedTextures.m_irradianceImageRelativePath; + m_bakedDistanceRelativePath = bakedTextures.m_distanceImageRelativePath; + m_bakedRelocationRelativePath = bakedTextures.m_relocationImageRelativePath; + m_bakedClassificationRelativePath = bakedTextures.m_classificationImageRelativePath; + + m_bakedRelocationImageData.resize(bakedTextures.m_relocationImageData.size()); + memcpy(m_bakedRelocationImageData.data(), bakedTextures.m_relocationImageData.data(), bakedTextures.m_relocationImageData.size()); + + m_bakedClassificationImageData.resize(bakedTextures.m_classificationImageData.size()); + memcpy(m_bakedClassificationImageData.data(), bakedTextures.m_classificationImageData.data(), bakedTextures.m_classificationImageData.size()); + + // create the relocation and distance RW textures now, these are needed for shader compatibility + // (image data is copied in UpdateTextures) + { + m_bakedRelocationImage = RHI::Factory::Get().CreateImage(); + RHI::ImageInitRequest initRequest; + initRequest.m_image = m_bakedRelocationImage.get(); + initRequest.m_descriptor = RHI::ImageDescriptor::Create2D( + RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, + bakedTextures.m_relocationImageDescriptor.m_size.m_width, + bakedTextures.m_relocationImageDescriptor.m_size.m_height, + bakedTextures.m_relocationImageDescriptor.m_format); + + [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(initRequest); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize Relocation image"); + } + + { + m_bakedClassificationImage = RHI::Factory::Get().CreateImage(); + RHI::ImageInitRequest initRequest; + initRequest.m_image = m_bakedClassificationImage.get(); + initRequest.m_descriptor = RHI::ImageDescriptor::Create2D( + RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, + bakedTextures.m_classificationImageDescriptor.m_size.m_width, + bakedTextures.m_classificationImageDescriptor.m_size.m_height, + bakedTextures.m_classificationImageDescriptor.m_format); + + [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(initRequest); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize Classification image"); + } + + m_updateTextures = true; + } + + bool DiffuseProbeGrid::HasValidBakedTextures() const + { + return m_bakedIrradianceImage.get() && + m_bakedDistanceImage.get() && + m_bakedRelocationImage.get() && + m_bakedClassificationImage.get(); + } + uint32_t DiffuseProbeGrid::GetTotalProbeCount() const { return m_probeCountX * m_probeCountY * m_probeCountZ; @@ -188,83 +272,117 @@ namespace AZ RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); - // advance to the next image in the frame image array - m_currentImageIndex = (m_currentImageIndex + 1) % ImageFrameCount; - - // probe raytrace - { - uint32_t width = m_numRaysPerProbe; - uint32_t height = GetTotalProbeCount(); - - m_rayTraceImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage(); - - RHI::ImageInitRequest request; - request.m_image = m_rayTraceImage[m_currentImageIndex].get(); - request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, width, height, DiffuseProbeGridRenderData::RayTraceImageFormat); - [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); - AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeRayTraceImage image"); - } - uint32_t probeCountX; uint32_t probeCountY; GetTexture2DProbeCount(probeCountX, probeCountY); - // probe irradiance + if (m_mode == DiffuseProbeGridMode::RealTime) { - uint32_t width = probeCountX * (DefaultNumIrradianceTexels + 2); - uint32_t height = probeCountY * (DefaultNumIrradianceTexels + 2); + // advance to the next image in the frame image array + m_currentImageIndex = (m_currentImageIndex + 1) % ImageFrameCount; - m_irradianceImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage(); + // probe raytrace + { + uint32_t width = m_numRaysPerProbe; + uint32_t height = GetTotalProbeCount(); - RHI::ImageInitRequest request; - request.m_image = m_irradianceImage[m_currentImageIndex].get(); - request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, width, height, DiffuseProbeGridRenderData::IrradianceImageFormat); - RHI::ClearValue clearValue = RHI::ClearValue::CreateVector4Float(0.0f, 0.0f, 0.0f, 0.0f); - request.m_optimizedClearValue = &clearValue; - [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); - AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeIrradianceImage image"); + m_rayTraceImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage(); + + RHI::ImageInitRequest request; + request.m_image = m_rayTraceImage[m_currentImageIndex].get(); + request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, width, height, DiffuseProbeGridRenderData::RayTraceImageFormat); + [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeRayTraceImage image"); + } + + // probe irradiance + { + uint32_t width = probeCountX * (DefaultNumIrradianceTexels + 2); + uint32_t height = probeCountY * (DefaultNumIrradianceTexels + 2); + + m_irradianceImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage(); + + RHI::ImageInitRequest request; + request.m_image = m_irradianceImage[m_currentImageIndex].get(); + request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, width, height, DiffuseProbeGridRenderData::IrradianceImageFormat); + RHI::ClearValue clearValue = RHI::ClearValue::CreateVector4Float(0.0f, 0.0f, 0.0f, 0.0f); + request.m_optimizedClearValue = &clearValue; + [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeIrradianceImage image"); + } + + // probe distance + { + uint32_t width = probeCountX * (DefaultNumDistanceTexels + 2); + uint32_t height = probeCountY * (DefaultNumDistanceTexels + 2); + + m_distanceImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage(); + + RHI::ImageInitRequest request; + request.m_image = m_distanceImage[m_currentImageIndex].get(); + request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, width, height, DiffuseProbeGridRenderData::DistanceImageFormat); + [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeDistanceImage image"); + } + + // probe relocation + { + uint32_t width = probeCountX; + uint32_t height = probeCountY; + + m_relocationImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage(); + + RHI::ImageInitRequest request; + request.m_image = m_relocationImage[m_currentImageIndex].get(); + request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, width, height, DiffuseProbeGridRenderData::RelocationImageFormat); + [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeRelocationImage image"); + } + + // probe classification + { + uint32_t width = probeCountX; + uint32_t height = probeCountY; + + m_classificationImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage(); + + RHI::ImageInitRequest request; + request.m_image = m_classificationImage[m_currentImageIndex].get(); + request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, width, height, DiffuseProbeGridRenderData::ClassificationImageFormat); + [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeClassificationImage image"); + } } - - // probe distance + else if (m_mode == DiffuseProbeGridMode::Baked && HasValidBakedTextures()) { - uint32_t width = probeCountX * (DefaultNumDistanceTexels + 2); - uint32_t height = probeCountY * (DefaultNumDistanceTexels + 2); + // copy the baked relocation and classification texture data to the RW textures + // (these need to be RW for shader compatibility) + RHI::ImageSubresourceRange range{ 0, 0, 0 ,0 }; + RHI::ImageSubresourceLayoutPlaced layout; - m_distanceImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage(); + // relocation + { + m_bakedRelocationImage->GetSubresourceLayouts(range, &layout, nullptr); - RHI::ImageInitRequest request; - request.m_image = m_distanceImage[m_currentImageIndex].get(); - request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, width, height, DiffuseProbeGridRenderData::DistanceImageFormat); - [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); - AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeDistanceImage image"); - } + RHI::ImageUpdateRequest updateRequest; + updateRequest.m_image = m_bakedRelocationImage.get(); + updateRequest.m_sourceSubresourceLayout = layout; + updateRequest.m_sourceData = m_bakedRelocationImageData.data(); + updateRequest.m_imageSubresourcePixelOffset = RHI::Origin(0, 0, 0); + m_renderData->m_imagePool->UpdateImageContents(updateRequest); + } - // probe relocation - { - uint32_t width = probeCountX; - uint32_t height = probeCountY; + // classification + { + m_bakedClassificationImage->GetSubresourceLayouts(range, &layout, nullptr); - m_relocationImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage(); - - RHI::ImageInitRequest request; - request.m_image = m_relocationImage[m_currentImageIndex].get(); - request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, width, height, DiffuseProbeGridRenderData::RelocationImageFormat); - [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); - AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeRelocationImage image"); - } - - // probe classification - { - uint32_t width = probeCountX; - uint32_t height = probeCountY; - - m_classificationImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage(); - - RHI::ImageInitRequest request; - request.m_image = m_classificationImage[m_currentImageIndex].get(); - request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, width, height, DiffuseProbeGridRenderData::ClassificationImageFormat); - [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); - AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeClassificationImage image"); + RHI::ImageUpdateRequest updateRequest; + updateRequest.m_image = m_bakedClassificationImage.get(); + updateRequest.m_sourceSubresourceLayout = layout; + updateRequest.m_sourceData = m_bakedClassificationImageData.data(); + updateRequest.m_imageSubresourcePixelOffset = RHI::Origin(0, 0, 0); + m_renderData->m_imagePool->UpdateImageContents(updateRequest); + } } m_updateTextures = false; @@ -639,16 +757,16 @@ namespace AZ m_renderObjectSrg->SetConstant(constantIndex, m_ambientMultiplier); imageIndex = srgLayout->FindShaderInputImageIndex(Name("m_probeIrradiance")); - m_renderObjectSrg->SetImageView(imageIndex, m_irradianceImage[m_currentImageIndex]->GetImageView(m_renderData->m_probeIrradianceImageViewDescriptor).get()); + m_renderObjectSrg->SetImageView(imageIndex, GetIrradianceImage()->GetImageView(m_renderData->m_probeIrradianceImageViewDescriptor).get()); imageIndex = srgLayout->FindShaderInputImageIndex(Name("m_probeDistance")); - m_renderObjectSrg->SetImageView(imageIndex, m_distanceImage[m_currentImageIndex]->GetImageView(m_renderData->m_probeDistanceImageViewDescriptor).get()); + m_renderObjectSrg->SetImageView(imageIndex, GetDistanceImage()->GetImageView(m_renderData->m_probeDistanceImageViewDescriptor).get()); imageIndex = srgLayout->FindShaderInputImageIndex(Name("m_probeOffsets")); - m_renderObjectSrg->SetImageView(imageIndex, m_relocationImage[m_currentImageIndex]->GetImageView(m_renderData->m_probeRelocationImageViewDescriptor).get()); + m_renderObjectSrg->SetImageView(imageIndex, GetRelocationImage()->GetImageView(m_renderData->m_probeRelocationImageViewDescriptor).get()); imageIndex = srgLayout->FindShaderInputImageIndex(Name("m_probeStates")); - m_renderObjectSrg->SetImageView(imageIndex, m_classificationImage[m_currentImageIndex]->GetImageView(m_renderData->m_probeClassificationImageViewDescriptor).get()); + m_renderObjectSrg->SetImageView(imageIndex, GetClassificationImage()->GetImageView(m_renderData->m_probeClassificationImageViewDescriptor).get()); SetGridConstants(m_renderObjectSrg); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.h index e1ca2123a5..ff6ad719cf 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGrid.h @@ -17,6 +17,7 @@ #include #include #include +#include namespace AZ { @@ -26,11 +27,12 @@ namespace AZ struct DiffuseProbeGridRenderData { + // [GFX TODO][ATOM-15650] Change DiffuseProbeGrid Classification texture to R8_UINT static const RHI::Format RayTraceImageFormat = RHI::Format::R32G32B32A32_FLOAT; static const RHI::Format IrradianceImageFormat = RHI::Format::R16G16B16A16_UNORM; static const RHI::Format DistanceImageFormat = RHI::Format::R32G32_FLOAT; static const RHI::Format RelocationImageFormat = RHI::Format::R16G16B16A16_FLOAT; - static const RHI::Format ClassificationImageFormat = RHI::Format::R8_UINT; + static const RHI::Format ClassificationImageFormat = RHI::Format::R32_FLOAT; // image pool RHI::Ptr m_imagePool; @@ -61,7 +63,7 @@ namespace AZ class DiffuseProbeGrid final { public: - DiffuseProbeGrid() = default; + DiffuseProbeGrid(); ~DiffuseProbeGrid(); void Init(RPI::Scene* scene, DiffuseProbeGridRenderData* diffuseProbeGridRenderData); @@ -96,6 +98,9 @@ namespace AZ bool GetUseDiffuseIbl() const { return m_useDiffuseIbl; } void SetUseDiffuseIbl(bool useDiffuseIbl) { m_useDiffuseIbl = useDiffuseIbl; } + DiffuseProbeGridMode GetMode() const { return m_mode; } + void SetMode(DiffuseProbeGridMode mode); + uint32_t GetNumRaysPerProbe() const { return m_numRaysPerProbe; } uint32_t GetRemainingRelocationIterations() const { return aznumeric_cast(m_remainingRelocationIterations); } @@ -133,11 +138,16 @@ namespace AZ void UpdateRenderObjectSrg(); // textures - const RHI::Ptr& GetRayTraceImage() { return m_rayTraceImage[m_currentImageIndex]; } - const RHI::Ptr& GetIrradianceImage() { return m_irradianceImage[m_currentImageIndex]; } - const RHI::Ptr& GetDistanceImage() { return m_distanceImage[m_currentImageIndex]; } - const RHI::Ptr& GetRelocationImage() { return m_relocationImage[m_currentImageIndex]; } - const RHI::Ptr& GetClassificationImage() { return m_classificationImage[m_currentImageIndex]; } + const RHI::Ptr GetRayTraceImage() { return m_rayTraceImage[m_currentImageIndex]; } + const RHI::Ptr GetIrradianceImage() { return m_mode == DiffuseProbeGridMode::RealTime ? m_irradianceImage[m_currentImageIndex] : m_bakedIrradianceImage->GetRHIImage(); } + const RHI::Ptr GetDistanceImage() { return m_mode == DiffuseProbeGridMode::RealTime ? m_distanceImage[m_currentImageIndex] : m_bakedDistanceImage->GetRHIImage(); } + const RHI::Ptr GetRelocationImage() { return m_mode == DiffuseProbeGridMode::RealTime ? m_relocationImage[m_currentImageIndex] : m_bakedRelocationImage; } + const RHI::Ptr GetClassificationImage() { return m_mode == DiffuseProbeGridMode::RealTime ? m_classificationImage[m_currentImageIndex] : m_bakedClassificationImage; } + + const AZStd::string& GetBakedIrradianceRelativePath() const { return m_bakedIrradianceRelativePath; } + const AZStd::string& GetBakedDistanceRelativePath() const { return m_bakedDistanceRelativePath; } + const AZStd::string& GetBakedRelocationRelativePath() const { return m_bakedRelocationRelativePath; } + const AZStd::string& GetBakedClassificationRelativePath() const { return m_bakedClassificationRelativePath; } // attachment Ids const RHI::AttachmentId GetRayTraceImageAttachmentId() const { return m_rayTraceImageAttachmentId; } @@ -152,6 +162,12 @@ namespace AZ bool GetIrradianceClearRequired() const { return m_irradianceClearRequired; } void ResetIrradianceClearRequired() { m_irradianceClearRequired = false; } + // texture readback + DiffuseProbeGridTextureReadback& GetTextureReadback() { return m_textureReadback; } + + void SetBakedTextures(const DiffuseProbeGridBakedTextures& bakedTextures); + bool HasValidBakedTextures() const; + static constexpr uint32_t DefaultNumIrradianceTexels = 6; static constexpr uint32_t DefaultNumDistanceTexels = 14; static constexpr int32_t DefaultNumRelocationIterations = 100; @@ -221,7 +237,10 @@ namespace AZ // culling RPI::Cullable m_cullable; - // textures + // grid mode (RealTime or Baked) + DiffuseProbeGridMode m_mode = DiffuseProbeGridMode::RealTime; + + // real-time textures static const uint32_t MaxTextureDimension = 8192; static const uint32_t ImageFrameCount = 3; RHI::Ptr m_rayTraceImage[ImageFrameCount]; @@ -233,6 +252,25 @@ namespace AZ bool m_updateTextures = false; bool m_irradianceClearRequired = true; + // baked textures + Data::Instance m_bakedIrradianceImage; + Data::Instance m_bakedDistanceImage; + RHI::Ptr m_bakedRelocationImage; + RHI::Ptr m_bakedClassificationImage; + + // baked texture relative paths + AZStd::string m_bakedIrradianceRelativePath; + AZStd::string m_bakedDistanceRelativePath; + AZStd::string m_bakedRelocationRelativePath; + AZStd::string m_bakedClassificationRelativePath; + + // baked texture data (only needed for the relocation and classification textures) + AZStd::vector m_bakedRelocationImageData; + AZStd::vector m_bakedClassificationImageData; + + // texture readback + DiffuseProbeGridTextureReadback m_textureReadback; + // Srgs Data::Instance m_rayTraceSrg; Data::Instance m_blendIrradianceSrg; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridBlendDistancePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridBlendDistancePass.cpp index 3df13556d3..2a06dacf3f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridBlendDistancePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridBlendDistancePass.cpp @@ -87,7 +87,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty()) + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().empty()) { // no diffuse probe grids return; @@ -111,7 +111,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { // probe raytrace image { @@ -150,7 +150,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs // (see ValidateSetImageView() in ShaderResourceGroupData.cpp) @@ -167,7 +167,7 @@ namespace AZ DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); // submit the DispatchItem for each DiffuseProbeGrid - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetBlendDistanceSrg()->GetRHIShaderResourceGroup(); commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridBlendIrradiancePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridBlendIrradiancePass.cpp index 4e05b8ef31..4818018ea3 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridBlendIrradiancePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridBlendIrradiancePass.cpp @@ -87,7 +87,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty()) + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().empty()) { // no diffuse probe grids return; @@ -111,7 +111,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { // probe raytrace image { @@ -150,7 +150,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs // (see ValidateSetImageView() in ShaderResourceGroupData.cpp) @@ -167,7 +167,7 @@ namespace AZ DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); // submit the DispatchItem for each DiffuseProbeGrid - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetBlendIrradianceSrg()->GetRHIShaderResourceGroup(); commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridBorderUpdatePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridBorderUpdatePass.cpp index 59549de331..8821de8a9d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridBorderUpdatePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridBorderUpdatePass.cpp @@ -100,7 +100,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty()) + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().empty()) { // no diffuse probe grids return; @@ -124,7 +124,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { // probe irradiance image { @@ -153,7 +153,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs // (see line ValidateSetImageView() in ShaderResourceGroupData.cpp) @@ -173,7 +173,7 @@ namespace AZ DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); // submit the DispatchItems for each DiffuseProbeGrid - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { uint32_t probeCountX; uint32_t probeCountY; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridClassificationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridClassificationPass.cpp index db85914cee..65f1c2dd5a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridClassificationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridClassificationPass.cpp @@ -91,7 +91,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty()) + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().empty()) { // no diffuse probe grids return; @@ -115,7 +115,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { // probe raytrace image { @@ -143,7 +143,7 @@ namespace AZ { RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs // (see ValidateSetImageView() in ShaderResourceGroupData.cpp) @@ -159,7 +159,7 @@ namespace AZ DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); // submit the DispatchItems for each DiffuseProbeGrid - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetClassificationSrg()->GetRHIShaderResourceGroup(); commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessor.cpp index 1aaa06c797..060d51d1d0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessor.cpp @@ -45,6 +45,7 @@ namespace AZ RHI::RHISystemInterface* rhiSystem = RHI::RHISystemInterface::Get(); m_diffuseProbeGrids.reserve(InitialProbeGridAllocationSize); + m_realTimeDiffuseProbeGrids.reserve(InitialProbeGridAllocationSize); RHI::BufferPoolDescriptor desc; desc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device; @@ -61,7 +62,7 @@ namespace AZ // image pool { RHI::ImagePoolDescriptor imagePoolDesc; - imagePoolDesc.m_bindFlags = RHI::ImageBindFlags::ShaderReadWrite; + imagePoolDesc.m_bindFlags = RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead; m_probeGridRenderData.m_imagePool = RHI::Factory::Get().CreateImagePool(); [[maybe_unused]] RHI::ResultCode result = m_probeGridRenderData.m_imagePool->Init(*rhiSystem->GetDevice(), imagePoolDesc); @@ -123,6 +124,32 @@ namespace AZ m_needUpdatePipelineStates = false; } + // check pending textures and connect bus for notifications + for (auto& notificationEntry : m_notifyTextureAssets) + { + if (notificationEntry.m_assetId.IsValid()) + { + // asset already has an assetId + continue; + } + + // query for the assetId + AZ::Data::AssetId assetId; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + assetId, + &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, + notificationEntry.m_relativePath.c_str(), + azrtti_typeid(), + false); + + if (assetId.IsValid()) + { + notificationEntry.m_assetId = assetId; + notificationEntry.m_asset.Create(assetId, true); + Data::AssetBus::MultiHandler::BusConnect(assetId); + } + } + // if the volumes changed we need to re-sort the probe list if (m_probeGridSortRequired) { @@ -139,6 +166,7 @@ namespace AZ }; AZStd::sort(m_diffuseProbeGrids.begin(), m_diffuseProbeGrids.end(), sortFn); + AZStd::sort(m_realTimeDiffuseProbeGrids.begin(), m_realTimeDiffuseProbeGrids.end(), sortFn); m_probeGridSortRequired = false; } @@ -160,6 +188,9 @@ namespace AZ diffuseProbeGrid->SetExtents(extents); diffuseProbeGrid->SetProbeSpacing(probeSpacing); m_diffuseProbeGrids.push_back(diffuseProbeGrid); + + UpdateRealTimeList(diffuseProbeGrid); + m_probeGridSortRequired = true; return diffuseProbeGrid; @@ -169,6 +200,7 @@ namespace AZ { AZ_Assert(probeGrid.get(), "RemoveProbeGrid called with an invalid handle"); + // remove from main list auto itEntry = AZStd::find_if(m_diffuseProbeGrids.begin(), m_diffuseProbeGrids.end(), [&](AZStd::shared_ptr const& entry) { return (entry == probeGrid); @@ -176,6 +208,18 @@ namespace AZ AZ_Assert(itEntry != m_diffuseProbeGrids.end(), "RemoveProbeGrid called with a probe grid that is not in the probe list"); m_diffuseProbeGrids.erase(itEntry); + + // remove from side list of real-time grids + itEntry = AZStd::find_if(m_realTimeDiffuseProbeGrids.begin(), m_realTimeDiffuseProbeGrids.end(), [&](AZStd::shared_ptr const& entry) + { + return (entry == probeGrid); + }); + + if (itEntry != m_realTimeDiffuseProbeGrids.end()) + { + m_realTimeDiffuseProbeGrids.erase(itEntry); + } + probeGrid = nullptr; } @@ -247,6 +291,134 @@ namespace AZ probeGrid->SetUseDiffuseIbl(useDiffuseIbl); } + void DiffuseProbeGridFeatureProcessor::BakeTextures( + const DiffuseProbeGridHandle& probeGrid, + DiffuseProbeGridBakeTexturesCallback callback, + const AZStd::string& irradianceTextureRelativePath, + const AZStd::string& distanceTextureRelativePath, + const AZStd::string& relocationTextureRelativePath, + const AZStd::string& classificationTextureRelativePath) + { + AZ_Assert(probeGrid.get(), "BakeTextures called with an invalid handle"); + + AddNotificationEntry(irradianceTextureRelativePath); + AddNotificationEntry(distanceTextureRelativePath); + AddNotificationEntry(relocationTextureRelativePath); + AddNotificationEntry(classificationTextureRelativePath); + + probeGrid->GetTextureReadback().BeginTextureReadback(callback); + } + + void DiffuseProbeGridFeatureProcessor::UpdateRealTimeList(const DiffuseProbeGridHandle& diffuseProbeGrid) + { + if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::RealTime) + { + // add to side list of real-time grids + auto itEntry = AZStd::find_if(m_realTimeDiffuseProbeGrids.begin(), m_realTimeDiffuseProbeGrids.end(), [&](AZStd::shared_ptr const& entry) + { + return (entry == diffuseProbeGrid); + }); + + if (itEntry == m_realTimeDiffuseProbeGrids.end()) + { + m_realTimeDiffuseProbeGrids.push_back(diffuseProbeGrid); + } + } + else + { + // remove from side list of real-time grids + auto itEntry = AZStd::find_if(m_realTimeDiffuseProbeGrids.begin(), m_realTimeDiffuseProbeGrids.end(), [&](AZStd::shared_ptr const& entry) + { + return (entry == diffuseProbeGrid); + }); + + if (itEntry != m_realTimeDiffuseProbeGrids.end()) + { + m_realTimeDiffuseProbeGrids.erase(itEntry); + } + } + } + + void DiffuseProbeGridFeatureProcessor::AddNotificationEntry(const AZStd::string& relativePath) + { + AZStd::string assetPath = relativePath + ".streamingimage"; + + // check to see if this is an existing asset + AZ::Data::AssetId assetId; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + assetId, + &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, + assetPath.c_str(), + azrtti_typeid(), + false); + + // We only track notifications for new texture assets, meaning assets that are created the first time a DiffuseProbeGrid is baked. + // On subsequent bakes the existing assets are automatically reloaded by the RPI since they are already known by the asset system. + if (!assetId.IsValid()) + { + m_notifyTextureAssets.push_back({ assetPath, assetId }); + } + } + + bool DiffuseProbeGridFeatureProcessor::CheckTextureAssetNotification( + const AZStd::string& relativePath, + Data::Asset& outTextureAsset, + DiffuseProbeGridTextureNotificationType& outNotificationType) + { + for (NotifyTextureAssetVector::iterator itNotification = m_notifyTextureAssets.begin(); itNotification != m_notifyTextureAssets.end(); ++itNotification) + { + if (itNotification->m_relativePath == relativePath) + { + outNotificationType = itNotification->m_notificationType; + if (outNotificationType != DiffuseProbeGridTextureNotificationType::None) + { + outTextureAsset = itNotification->m_asset; + m_notifyTextureAssets.erase(itNotification); + } + + return true; + } + } + + return false; + } + + bool DiffuseProbeGridFeatureProcessor::AreBakedTexturesReferenced( + const AZStd::string& irradianceTextureRelativePath, + const AZStd::string& distanceTextureRelativePath, + const AZStd::string& relocationTextureRelativePath, + const AZStd::string& classificationTextureRelativePath) + { + for (auto& diffuseProbeGrid : m_diffuseProbeGrids) + { + if ((diffuseProbeGrid->GetBakedIrradianceRelativePath() == irradianceTextureRelativePath) || + (diffuseProbeGrid->GetBakedDistanceRelativePath() == distanceTextureRelativePath) || + (diffuseProbeGrid->GetBakedRelocationRelativePath() == relocationTextureRelativePath) || + (diffuseProbeGrid->GetBakedClassificationRelativePath() == classificationTextureRelativePath)) + { + return true; + } + } + + return false; + } + + void DiffuseProbeGridFeatureProcessor::SetMode(const DiffuseProbeGridHandle& probeGrid, DiffuseProbeGridMode mode) + { + AZ_Assert(probeGrid.get(), "SetMode called with an invalid handle"); + probeGrid->SetMode(mode); + + UpdateRealTimeList(probeGrid); + + m_probeGridSortRequired = true; + } + + void DiffuseProbeGridFeatureProcessor::SetBakedTextures(const DiffuseProbeGridHandle& probeGrid, const DiffuseProbeGridBakedTextures& bakedTextures) + { + AZ_Assert(probeGrid.get(), "SetBakedTextures called with an invalid handle"); + probeGrid->SetBakedTextures(bakedTextures); + } + void DiffuseProbeGridFeatureProcessor::CreateBoxMesh() { // vertex positions @@ -418,5 +590,34 @@ namespace AZ } } + void DiffuseProbeGridFeatureProcessor::HandleAssetNotification(Data::Asset asset, DiffuseProbeGridTextureNotificationType notificationType) + { + for (NotifyTextureAssetVector::iterator itNotification = m_notifyTextureAssets.begin(); itNotification != m_notifyTextureAssets.end(); ++itNotification) + { + if (itNotification->m_assetId == asset.GetId()) + { + // store the texture asset + itNotification->m_asset = Data::static_pointer_cast(asset); + itNotification->m_notificationType = notificationType; + + // stop notifications on this asset + Data::AssetBus::MultiHandler::BusDisconnect(itNotification->m_assetId); + + break; + } + } + } + + void DiffuseProbeGridFeatureProcessor::OnAssetReady(Data::Asset asset) + { + HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Ready); + } + + void DiffuseProbeGridFeatureProcessor::OnAssetError(Data::Asset asset) + { + AZ_Error("ReflectionProbeFeatureProcessor", false, "Failed to load cubemap [%s]", asset.GetHint().c_str()); + + HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Error); + } } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessor.h index ad36f8aafa..19e9bf1b1d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessor.h @@ -22,6 +22,7 @@ namespace AZ //! This class manages DiffuseProbeGrids which generate diffuse global illumination class DiffuseProbeGridFeatureProcessor final : public DiffuseProbeGridFeatureProcessorInterface + , private Data::AssetBus::MultiHandler { public: AZ_RTTI(AZ::Render::DiffuseProbeGridFeatureProcessor, "{BCD232F9-1EBF-4D0D-A5F4-84AEC933A93C}", DiffuseProbeGridFeatureProcessorInterface); @@ -46,6 +47,27 @@ namespace AZ void Enable(const DiffuseProbeGridHandle& probeGrid, bool enable) override; void SetGIShadows(const DiffuseProbeGridHandle& probeGrid, bool giShadows) override; void SetUseDiffuseIbl(const DiffuseProbeGridHandle& probeGrid, bool useDiffuseIbl) override; + void SetMode(const DiffuseProbeGridHandle& probeGrid, DiffuseProbeGridMode mode) override; + void SetBakedTextures(const DiffuseProbeGridHandle& probeGrid, const DiffuseProbeGridBakedTextures& bakedTextures) override; + + void BakeTextures( + const DiffuseProbeGridHandle& probeGrid, + DiffuseProbeGridBakeTexturesCallback callback, + const AZStd::string& irradianceTextureRelativePath, + const AZStd::string& distanceTextureRelativePath, + const AZStd::string& relocationTextureRelativePath, + const AZStd::string& classificationTextureRelativePath) override; + + bool CheckTextureAssetNotification( + const AZStd::string& relativePath, + Data::Asset& outTextureAsset, + DiffuseProbeGridTextureNotificationType& outNotificationType) override; + + bool AreBakedTexturesReferenced( + const AZStd::string& irradianceTextureRelativePath, + const AZStd::string& distanceTextureRelativePath, + const AZStd::string& relocationTextureRelativePath, + const AZStd::string& classificationTextureRelativePath) override; // FeatureProcessor overrides void Activate() override; @@ -56,12 +78,28 @@ namespace AZ using DiffuseProbeGridVector = AZStd::vector>; DiffuseProbeGridVector& GetProbeGrids() { return m_diffuseProbeGrids; } + // retrieve the side list of probe grids that are using real-time (raytraced) mode + DiffuseProbeGridVector& GetRealTimeProbeGrids() { return m_realTimeDiffuseProbeGrids; } + private: AZ_DISABLE_COPY_MOVE(DiffuseProbeGridFeatureProcessor); // create the box vertex and index streams, which are used to render the probe volumes void CreateBoxMesh(); + // AssetBus::MultiHandler overrides... + void OnAssetReady(Data::Asset asset) override; + void OnAssetError(Data::Asset asset) override; + + // updates the real-time list for a specific probe grid + void UpdateRealTimeList(const DiffuseProbeGridHandle& diffuseProbeGrid); + + // adds a notification entry for a new asset + void AddNotificationEntry(const AZStd::string& relativePath); + + // notifies and removes the notification entry + void HandleAssetNotification(Data::Asset asset, DiffuseProbeGridTextureNotificationType notificationType); + // RPI::SceneNotificationBus::Handler overrides void OnRenderPipelinePassesChanged(RPI::RenderPipeline* renderPipeline) override; void OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline) override; @@ -70,10 +108,13 @@ namespace AZ void UpdatePipelineStates(); void UpdatePasses(); - // list of diffuse probe grids + // list of all diffuse probe grids const size_t InitialProbeGridAllocationSize = 64; DiffuseProbeGridVector m_diffuseProbeGrids; + // side list of diffuse probe grids that are in real-time mode (subset of m_diffuseProbeGrids) + DiffuseProbeGridVector m_realTimeDiffuseProbeGrids; + // position structure for the box vertices struct Position { @@ -102,6 +143,17 @@ namespace AZ // indicates the the diffuse probe grid render pipeline state needs to be updated bool m_needUpdatePipelineStates = false; + + // list of texture assets that we need to check during Simulate() to see if they are ready + struct NotifyTextureAssetEntry + { + AZStd::string m_relativePath; + AZ::Data::AssetId m_assetId; + Data::Asset m_asset; + DiffuseProbeGridTextureNotificationType m_notificationType = DiffuseProbeGridTextureNotificationType::None; + }; + typedef AZStd::vector NotifyTextureAssetVector; + NotifyTextureAssetVector m_notifyTextureAssets; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp index b2b5f60660..65d71b8272 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp @@ -136,7 +136,7 @@ namespace AZ } DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty()) + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().empty()) { // no diffuse probe grids return; @@ -153,9 +153,9 @@ namespace AZ DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); - frameGraph.SetEstimatedItemCount(aznumeric_cast(diffuseProbeGridFeatureProcessor->GetProbeGrids().size())); + frameGraph.SetEstimatedItemCount(aznumeric_cast(diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().size())); - for (const auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (const auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { // TLAS { @@ -260,7 +260,7 @@ namespace AZ rayTracingFeatureProcessor->GetMeshInfoBuffer() && rayTracingFeatureProcessor->GetSubMeshCount()) { - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader // inputs (see line ValidateSetImageView() in ShaderResourceGroupData.cpp) @@ -308,7 +308,7 @@ namespace AZ m_rayTracingShaderTable) { // submit the DispatchRaysItem for each DiffuseProbeGrid - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { const RHI::ShaderResourceGroup* shaderResourceGroups[] = { diffuseProbeGrid->GetRayTraceSrg()->GetRHIShaderResourceGroup(), diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRelocationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRelocationPass.cpp index 2bd6595b71..86a26f002d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRelocationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRelocationPass.cpp @@ -91,7 +91,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty()) + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().empty()) { // no diffuse probe grids return; @@ -108,7 +108,7 @@ namespace AZ // create the Relocation Srgs for each DiffuseProbeGrid, and check to see if any grids need relocation bool needRelocation = false; - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { uint32_t rayTracingDataRevision = rayTracingFeatureProcessor->GetRevision(); if (rayTracingDataRevision != m_rayTracingDataRevision) @@ -139,7 +139,7 @@ namespace AZ RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { // probe raytrace image { @@ -167,7 +167,7 @@ namespace AZ { RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs // (see ValidateSetImageView() in ShaderResourceGroupData.cpp) @@ -187,7 +187,7 @@ namespace AZ DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); // submit the DispatchItems for each DiffuseProbeGrid - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) { const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetRelocationSrg()->GetRHIShaderResourceGroup(); commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRenderPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRenderPass.cpp index af6fce6f6a..4f9221a65f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRenderPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRenderPass.cpp @@ -79,6 +79,12 @@ namespace AZ params.m_scissorState = scissor; Base::FrameBeginInternal(params); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids()) + { + // process attachment readback + diffuseProbeGrid->GetTextureReadback().FrameBegin(params); + } } void DiffuseProbeGridRenderPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) @@ -88,8 +94,21 @@ namespace AZ for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) { + if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked && + !diffuseProbeGrid->HasValidBakedTextures()) + { + continue; + } + // probe irradiance image { + if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked) + { + // import the irradiance image now, since it is baked and therefore was not imported during the raytracing pass + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(diffuseProbeGrid->GetIrradianceImageAttachmentId(), diffuseProbeGrid->GetIrradianceImage()); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import probeIrradianceImage"); + } + RHI::ImageScopeAttachmentDescriptor desc; desc.m_attachmentId = diffuseProbeGrid->GetIrradianceImageAttachmentId(); desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeIrradianceImageViewDescriptor; @@ -100,6 +119,13 @@ namespace AZ // probe distance image { + if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked) + { + // import the distance image now, since it is baked and therefore was not imported during the raytracing pass + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(diffuseProbeGrid->GetDistanceImageAttachmentId(), diffuseProbeGrid->GetDistanceImage()); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import probeDistanceImage"); + } + RHI::ImageScopeAttachmentDescriptor desc; desc.m_attachmentId = diffuseProbeGrid->GetDistanceImageAttachmentId(); desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDistanceImageViewDescriptor; @@ -110,6 +136,13 @@ namespace AZ // probe relocation image { + if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked) + { + // import the relocation image now, since it is baked and therefore was not imported during the raytracing pass + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(diffuseProbeGrid->GetRelocationImageAttachmentId(), diffuseProbeGrid->GetRelocationImage()); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import probeRelocationImage"); + } + RHI::ImageScopeAttachmentDescriptor desc; desc.m_attachmentId = diffuseProbeGrid->GetRelocationImageAttachmentId(); desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeRelocationImageViewDescriptor; @@ -120,6 +153,13 @@ namespace AZ // probe classification image { + if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked) + { + // import the classification image now, since it is baked and therefore was not imported during the raytracing pass + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(diffuseProbeGrid->GetClassificationImageAttachmentId(), diffuseProbeGrid->GetClassificationImage()); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import probeClassificationImage"); + } + RHI::ImageScopeAttachmentDescriptor desc; desc.m_attachmentId = diffuseProbeGrid->GetClassificationImageAttachmentId(); desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeClassificationImageViewDescriptor; @@ -127,6 +167,8 @@ namespace AZ frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite); } + + diffuseProbeGrid->GetTextureReadback().Update(GetName()); } Base::SetupFrameGraphDependencies(frameGraph); @@ -139,6 +181,12 @@ namespace AZ for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids()) { + if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked && + !diffuseProbeGrid->HasValidBakedTextures()) + { + continue; + } + // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs // (see ValidateSetImageView() of ShaderResourceGroupData.cpp) diffuseProbeGrid->UpdateRenderObjectSrg(); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridTextureReadback.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridTextureReadback.cpp new file mode 100644 index 0000000000..bc619cc277 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridTextureReadback.cpp @@ -0,0 +1,134 @@ +/* +* 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 + +namespace AZ +{ + namespace Render + { + DiffuseProbeGridTextureReadback::DiffuseProbeGridTextureReadback(DiffuseProbeGrid* diffuseProbeGrid) + : m_diffuseProbeGrid(diffuseProbeGrid) + { + } + + void DiffuseProbeGridTextureReadback::BeginTextureReadback(DiffuseProbeGridBakeTexturesCallback callback) + { + AZ_Assert(m_readbackState == DiffuseProbeGridReadbackState::Idle, "DiffuseProbeGridTextureReadback is already processing a readback request"); + + m_callback = callback; + m_readbackState = DiffuseProbeGridReadbackState::Irradiance; + } + + void DiffuseProbeGridTextureReadback::Update(const AZ::Name& passName) + { + if (m_readbackState == DiffuseProbeGridReadbackState::Idle || m_readbackState == DiffuseProbeGridReadbackState::Complete) + { + return; + } + + if (m_attachmentReadback.get() && m_attachmentReadback->GetReadbackState() > RPI::AttachmentReadback::ReadbackState::Idle) + { + // still processing previous request + return; + } + + AZStd::string readbackName = AZStd::string::format("DiffuseProbeGridReadback_%s", passName.GetCStr()); + RHI::ImageDescriptor descriptor; + RHI::AttachmentId attachmentId; + RPI::AttachmentReadback::CallbackFunction callbackFunction; + + switch (m_readbackState) + { + case DiffuseProbeGridReadbackState::Irradiance: + descriptor = m_diffuseProbeGrid->GetIrradianceImage()->GetDescriptor(); + attachmentId = m_diffuseProbeGrid->GetIrradianceImageAttachmentId(); + callbackFunction = [this](const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult) + { + m_irradianceReadbackResult = readbackResult; + m_readbackState = DiffuseProbeGridReadbackState::Distance; + }; + break; + case DiffuseProbeGridReadbackState::Distance: + descriptor = m_diffuseProbeGrid->GetDistanceImage()->GetDescriptor(); + attachmentId = m_diffuseProbeGrid->GetDistanceImageAttachmentId(); + callbackFunction = [this](const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult) + { + m_distanceReadbackResult = readbackResult; + m_readbackState = DiffuseProbeGridReadbackState::Relocation; + }; + break; + case DiffuseProbeGridReadbackState::Relocation: + descriptor = m_diffuseProbeGrid->GetRelocationImage()->GetDescriptor(); + attachmentId = m_diffuseProbeGrid->GetRelocationImageAttachmentId(); + callbackFunction = [this](const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult) + { + m_relocationReadbackResult = readbackResult; + m_readbackState = DiffuseProbeGridReadbackState::Classification; + }; + break; + case DiffuseProbeGridReadbackState::Classification: + descriptor = m_diffuseProbeGrid->GetClassificationImage()->GetDescriptor(); + attachmentId = m_diffuseProbeGrid->GetClassificationImageAttachmentId(); + callbackFunction = [this](const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult) + { + m_classificationReadbackResult = readbackResult; + m_readbackState = DiffuseProbeGridReadbackState::Complete; + }; + break; + default: + AZ_Assert(false, "Unknown readback state"); + } + + m_attachmentReadback = AZStd::make_shared(AZ::RHI::ScopeId{ "DiffuseProbeGridTextureReadBack" }); + m_attachmentReadback->SetCallback(callbackFunction); + + AZ::RPI::PassAttachment passAttachment; + passAttachment.m_descriptor = descriptor; + passAttachment.m_path = attachmentId; + passAttachment.m_name = readbackName; + passAttachment.m_lifetime = RHI::AttachmentLifetimeType::Imported; + + m_attachmentReadback->ReadPassAttachment(&passAttachment, AZ::Name(readbackName)); + } + + void DiffuseProbeGridTextureReadback::FrameBegin(AZ::RPI::Pass::FramePrepareParams& params) + { + if (m_readbackState == DiffuseProbeGridReadbackState::Idle) + { + return; + } + + if (!m_attachmentReadback.get()) + { + return; + } + + if (m_readbackState == DiffuseProbeGridReadbackState::Complete) + { + // readback of all textures is complete, invoke callback and return to Idle state + m_callback( + { m_irradianceReadbackResult.m_dataBuffer, m_irradianceReadbackResult.m_imageDescriptor.m_format, m_irradianceReadbackResult.m_imageDescriptor.m_size }, + { m_distanceReadbackResult.m_dataBuffer, m_distanceReadbackResult.m_imageDescriptor.m_format, m_distanceReadbackResult.m_imageDescriptor.m_size }, + { m_relocationReadbackResult.m_dataBuffer, m_relocationReadbackResult.m_imageDescriptor.m_format, m_relocationReadbackResult.m_imageDescriptor.m_size }, + { m_classificationReadbackResult.m_dataBuffer, m_classificationReadbackResult.m_imageDescriptor.m_format, m_classificationReadbackResult.m_imageDescriptor.m_size }); + + m_readbackState = DiffuseProbeGridReadbackState::Idle; + m_attachmentReadback.reset(); + return; + } + + m_attachmentReadback->FrameBegin(params); + } + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridTextureReadback.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridTextureReadback.h new file mode 100644 index 0000000000..1becd6fb3e --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridTextureReadback.h @@ -0,0 +1,60 @@ +/* +* 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 AZ +{ + namespace Render + { + class DiffuseProbeGrid; + + enum class DiffuseProbeGridReadbackState + { + Idle, + Irradiance, + Distance, + Relocation, + Classification, + Complete + }; + + //! This class contains functionality necessary to read back the DiffuseProbeGrid textures, which + //! allows them to be saved as assets to run the DiffuseProbeGrid in non-realtime mode. + class DiffuseProbeGridTextureReadback final + { + public: + DiffuseProbeGridTextureReadback(DiffuseProbeGrid* diffuseProbeGrid); + ~DiffuseProbeGridTextureReadback() = default; + + void BeginTextureReadback(DiffuseProbeGridBakeTexturesCallback callback); + void Update(const AZ::Name& passName); + void FrameBegin(AZ::RPI::Pass::FramePrepareParams& params); + + private: + + DiffuseProbeGrid* m_diffuseProbeGrid = nullptr; + DiffuseProbeGridReadbackState m_readbackState = DiffuseProbeGridReadbackState::Idle; + AZStd::shared_ptr m_attachmentReadback; + DiffuseProbeGridBakeTexturesCallback m_callback; + + AZ::RPI::AttachmentReadback::ReadbackResult m_irradianceReadbackResult; + AZ::RPI::AttachmentReadback::ReadbackResult m_distanceReadbackResult; + AZ::RPI::AttachmentReadback::ReadbackResult m_relocationReadbackResult; + AZ::RPI::AttachmentReadback::ReadbackResult m_classificationReadbackResult; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 4059d65cbb..117b177f05 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -741,7 +741,7 @@ namespace AZ // retrieve vertex/index buffers RPI::ModelLod::StreamBufferViewList streamBufferViews; - [[maybe_unused]] bool result = modelLod->GetStreamsForMesh(inputStreamLayout, streamBufferViews, shaderInputContract, meshIndex); + [[maybe_unused]] bool result = modelLod->GetStreamsForMesh(inputStreamLayout, streamBufferViews, nullptr, shaderInputContract, meshIndex); AZ_Assert(result, "Failed to retrieve mesh stream buffer views"); // note that the element count is the size of the entire buffer, even though this mesh may only diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake index 8926b0c19f..46a4e06ac2 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -135,6 +135,8 @@ set(FILES Source/DiffuseProbeGrid/DiffuseProbeGridRenderPass.h Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp Source/DiffuseProbeGrid/DiffuseProbeGrid.h + Source/DiffuseProbeGrid/DiffuseProbeGridTextureReadback.cpp + Source/DiffuseProbeGrid/DiffuseProbeGridTextureReadback.h Source/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessor.h Source/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessor.cpp Source/DisplayMapper/AcesOutputTransformPass.cpp diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Edit/ShaderCompilerArguments.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Edit/ShaderCompilerArguments.h index 2073c48d25..a5d8f53573 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Edit/ShaderCompilerArguments.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Edit/ShaderCompilerArguments.h @@ -13,6 +13,8 @@ #include #include +#include +#include namespace AZ { @@ -30,9 +32,16 @@ namespace AZ static void Reflect(ReflectContext* context); + //! Returns true if either @m_azslcAdditionalFreeArguments or @m_dxcAdditionalFreeArguments contain + //! macro definitions, e.g. "-D MACRO" or "-D MACRO=VALUE" or "-DMACRO", "-DMACRO=VALUE". + //! It is used for validation to forbid macro definitions, because the idea is that this struct + //! is used inside GlobalBuildOptions which has a dedicated variable for macro definitions. + bool HasMacroDefinitionsInCommandLineArguments(); + //! Mix two instances of arguments, by or-ing bools, or by "if different, right hand side wins" void Merge(const ShaderCompilerArguments& right); + //! [GFX TODO] [ATOM-15472] Remove this function. //! Determine whether there is a rebuild-worthy difference in arguments for AZSLc bool HasDifferentAzslcArguments(const ShaderCompilerArguments& right) const; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Edit/Utils.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Edit/Utils.h index 3e593794af..6f884eb358 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Edit/Utils.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Edit/Utils.h @@ -110,6 +110,46 @@ namespace AZ AZStd::string BuildFileNameWithExtension(const AZStd::string& shaderSourceFile, const AZStd::string& tempFolder, const char* outputExtension); + + namespace CommandLineArgumentUtils + { + //! @param commandLineString: A string with command line arguments of the form: + //! "- -- --[=] ..." + //! Example: "--use-spaces --namespace=vk -W1" + //! Returns: A list with just the [-|--]: + //! ["-", "--", "--arg3"] + //! For the example shown above it will return this vector: + //! ["--use-spaces", "--namespace", "-W1] + AZStd::vector GetListOfArgumentNames(AZStd::string_view commandLineString); + + //! Takes a list of names of command line arguments and removes those arguments from @commandLineString. + //! The core functionality of this function is that it searches by name in @commandLineString and removes + //! name and value if the name is found. + //! @param listOfArguments: This is a list of strings, usually generated by the helper function + //! ShaderCompilerArguments::GetListOfArgumentNames() + //! @param commandLineString: A single string made of several command line arguments + //! @returns A new string based on @commandLineString but with the matching arguments and their values + //! removed from it. + AZStd::string RemoveArgumentsFromCommandLineString( + AZStd::array_view listOfArguments, AZStd::string_view commandLineString); + + //! @param commandLineString: " --arg1 -arg2 --arg3=foo --arg4=bar " + //! @returns "--arg1 -arg2 --arg3=foo --arg4=bar" + AZStd::string RemoveExtraSpaces(AZStd::string_view commandLineString); + + //! Accepts two arbitrary strings that contain typical command line arguments and returns + //! a new string that combines the arguments were the arguments on the @right have precedence. + //! Example: + //! @param left: "--arg1 -arg2 --arg3=foo" + //! @param right: "--arg3=bar --arg4" + //! @returns: "--arg1 -arg2 --arg3=bar --arg4" + AZStd::string MergeCommandLineArguments(AZStd::string_view left, AZStd::string_view right); + + //! @param commandLineString: A string that contains a series of command line arguments. + //! @returns: true if @commandLineString contains macro definitions, e.g: + //! "-D MACRO" or "-D MACRO=VALUE" or "-DMACRO", "-DMACRO=VALUE". + bool HasMacroDefinitions(AZStd::string_view commandLineString); + } } } diff --git a/Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp b/Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp index 7304a351d4..3a04bf6b88 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp @@ -12,6 +12,9 @@ #include #include +#include + +#include namespace AZ { @@ -49,6 +52,12 @@ namespace AZ } } + bool ShaderCompilerArguments::HasMacroDefinitionsInCommandLineArguments() + { + return CommandLineArgumentUtils::HasMacroDefinitions(m_azslcAdditionalFreeArguments) || + CommandLineArgumentUtils::HasMacroDefinitions(m_dxcAdditionalFreeArguments); + } + void ShaderCompilerArguments::Merge(const ShaderCompilerArguments& right) { if (right.m_azslcWarningLevel != LevelUnset) @@ -56,7 +65,7 @@ namespace AZ m_azslcWarningLevel = right.m_azslcWarningLevel; } m_azslcWarningAsError = m_azslcWarningAsError || right.m_azslcWarningAsError; - m_azslcAdditionalFreeArguments += " " + right.m_azslcAdditionalFreeArguments; + m_azslcAdditionalFreeArguments = CommandLineArgumentUtils::MergeCommandLineArguments(m_azslcAdditionalFreeArguments, right.m_azslcAdditionalFreeArguments); m_dxcDisableWarnings = m_dxcDisableWarnings || right.m_dxcDisableWarnings; m_dxcWarningAsError = m_dxcWarningAsError || right.m_dxcWarningAsError; m_dxcDisableOptimizations = m_dxcDisableOptimizations || right.m_dxcDisableOptimizations; @@ -65,13 +74,14 @@ namespace AZ { m_dxcOptimizationLevel = right.m_dxcOptimizationLevel; } - m_dxcAdditionalFreeArguments += " " + right.m_dxcAdditionalFreeArguments; + m_dxcAdditionalFreeArguments = CommandLineArgumentUtils::MergeCommandLineArguments(m_dxcAdditionalFreeArguments, right.m_dxcAdditionalFreeArguments); if (right.m_defaultMatrixOrder != MatrixOrder::Default) { m_defaultMatrixOrder = right.m_defaultMatrixOrder; } } + //! [GFX TODO] [ATOM-15472] Remove this function. bool ShaderCompilerArguments::HasDifferentAzslcArguments(const ShaderCompilerArguments& right) const { auto isSet = +[](uint8_t level) { return level != LevelUnset; }; diff --git a/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp b/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp index 00b5dada69..dc0efb7e9a 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp @@ -494,5 +494,64 @@ namespace AZ AzFramework::StringFunc::Path::ReplaceExtension(outputFile, outputExtension); return outputFile; } + + namespace CommandLineArgumentUtils + { + AZStd::vector GetListOfArgumentNames(AZStd::string_view commandLineString) + { + AZStd::vector listOfTokens; + AzFramework::StringFunc::Tokenize(commandLineString, listOfTokens, " \t\n"); + AZStd::vector listOfArguments; + for (const AZStd::string& token : listOfTokens) + { + AZStd::vector splitArguments; + AzFramework::StringFunc::Tokenize(token, splitArguments, "="); + listOfArguments.push_back(splitArguments[0]); + } + return listOfArguments; + } + + AZStd::string RemoveArgumentsFromCommandLineString( + AZStd::array_view listOfArgumentsToRemove, AZStd::string_view commandLineString) + { + AZStd::string customizedArguments = commandLineString; + for (const AZStd::string& azslcArgumentName : listOfArgumentsToRemove) + { + AZStd::string regexStr = AZStd::string::format("%s(=\\S+)?", azslcArgumentName.c_str()); + AZStd::regex replaceRegex(regexStr, AZStd::regex::ECMAScript); + customizedArguments = AZStd::regex_replace(customizedArguments, replaceRegex, ""); + } + return customizedArguments; + } + + AZStd::string RemoveExtraSpaces(AZStd::string_view commandLineString) + { + AZStd::vector argumentList; + AzFramework::StringFunc::Tokenize(commandLineString, argumentList, " \t\n"); + AZStd::string cleanStringWithArguments; + AzFramework::StringFunc::Join(cleanStringWithArguments, argumentList.begin(), argumentList.end(), " "); + return cleanStringWithArguments; + } + + AZStd::string MergeCommandLineArguments(AZStd::string_view left, AZStd::string_view right) + { + auto listOfArgumentNamesFromRight = GetListOfArgumentNames(right); + auto leftWithRightArgumentsRemoved = RemoveArgumentsFromCommandLineString(listOfArgumentNamesFromRight, left); + AZStd::string combinedArguments = AZStd::string::format("%s %s", leftWithRightArgumentsRemoved.c_str(), right.data()); + return RemoveExtraSpaces(combinedArguments); + } + + bool HasMacroDefinitions(AZStd::string_view commandLineString) + { + const AZStd::regex macroRegex(R"((^-D\s*(\w+))|(\s+-D\s*(\w+)))", AZStd::regex::ECMAScript); + + AZStd::smatch match; + if (AZStd::regex_search(commandLineString.data(), match, macroRegex)) + { + return (match.size() >= 1); + } + return false; + } + } //namespace CommandLineArgumentUtils } // namespace RHI } // namespace AZ 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 841c71126a..c4666578a7 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp @@ -251,7 +251,7 @@ namespace AZ ByProducts& byProducts) const { // Shader compiler executable - static const char* dxcRelativePath = "Builders/DirectXShaderCompilerAz/bin/dxc"; + static const char* dxcRelativePath = "Builders/DirectXShaderCompiler/bin/dxc"; // Output file AZStd::string shaderMSLOutputFile = RHI::BuildFileNameWithExtension(shaderSourceFile, tempFolder, "metal"); diff --git a/Gems/Atom/RHI/Null/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp b/Gems/Atom/RHI/Null/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp index 35ee5a7ec0..0be84dba15 100644 --- a/Gems/Atom/RHI/Null/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp +++ b/Gems/Atom/RHI/Null/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp @@ -104,7 +104,7 @@ namespace AZ { return WindowsAzslShaderHeader; } - else if (platform.m_identifier == "osx_gl") + else if (platform.m_identifier == "mac") { return MacAzslShaderHeader; } diff --git a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli index 2381febed0..9b90c40ab9 100644 --- a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli +++ b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli @@ -225,3 +225,16 @@ float NextRandomFloatUniform(inout uint seed) seed = Xorshift(seed); return (float)seed / 4294967295.0f; } + +//! Returns the inverse of lerp, 't', such that value = lerp(a, b, t), or returns 0 when a == b. +float LerpInverse(float a, float b, float value) +{ + if(abs(a - b) <= EPSILON) + { + return 0.0; + } + else + { + return (value - a) / (b - a); + } +} diff --git a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli index 69381ca0fc..e12736dfec 100644 --- a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli +++ b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli @@ -16,7 +16,12 @@ ShaderResourceGroup DrawSrg : SRG_PerDraw { - float4 m_placeholder; // [GFX-TODO] [Atom-1727] Bug in AZSLc, empty SRGs cannot be shader variant fallbacks! // This SRG is unique per draw packet + uint m_uvStreamTangentBitmask; + + uint GetTangentAtUv(uint uvIndex) + { + return (m_uvStreamTangentBitmask >> (4 * uvIndex)) & 0xF; + } } diff --git a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/TangentSpace.azsli b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/TangentSpace.azsli index 13e3c652db..62111b3e80 100644 --- a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/TangentSpace.azsli +++ b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/TangentSpace.azsli @@ -52,6 +52,12 @@ float3 GetTangentSpaceNormal_Unnormalized(float2 normalMapSample, float normalSt // The image build pipeline drops the B channel so we have to reconstruct it here. surfaceNormal.z = sqrt(1 - dot(surfaceNormal.xy, surfaceNormal.xy)); + // Don't allow z to be zero just in case normalStrength approaches 0, to avoid a 0-length normal. + // It doesn't make sense anyway to have a surface with a normal map completely tangential. + // This also addresses the possibility of z being NaN, in the case where x^2+y^2 > 1, so we don't need to call saturate in the sqrt operation above. + // (Note this edge case would be particularly evident in multilayer material types, where the normal map is masked out using normalStrength). + surfaceNormal.z = max(surfaceNormal.z, 0.01); + surfaceNormal.xy *= normalStrength; return surfaceNormal; @@ -190,12 +196,22 @@ void SurfaceGradientNormalMapping_GenerateTB(float2 uv, out float3 tangentWS, ou } //! Utility macro to nest SGBNM setup processes. -#define PrepareGeneratedTangent(normal, worldPos, isFrontFace, uvSets, uvSetCount, outTangents, outBitangents, startIndex) \ +//! We support two UV streams, but only a single stream of tangent/bitangent. +//! By default, the first UV stream is applied and the default tangent/bitangent are used. +//! If anything uses the second UV stream, and it is not a duplication of the first stream, +//! generated tangent/bitangent will be applied. +//! (As it implies, cases may occur where all/none of the UV steams use the default TB.) +//! What tangent/bitangent a UV stream uses is encoded in DrawSrg. +#define PrepareGeneratedTangent(normal, worldPos, isFrontFace, uvSets, uvSetCount, outTangents, outBitangents) \ { \ SurfaceGradientNormalMapping_Init(normal, worldPos, !isFrontFace); \ [unroll] \ - for (int i = startIndex; i < uvSetCount; ++i) \ + for (uint i = 0; i < uvSetCount; ++i) \ { \ + if (DrawSrg::GetTangentAtUv(i) == 0) \ + { \ + continue; \ + } \ SurfaceGradientNormalMapping_GenerateTB(uvSets[i], outTangents[i], outBitangents[i]); \ } \ } diff --git a/Gems/Atom/RPI/Code/CMakeLists.txt b/Gems/Atom/RPI/Code/CMakeLists.txt index f92213d9d7..d2b7fba071 100644 --- a/Gems/Atom/RPI/Code/CMakeLists.txt +++ b/Gems/Atom/RPI/Code/CMakeLists.txt @@ -69,6 +69,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) PRIVATE AZ::AtomCore AZ::AzToolsFramework + Gem::Atom_RHI.Edit Gem::Atom_RPI.Public ) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h index e4b9b91e81..2dd0865688 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h @@ -87,6 +87,14 @@ namespace AZ //! Finalize and validate initialization. Any initialization functions should be called before EndInit is called. void EndInit(); + //! Set up the DynamicDrawContext for the input Scene. + //! This should be called after the last frame is done and before any draw calls. + void SetScene(Scene* scene); + + //! Set up the DynamicDrawContext for the input RenderPipeline. + //! This should be called after the last frame is done and before any draw calls. + void SetRenderPipeline(RenderPipeline* pipeline); + //! Return if this DynamicDrawContext is ready to add draw calls bool IsReady(); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/MeshDrawPacket.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/MeshDrawPacket.h index 0aa979d611..70cabca371 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/MeshDrawPacket.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/MeshDrawPacket.h @@ -98,7 +98,7 @@ namespace AZ //! List of shader options set for this specific draw packet typedef AZStd::pair ShaderOptionPair; typedef AZStd::vector ShaderOptionVector; - ShaderOptionVector m_shaderOptions; + ShaderOptionVector m_shaderOptions; }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h index 285cf80aca..5a1c571a26 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h @@ -14,6 +14,7 @@ #include #include +#include #include @@ -108,6 +109,7 @@ namespace AZ const MaterialUvNameMap& materialUvNameMap = {}) const; //! Fills a InputStreamLayout and StreamBufferViewList for the set of streams that satisfy a ShaderInputContract. + // @param uvStreamTangentBitmaskOut a mask processed during UV stream matching, and later to determine which tangent/bitangent stream to use. // @param contract the contract that defines the expected inputs for a shader, used to determine which streams are optional. // @param meshIndex the index of the mesh to search in. // @param materialModelUvMap a map of UV name overrides, which can be supplied to bind a specific mesh stream name to a different material shader stream name. @@ -115,6 +117,7 @@ namespace AZ bool GetStreamsForMesh( RHI::InputStreamLayout& layoutOut, ModelLod::StreamBufferViewList& streamBufferViewsOut, + UvStreamTangentBitmask* uvStreamTangentBitmaskOut, const ShaderInputContract& contract, size_t meshIndex, const MaterialModelUvOverrideMap& materialModelUvMap = {}, @@ -130,6 +133,8 @@ namespace AZ const ModelLodAsset::Mesh::StreamBufferInfo& streamBufferInfo, Mesh& meshInstance); + StreamInfoList::const_iterator FindFirstUvStreamFromMesh(size_t meshIndex) const; + StreamInfoList::const_iterator FindDefaultUvStream(size_t meshIndex, const MaterialUvNameMap& materialUvNameMap) const; // Finds a mesh vertex input stream that is the best match for a contracted stream channel. @@ -137,12 +142,16 @@ namespace AZ // @param materialModelUvMap a map of UV name overrides, which can be supplied to bind a specific mesh stream name to a different material shader stream name. // @param materialUvNameMap the UV name map that came from a MaterialTypeAsset, which defines the default set of material shader stream names. // @param defaultUv the default UV stream to use if a matching UV stream could not be found. Use FindDefaultUvStream() to populate this. + // @param firstUv the first UV stream from the mesh, which, by design, the tangent/bitangent stream belongs to. + // @param uvStreamTangentIndex a bitset indicating which tangent/bitangent stream (including generated ones) a UV stream will be using. StreamInfoList::const_iterator FindMatchingStream( size_t meshIndex, const MaterialModelUvOverrideMap& materialModelUvMap, const MaterialUvNameMap& materialUvNameMap, const ShaderInputContract::StreamChannelInfo& contractStreamChannel, - StreamInfoList::const_iterator defaultUv) const; + StreamInfoList::const_iterator defaultUv, + StreamInfoList::const_iterator firstUv, + UvStreamTangentBitmask* uvStreamTangentBitmaskOut) const; // Meshes may share index/stream buffers in an LOD or they may have // unique buffers. Often the asset builder will prioritize shared buffers diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/UvStreamTangentBitmask.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/UvStreamTangentBitmask.h new file mode 100644 index 0000000000..aa599bc27c --- /dev/null +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/UvStreamTangentBitmask.h @@ -0,0 +1,72 @@ +/* +* 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 + +namespace AZ +{ + namespace RPI + { + //! An encoded bitmask for tangent used by UV streams. + //! It contains the information about number of UV streams and which tangent/bitangent is used by each UV stream. + //! See m_mask for more details. + //! The mask will be passed through per draw SRG. + class UvStreamTangentBitmask + { + public: + //! Get the full mask including number of UVs and tangent/bitangent assignment to each UV. + uint32_t GetFullTangentBitmask() const; + + //! Get number of UVs that have tangent/bitangent assigned. + uint32_t GetUvStreamCount() const; + + //! Get tangent/bitangent assignment to the specified UV in the material. + //! @param uvIndex the index of the UV from the material, in default order as in the shader code. + uint32_t GetTangentAtUv(uint32_t uvIndex) const; + + //! Apply the tangent to the next UV, whose index is the same as GetUvStreamCount. + //! @param tangent the tangent/bitangent to be assigned. Ranged in [0, 0xF) + //! It comes from the model in order, e.g. 0 means the first available tangent stream from the model. + //! Specially, value 0xF(=UnassignedTangent) means generated tangent/bitangent will be used in shader. + //! If ranged out of definition, unassigned tangent will be applied. + void ApplyTangent(uint32_t tangent); + + //! Reset the bitmask to clear state. + void Reset(); + + //! The bit mask indicating generated tangent/bitangent will be used. + static constexpr uint32_t UnassignedTangent = 0b1111u; + + //! The variable name defined in the SRG shader code. + static constexpr const char* SrgName = "m_uvStreamTangentBitmask"; + private: + //! Mask composition: + //! The number of UV slots (highest 4 bits) + tangent mask (4 bits each) * 7 + //! e.g. 0x200000F0 means there are 2 UV streams, + //! the first UV stream uses 0th tangent stream (0x0), + //! the second UV stream uses the generated tangent stream (0xF). + uint32_t m_mask = 0; + + //! Bit size in the mask composition. + static constexpr uint32_t BitsPerTangent = 4; + static constexpr uint32_t BitsForUvIndex = 4; + + public: + //! Max UV slots available in this bit mask. + static constexpr uint32_t MaxUvSlots = (sizeof(m_mask) * CHAR_BIT - BitsForUvIndex) / BitsPerTangent; + }; + } +} diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h index 4f24a20f35..8075c6fc5d 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h @@ -26,9 +26,9 @@ namespace AZ class ViewportContextManager; //! ViewportContext wraps a native window and represents a minimal viewport - //! in which a scene is rendered on-screen + //! in which a scene is rendered on-screen. //! ViewportContexts are registered on creation to allow consumers to listen to notifications - //! and manage the view stack for a given viewport + //! and manage the view stack for a given viewport. class ViewportContext : public SceneNotificationBus::Handler , public AzFramework::WindowNotificationBus::Handler @@ -61,11 +61,11 @@ namespace AZ //! Gets the current name of this ViewportContext. //! This name is used to tie this ViewportContext to its View stack, and ViewportContexts may be - //! renamed via AZ::Interface::Get()->RenameViewportContext. + //! renamed via AZ::RPI::ViewportContextRequests::Get()->RenameViewportContext(...). AZ::Name GetName() const; //! Gets the default view associated with this ViewportContext. - //! Alternatively, use AZ::Interface::Get()->GetCurrentView. + //! Alternatively, use AZ::RPI::ViewportContextRequests::Get()->GetCurrentView(). ViewPtr GetDefaultView(); ConstViewPtr GetDefaultView() const; @@ -99,6 +99,18 @@ namespace AZ //! Notifies consumers when the render scene has changed. void ConnectSceneChangedHandler(SceneChangedEvent::Handler& handler); + using PipelineChangedEvent = AZ::Event; + //! Notifies consumers when the current pipeline associated with our window has changed. + void ConnectCurrentPipelineChangedHandler(PipelineChangedEvent::Handler& handler); + + using ViewChangedEvent = AZ::Event; + //! Notifies consumers when the default view has changed. + void ConnectDefaultViewChangedHandler(ViewChangedEvent::Handler& handler); + + using ViewportIdEvent = AZ::Event; + //! Notifies consumers when this ViewportContext is about to be destroyed. + void ConnectAboutToBeDestroyedHandler(ViewportIdEvent::Handler& handler); + // ViewportRequestBus interface //! Gets the current camera's view matrix. const AZ::Matrix4x4& GetCameraViewMatrix() const override; @@ -123,12 +135,17 @@ namespace AZ WindowContextSharedPtr m_windowContext; ViewPtr m_defaultView; AzFramework::WindowSize m_viewportSize; + SizeChangedEvent m_sizeChangedEvent; MatrixChangedEvent m_viewMatrixChangedEvent; MatrixChangedEvent::Handler m_onViewMatrixChangedHandler; MatrixChangedEvent m_projectionMatrixChangedEvent; MatrixChangedEvent::Handler m_onProjectionMatrixChangedHandler; SceneChangedEvent m_sceneChangedEvent; + PipelineChangedEvent m_currentPipelineChangedEvent; + ViewChangedEvent m_defaultViewChangedEvent; + ViewportIdEvent m_aboutToBeDestroyedEvent; + ViewportContextManager* m_manager; RenderPipelinePtr m_currentPipeline; Name m_name; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderSourceData.cpp index aac81a6e26..376399ff84 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderSourceData.cpp @@ -11,6 +11,8 @@ */ #include +#include +#include #include #include @@ -57,7 +59,7 @@ namespace AZ bool ShaderSourceData::IsRhiBackendDisabled(const AZ::Name& rhiName) const { - return AZStd::any_of(m_disabledRhiBackends.begin(), m_disabledRhiBackends.end(), [&](const AZStd::string& currentRhiName) + return AZStd::any_of(AZ_BEGIN_END(m_disabledRhiBackends), [&](const AZStd::string& currentRhiName) { return currentRhiName == rhiName.GetStringView(); }); @@ -72,19 +74,32 @@ namespace AZ static void GetListOfMacroDefinitionNames( const AZStd::string& stringWithArguments, AZStd::vector& macroDefinitionNames) { - static const AZStd::regex macroRegex("-D\\s*(\\w+)", AZStd::regex::ECMAScript); + const AZStd::regex macroRegex(R"(-D\s*(\w+))", AZStd::regex::ECMAScript); - AZStd::cmatch match; - if (AZStd::regex_search(stringWithArguments.c_str(), match, macroRegex)) + AZStd::string hayStack(stringWithArguments); + AZStd::smatch match; + while (AZStd::regex_search(hayStack.c_str(), match, macroRegex)) { // First pattern is always the entire string for (unsigned i = 1; i < match.size(); ++i) { if (match[i].matched) { - macroDefinitionNames.push_back(match[i].str().c_str()); + AZStd::string macroToAdd(match[i].str().c_str()); + const bool isPresent = AZStd::any_of(AZ_BEGIN_END(macroDefinitionNames), + [&](AZStd::string_view macroName) -> bool + { + return macroToAdd == macroName; + } + ); + if (isPresent) + { + continue; + } + macroDefinitionNames.push_back(macroToAdd); } } + hayStack = match.suffix(); } } @@ -103,19 +118,22 @@ namespace AZ static void GetListOfMacroDefinitions( const AZStd::string& stringWithArguments, AZStd::vector& macroDefinitions) { - static const AZStd::regex macroRegex("-D\\s*(\\w+(=\\w+)?)", AZStd::regex::ECMAScript); + const AZStd::regex macroRegex(R"(-D\s*(\w+)(=\w+)?)", AZStd::regex::ECMAScript); - AZStd::cmatch match; - if (AZStd::regex_search(stringWithArguments.c_str(), match, macroRegex)) + AZStd::string hayStack(stringWithArguments); + AZStd::smatch match; + while (AZStd::regex_search(hayStack.c_str(), match, macroRegex)) { - // First pattern is always the entire string - for (unsigned i = 1; i < match.size(); ++i) + if (match.size() > 1) { - if (match[i].matched) + AZStd::string macro(match[1].str().c_str()); + if (match.size() > 2) { - macroDefinitions.push_back(match[i].str().c_str()); + macro += match[2].str().c_str(); } + macroDefinitions.push_back(macro); } + hayStack = match.suffix(); } } @@ -126,62 +144,27 @@ namespace AZ return parsedMacroDefinitions; } - - // Helper. - // @arguments: A string with command line arguments for a console application of the form: - // "- -- --[=] ..." - // Example: "--use-spaces --namespace=vk" - // Returns: A list with just the [-|--]: - // ["-", "--", "--arg3"] - // For the example shown above it will return this vector: - // ["--use-spaces", "--namespace"] - AZStd::vector GetListOfArgumentNames(const AZStd::string& arguments) - { - AZStd::vector listOfTokens; - AzFramework::StringFunc::Tokenize(arguments, listOfTokens); - AZStd::vector listOfArguments; - for (const AZStd::string& token : listOfTokens) - { - AZStd::vector splitArguments; - AzFramework::StringFunc::Tokenize(token, splitArguments, "="); - listOfArguments.push_back(splitArguments[0]); - } - return listOfArguments; - } - AZStd::string ShaderSourceData::SupervariantInfo::GetCustomizedArgumentsForAzslc( const AZStd::string& initialAzslcCompilerArguments) const { - static const AZStd::regex macroRegex("-D\\s*(\\w+(=\\S+)?)", AZStd::regex::ECMAScript); + const AZStd::regex macroRegex(R"(-D\s*(\w+(=\S+)?))", AZStd::regex::ECMAScript); // We are only concerned with AZSLc arguments. Let's remove the C-Preprocessor macro definitions // from @minusArguments. const AZStd::string minusArguments = AZStd::regex_replace(m_minusArguments, macroRegex, ""); const AZStd::string plusArguments = AZStd::regex_replace(m_plusArguments, macroRegex, ""); AZStd::string azslcArgumentsToRemove = minusArguments + " " + plusArguments; - AZStd::vector azslcArgumentNamesToRemove = GetListOfArgumentNames(azslcArgumentsToRemove); + AZStd::vector azslcArgumentNamesToRemove = RHI::CommandLineArgumentUtils::GetListOfArgumentNames(azslcArgumentsToRemove); // At this moment @azslcArgumentsToRemove contains arguments for AZSLc that can be of the form: // - // --[=] // We need to remove those from @initialAzslcCompilerArguments. - AZStd::string customizedArguments = initialAzslcCompilerArguments; - for (const AZStd::string& azslcArgumentName : azslcArgumentNamesToRemove) - { - AZStd::string regexStr = AZStd::string::format("%s(=\\S+)?", azslcArgumentName.c_str()); - AZStd::regex replaceRegex(regexStr, AZStd::regex::ECMAScript); - customizedArguments = AZStd::regex_replace(customizedArguments, replaceRegex, ""); - } - + AZStd::string customizedArguments = RHI::CommandLineArgumentUtils::RemoveArgumentsFromCommandLineString( + azslcArgumentNamesToRemove, initialAzslcCompilerArguments); customizedArguments += " " + plusArguments; - // Will contain the results that will be joined by a space. - // This is used to get a clean string to return without excess spaces. - AZStd::vector argumentList; - AzFramework::StringFunc::Tokenize(customizedArguments, argumentList, " \t\n"); - customizedArguments.clear(); // Need to clear because Join appends. - AzFramework::StringFunc::Join(customizedArguments, argumentList.begin(), argumentList.end(), " "); - return customizedArguments; + return RHI::CommandLineArgumentUtils::RemoveExtraSpaces(customizedArguments); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp index b7ba7d4a32..4e4a7a5e71 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/DynamicDraw/DynamicDrawContext.cpp @@ -211,6 +211,42 @@ namespace AZ m_rhiPipelineState = m_pipelineState->GetRHIPipelineState(); } + void DynamicDrawContext::SetScene(Scene* scene) + { + AZ_Assert(scene, "SetScene called with an invalid scene"); + if (!scene || m_scene == scene) + { + return; + } + m_scene = scene; + m_drawFilter = RHI::DrawFilterMaskDefaultValue; + // Reinitialize if it was initialized + if (m_initialized) + { + // Report warning if there were some draw data + AZ_Warning( + "DynamicDrawContext", m_cachedDrawItems.size() == 0, + "DynamicDrawContext::SetForScene should be called" + " when there is no cached draw data"); + // Clear some cached data + FrameEnd(); + m_cachedRhiPipelineStates.clear(); + // Reinitialize + EndInit(); + } + } + + void DynamicDrawContext::SetRenderPipeline(RenderPipeline* pipeline) + { + AZ_Assert(pipeline, "SetRenderPipeline called with an invalid pipeline"); + if (!pipeline) + { + return; + } + SetScene(pipeline->GetScene()); + m_drawFilter = pipeline->GetDrawFilterMask(); + } + bool DynamicDrawContext::IsReady() { return m_initialized; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp index d0a277304e..b1265b1228 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp @@ -169,7 +169,7 @@ namespace AZ const AZ::Data::Asset& drawSrgAsset = shader->GetAsset()->GetDrawSrgAsset(); // Set all unspecified shader options to default values, so that we get the most specialized variant possible. - // (because FindVariantStableId treats unspecified options as a request specificlly for a variant that doesn't specify those options) + // (because FindVariantStableId treats unspecified options as a request specifically for a variant that doesn't specify those options) // [GFX TODO][ATOM-3883] We should consider updating the FindVariantStableId algorithm to handle default values for us, and remove this step here. RPI::ShaderOptionGroup shaderOptions = *shaderItem.GetShaderOptions(); shaderOptions.SetUnspecifiedToDefaultValues(); @@ -198,6 +198,31 @@ namespace AZ const ShaderVariantId finalVariantId = shaderOptions.GetShaderVariantId(); const ShaderVariant& variant = r_forceRootShaderVariantUsage ? shader->GetRootVariant() : shader->GetVariant(finalVariantId); + RHI::PipelineStateDescriptorForDraw pipelineStateDescriptor; + variant.ConfigurePipelineState(pipelineStateDescriptor); + + // Render states need to merge the runtime variation. + // This allows materials to customize the render states that the shader uses. + const RHI::RenderStates& renderStatesOverlay = *shaderItem.GetRenderStatesOverlay(); + RHI::MergeStateInto(renderStatesOverlay, pipelineStateDescriptor.m_renderStates); + + streamBufferViewsPerShader.push_back(); + auto& streamBufferViews = streamBufferViewsPerShader.back(); + + UvStreamTangentBitmask uvStreamTangentBitmask; + + if (!m_modelLod->GetStreamsForMesh( + pipelineStateDescriptor.m_inputStreamLayout, + streamBufferViews, + &uvStreamTangentBitmask, + variant.GetInputContract(), + m_modelLodMeshIndex, + m_materialModelUvMap, + m_material->GetAsset()->GetMaterialTypeAsset()->GetUvNameMap())) + { + return false; + } + Data::Instance drawSrg; if (drawSrgAsset) { @@ -210,31 +235,20 @@ namespace AZ drawSrg->SetShaderVariantKeyFallbackValue(shaderOptions.GetShaderVariantKeyFallbackValue()); } + // Pass UvStreamTangentBitmask to the shader if the draw SRG has it. + { + AZ::Name shaderUvStreamTangentBitmask = AZ::Name(UvStreamTangentBitmask::SrgName); + auto index = drawSrg->FindShaderInputConstantIndex(shaderUvStreamTangentBitmask); + + if (index.IsValid()) + { + drawSrg->SetConstant(index, uvStreamTangentBitmask.GetFullTangentBitmask()); + } + } + drawSrg->Compile(); } - RHI::PipelineStateDescriptorForDraw pipelineStateDescriptor; - variant.ConfigurePipelineState(pipelineStateDescriptor); - - // Render states need to merge the runtime variation. - // This allows materials to customize the render states that the shader uses. - const RHI::RenderStates& renderStatesOverlay = *shaderItem.GetRenderStatesOverlay(); - RHI::MergeStateInto(renderStatesOverlay, pipelineStateDescriptor.m_renderStates); - - streamBufferViewsPerShader.push_back(); - auto& streamBufferViews = streamBufferViewsPerShader.back(); - - if (!m_modelLod->GetStreamsForMesh( - pipelineStateDescriptor.m_inputStreamLayout, - streamBufferViews, - variant.GetInputContract(), - m_modelLodMeshIndex, - m_materialModelUvMap, - m_material->GetAsset()->GetMaterialTypeAsset()->GetUvNameMap())) - { - return false; - } - // Use the default draw list tag from the shader variant. RHI::DrawListTag drawListTag = shader->GetDrawListTag(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp index 8747dac663..c6a1a51f39 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp @@ -117,6 +117,17 @@ namespace AZ return RHI::ResultCode::Success; } + ModelLod::StreamInfoList::const_iterator ModelLod::FindFirstUvStreamFromMesh(size_t meshIndex) const + { + const Mesh& mesh = m_meshes[meshIndex]; + + auto firstUv = AZStd::find_if(mesh.m_streamInfo.begin(), mesh.m_streamInfo.end(), [](const StreamBufferInfo& info) { + return info.m_semantic.m_name.GetStringView().starts_with(RHI::ShaderSemantic::UvStreamSemantic); + }); + + return firstUv; + } + ModelLod::StreamInfoList::const_iterator ModelLod::FindDefaultUvStream(size_t meshIndex, const MaterialUvNameMap& materialUvNameMap) const { const Mesh& mesh = m_meshes[meshIndex]; @@ -160,7 +171,9 @@ namespace AZ const MaterialModelUvOverrideMap& materialModelUvMap, const MaterialUvNameMap& materialUvNameMap, const ShaderInputContract::StreamChannelInfo& contractStreamChannel, - StreamInfoList::const_iterator defaultUv) const + StreamInfoList::const_iterator defaultUv, + StreamInfoList::const_iterator firstUv, + UvStreamTangentBitmask* uvStreamTangentBitmaskOut) const { const Mesh& mesh = m_meshes[meshIndex]; auto iter = mesh.m_streamInfo.end(); @@ -184,8 +197,8 @@ namespace AZ // Cost of linear search UV names is low because the size is extremely limited. return uvNamePair.m_shaderInput == contractStreamChannel.m_semantic; }); - const bool IsUv = materialUvIter != materialUvNameMap.end(); - if (IsUv) + const bool isUv = materialUvIter != materialUvNameMap.end(); + if (isUv) { const AZ::Name& materialUvName = materialUvIter->m_uvName; auto modelUvMapIter = materialModelUvMap.find(materialUvIter->m_shaderInput); @@ -224,17 +237,23 @@ namespace AZ }); } - if (iter == mesh.m_streamInfo.end() && IsUv) + if (iter == mesh.m_streamInfo.end() && isUv) { iter = defaultUv; } + if (isUv && uvStreamTangentBitmaskOut) + { + uvStreamTangentBitmaskOut->ApplyTangent(iter == firstUv ? 0 : UvStreamTangentBitmask::UnassignedTangent); + } + return iter; } bool ModelLod::GetStreamsForMesh( RHI::InputStreamLayout& layoutOut, StreamBufferViewList& streamBufferViewsOut, + UvStreamTangentBitmask* uvStreamTangentBitmaskOut, const ShaderInputContract& contract, size_t meshIndex, const MaterialModelUvOverrideMap& materialModelUvMap, @@ -250,11 +269,17 @@ namespace AZ bool success = true; + // Searching for the first UV in the mesh, so it can be used to paired with tangent/bitangent stream + auto firstUv = FindFirstUvStreamFromMesh(meshIndex); auto defaultUv = FindDefaultUvStream(meshIndex, materialUvNameMap); + if (uvStreamTangentBitmaskOut) + { + uvStreamTangentBitmaskOut->Reset(); + } for (auto& contractStreamChannel : contract.m_streamChannels) { - auto iter = FindMatchingStream(meshIndex, materialModelUvMap, materialUvNameMap, contractStreamChannel, defaultUv); + auto iter = FindMatchingStream(meshIndex, materialModelUvMap, materialUvNameMap, contractStreamChannel, defaultUv, firstUv, uvStreamTangentBitmaskOut); if (iter == mesh.m_streamInfo.end()) { @@ -340,6 +365,7 @@ namespace AZ const Mesh& mesh = m_meshes[meshIndex]; auto defaultUv = FindDefaultUvStream(meshIndex, materialUvNameMap); + auto firstUv = FindFirstUvStreamFromMesh(meshIndex); for (auto& contractStreamChannel : contract.m_streamChannels) { @@ -350,7 +376,7 @@ namespace AZ AZ_Assert(contractStreamChannel.m_streamBoundIndicatorIndex.IsValid(), "m_streamBoundIndicatorIndex was invalid for an optional shader input stream"); - auto iter = FindMatchingStream(meshIndex, materialModelUvMap, materialUvNameMap, contractStreamChannel, defaultUv); + auto iter = FindMatchingStream(meshIndex, materialModelUvMap, materialUvNameMap, contractStreamChannel, defaultUv, firstUv, nullptr); ShaderOptionValue isStreamBound = (iter == mesh.m_streamInfo.end()) ? ShaderOptionValue{0} : ShaderOptionValue{1}; shaderOptions.SetValue(contractStreamChannel.m_streamBoundIndicatorIndex, isStreamBound); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/UvStreamTangentBitmask.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/UvStreamTangentBitmask.cpp new file mode 100644 index 0000000000..829207e406 --- /dev/null +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/UvStreamTangentBitmask.cpp @@ -0,0 +1,71 @@ +/* +* 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 + +namespace AZ +{ + namespace RPI + { + uint32_t UvStreamTangentBitmask::GetFullTangentBitmask() const + { + return m_mask; + } + + uint32_t UvStreamTangentBitmask::GetUvStreamCount() const + { + return m_mask >> (sizeof(m_mask) * CHAR_BIT - BitsForUvIndex); + } + + uint32_t UvStreamTangentBitmask::GetTangentAtUv(uint32_t uvIndex) const + { + return (m_mask >> (BitsPerTangent * uvIndex)) & 0b1111u; + } + + void UvStreamTangentBitmask::ApplyTangent(uint32_t tangentIndex) + { + uint32_t currentSlot = GetUvStreamCount(); + if (currentSlot >= MaxUvSlots) + { + AZ_Error("UV Stream", false, "Reaching the max of avaiblable stream slots."); + return; + } + + if (tangentIndex > UnassignedTangent) + { + AZ_Warning( + "UV Stream", false, + "Tangent index must use %d bits as defined in UvStreamTangentIndex::m_flag. Unassigned index will be applied.", + BitsPerTangent); + tangentIndex = UnassignedTangent; + } + + uint32_t clearMask = 0b1111u << (BitsPerTangent * currentSlot); + clearMask = ~clearMask; + + // Clear the writing bits in case + m_mask &= clearMask; + + // Write the bits to the slot + m_mask |= (tangentIndex << (BitsPerTangent * currentSlot)); + + // Increase the index + m_mask += (1u << (sizeof(m_mask) * CHAR_BIT - BitsForUvIndex)); + } + + void UvStreamTangentBitmask::Reset() + { + m_mask = 0; + } + } +} diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp index 22287238e9..08f8ff0c5e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp @@ -51,6 +51,8 @@ namespace AZ ViewportContext::~ViewportContext() { + m_aboutToBeDestroyedEvent.Signal(m_id); + AzFramework::WindowNotificationBus::Handler::BusDisconnect(); AzFramework::ViewportRequestBus::Handler::BusDisconnect(); @@ -171,6 +173,21 @@ namespace AZ handler.Connect(m_sceneChangedEvent); } + void ViewportContext::ConnectCurrentPipelineChangedHandler(PipelineChangedEvent::Handler& handler) + { + handler.Connect(m_currentPipelineChangedEvent); + } + + void ViewportContext::ConnectDefaultViewChangedHandler(ViewChangedEvent::Handler& handler) + { + handler.Connect(m_defaultViewChangedEvent); + } + + void ViewportContext::ConnectAboutToBeDestroyedHandler(ViewportIdEvent::Handler& handler) + { + handler.Connect(m_aboutToBeDestroyedEvent); + } + const AZ::Matrix4x4& ViewportContext::GetCameraViewMatrix() const { return GetDefaultView()->GetWorldToViewMatrix(); @@ -214,6 +231,7 @@ namespace AZ m_defaultView = view; UpdatePipelineView(); + m_defaultViewChangedEvent.Signal(view); m_viewMatrixChangedEvent.Signal(view->GetWorldToViewMatrix()); m_projectionMatrixChangedEvent.Signal(view->GetViewToClipMatrix()); @@ -232,6 +250,7 @@ namespace AZ if (!m_currentPipeline) { m_currentPipeline = m_rootScene ? m_rootScene->FindRenderPipelineForWindow(m_windowContext->GetWindowHandle()) : nullptr; + m_currentPipelineChangedEvent.Signal(m_currentPipeline); } if (auto pipeline = GetCurrentPipeline()) diff --git a/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.cpp b/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.cpp index 84e8a4ba65..6b9c503ec2 100644 --- a/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.cpp +++ b/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.cpp @@ -72,7 +72,15 @@ namespace UnitTest return false; } - bool AssetSystemStub::GetFullSourcePathFromRelativeProductPath([[maybe_unused]] const AZStd::string& relPath, [[maybe_unused]] AZStd::string& fullSourcePath) + bool AssetSystemStub::GenerateRelativeSourcePath( + [[maybe_unused]] const AZStd::string& sourcePath, [[maybe_unused]] AZStd::string& relativePath, + [[maybe_unused]] AZStd::string& watchFolder) + { + return false; + } + + bool AssetSystemStub::GetFullSourcePathFromRelativeProductPath( + [[maybe_unused]] const AZStd::string& relPath, [[maybe_unused]] AZStd::string& fullSourcePath) { return false; } diff --git a/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.h b/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.h index c6f4ac891f..48609ed0cb 100644 --- a/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.h +++ b/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.h @@ -63,6 +63,8 @@ namespace UnitTest const char* GetAbsoluteDevGameFolderPath() override; const char* GetAbsoluteDevRootFolderPath() override; bool GetRelativeProductPathFromFullSourceOrProductPath(const AZStd::string& fullPath, AZStd::string& relativeProductPath) override; + bool GenerateRelativeSourcePath( + const AZStd::string& sourcePath, AZStd::string& relativePath, AZStd::string& watchFolder) override; bool GetFullSourcePathFromRelativeProductPath(const AZStd::string& relPath, AZStd::string& fullSourcePath) override; bool GetAssetInfoById(const AZ::Data::AssetId& assetId, const AZ::Data::AssetType& assetType, const AZStd::string& platformName, AZ::Data::AssetInfo& assetInfo, AZStd::string& rootFilePath) override; bool GetSourceInfoBySourceUUID(const AZ::Uuid& sourceUuid, AZ::Data::AssetInfo& assetInfo, AZStd::string& watchFolder) override; diff --git a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp index 980a9ac320..1ec14c6169 100644 --- a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -917,6 +918,43 @@ namespace UnitTest } } + TEST_F(ModelTests, UvStream) + { + AZ::RPI::UvStreamTangentBitmask uvStreamTangentBitmask; + EXPECT_EQ(uvStreamTangentBitmask.GetFullTangentBitmask(), 0u); + + uvStreamTangentBitmask.ApplyTangent(1u); + EXPECT_EQ(uvStreamTangentBitmask.GetTangentAtUv(0u), 1u); + EXPECT_EQ(uvStreamTangentBitmask.GetFullTangentBitmask(), 0x10000001); + EXPECT_EQ(uvStreamTangentBitmask.GetUvStreamCount(), 1u); + + uvStreamTangentBitmask.ApplyTangent(5u); + EXPECT_EQ(uvStreamTangentBitmask.GetTangentAtUv(0u), 1u); + EXPECT_EQ(uvStreamTangentBitmask.GetTangentAtUv(1u), 5u); + EXPECT_EQ(uvStreamTangentBitmask.GetFullTangentBitmask(), 0x20000051); + EXPECT_EQ(uvStreamTangentBitmask.GetUvStreamCount(), 2u); + + uvStreamTangentBitmask.ApplyTangent(100u); + EXPECT_EQ(uvStreamTangentBitmask.GetTangentAtUv(0u), 1u); + EXPECT_EQ(uvStreamTangentBitmask.GetTangentAtUv(1u), 5u); + EXPECT_EQ(uvStreamTangentBitmask.GetTangentAtUv(2u), AZ::RPI::UvStreamTangentBitmask::UnassignedTangent); + EXPECT_EQ(uvStreamTangentBitmask.GetFullTangentBitmask(), 0x30000F51); + EXPECT_EQ(uvStreamTangentBitmask.GetUvStreamCount(), 3u); + + for (uint32_t i = 3; i < AZ::RPI::UvStreamTangentBitmask::MaxUvSlots; ++i) + { + uvStreamTangentBitmask.ApplyTangent(0u); + } + + EXPECT_EQ(uvStreamTangentBitmask.GetFullTangentBitmask(), 0x70000F51); + + AZ_TEST_START_TRACE_SUPPRESSION; + uvStreamTangentBitmask.ApplyTangent(0u); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + + EXPECT_EQ(uvStreamTangentBitmask.GetFullTangentBitmask(), 0x70000F51); + } + // This class creates a Model with one LOD, whose mesh contains 2 planes. Plane 1 is in the XY plane at Z=-0.5, and // plane 2 is in the XY plane at Z=0.5. The two planes each have 9 quads which have been triangulated. It only has // a position and index buffer. diff --git a/Gems/Atom/RPI/Code/atom_rpi_public_files.cmake b/Gems/Atom/RPI/Code/atom_rpi_public_files.cmake index 0d5c19758b..6242f3f140 100644 --- a/Gems/Atom/RPI/Code/atom_rpi_public_files.cmake +++ b/Gems/Atom/RPI/Code/atom_rpi_public_files.cmake @@ -57,6 +57,7 @@ set(FILES Include/Atom/RPI.Public/Model/ModelLod.h Include/Atom/RPI.Public/Model/ModelLodUtils.h Include/Atom/RPI.Public/Model/ModelSystem.h + Include/Atom/RPI.Public/Model/UvStreamTangentBitmask.h Include/Atom/RPI.Public/Pass/AttachmentReadback.h Include/Atom/RPI.Public/Pass/ComputePass.h Include/Atom/RPI.Public/Pass/CopyPass.h @@ -136,6 +137,7 @@ set(FILES Source/RPI.Public/Model/ModelLod.cpp Source/RPI.Public/Model/ModelLodUtils.cpp Source/RPI.Public/Model/ModelSystem.cpp + Source/RPI.Public/Model/UvStreamTangentBitmask.cpp Source/RPI.Public/Pass/AttachmentReadback.cpp Source/RPI.Public/Pass/ComputePass.cpp Source/RPI.Public/Pass/CopyPass.cpp diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material index d9a4aabe2a..17353a0603 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material @@ -36,7 +36,6 @@ "diffuseTextureMap": "TestData/Textures/cc0/bark1_disp.jpg" }, "layer1_parallax": { - "enable": true, "factor": 0.02500000037252903, "textureMap": "TestData/Textures/cc0/bark1_disp.jpg" }, @@ -80,7 +79,6 @@ "specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg" }, "layer2_parallax": { - "enable": true, "factor": 0.01600000075995922, "textureMap": "TestData/Textures/cc0/Lava004_1K_Displacement.jpg" }, @@ -118,7 +116,6 @@ "diffuseTextureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Displacement.jpg" }, "layer3_parallax": { - "enable": true, "factor": 0.004999999888241291, "textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Displacement.jpg" }, diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material index 0bf4177db9..8cddab24bc 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material @@ -15,7 +15,6 @@ "textureMap": "TestData/Textures/cc0/bark1_norm.jpg" }, "layer1_parallax": { - "enable": true, "factor": 0.03999999910593033, "textureMap": "TestData/Textures/cc0/bark1_disp.jpg" }, @@ -32,7 +31,6 @@ "textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg" }, "layer2_parallax": { - "enable": true, "factor": 0.05299999937415123, "offset": -0.024000000208616258, "textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg" diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_DepthMaps.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material similarity index 81% rename from Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_DepthMaps.material rename to Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material index d41e116067..ffcbf3ce7e 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_DepthMaps.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendMask.material @@ -4,8 +4,8 @@ "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", "propertyLayoutVersion": 3, "properties": { - "general": { - "debugDrawMode": "DepthMaps" + "blend": { + "debugDrawMode": "BlendMask" } } } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material new file mode 100644 index 0000000000..8d13ac781f --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendWeights.material @@ -0,0 +1,11 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "debugDrawMode": "FinalBlendWeights" + } + } +} diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendSource.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material similarity index 80% rename from Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendSource.material rename to Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material index cdd21212c9..7aff50cb56 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_BlendSource.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/003_Debug_Displacement.material @@ -4,8 +4,8 @@ "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material", "propertyLayoutVersion": 3, "properties": { - "general": { - "debugDrawMode": "BlendSource" + "blend": { + "debugDrawMode": "Displacement" } } } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material index ea3ffab467..3201fa3864 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material @@ -5,7 +5,7 @@ "propertyLayoutVersion": 3, "properties": { "blend": { - "blendSource": "VertexColors" + "blendSource": "BlendMaskVertexColors" } } } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material new file mode 100644 index 0000000000..55a4774d49 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material @@ -0,0 +1,79 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "blendSource": "Displacement", + "displacementBlendDistance": 0.008999999612569809, + "enableLayer2": true, + "enableLayer3": true + }, + "layer1_baseColor": { + "textureMap": "TestData/Textures/cc0/Ground033_1K_Color.jpg" + }, + "layer1_normal": { + "textureMap": "TestData/Textures/cc0/Ground033_1K_Normal.jpg" + }, + "layer1_occlusion": { + "diffuseTextureMap": "TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg" + }, + "layer1_parallax": { + "factor": 0.017000000923871995, + "offset": -0.006000000052154064, + "textureMap": "TestData/Textures/cc0/Ground033_1K_Displacement.jpg" + }, + "layer1_roughness": { + "textureMap": "TestData/Textures/cc0/Ground033_1K_Roughness.jpg" + }, + "layer2_baseColor": { + "textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg" + }, + "layer2_normal": { + "textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg" + }, + "layer2_occlusion": { + "diffuseTextureMap": "TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg" + }, + "layer2_parallax": { + "factor": 0.03099999949336052, + "offset": 0.0020000000949949028, + "textureMap": "TestData/Textures/cc0/Rock030_2K_Displacement.jpg" + }, + "layer2_roughness": { + "textureMap": "TestData/Textures/cc0/Rock030_2K_Roughness.jpg" + }, + "layer2_uv": { + "center": [ + 0.5, + 0.5 + ], + "offsetU": 0.1599999964237213, + "offsetV": 0.07999999821186066, + "rotateDegrees": 90.0 + }, + "layer3_baseColor": { + "textureMap": "TestData/Textures/cc0/Rocks002_1K_Color.jpg" + }, + "layer3_normal": { + "textureMap": "TestData/Textures/cc0/Rocks002_1K_Normal.jpg" + }, + "layer3_parallax": { + "factor": 0.027000000700354577, + "textureMap": "TestData/Textures/cc0/Rocks002_1K_Displacement.jpg" + }, + "layer3_roughness": { + "textureMap": "TestData/Textures/cc0/Rocks002_1K_Roughness.jpg" + }, + "layer3_uv": { + "scale": 3.4999988079071047 + }, + "parallax": { + "algorithm": "Relief", + "enable": true, + "pdo": true, + "quality": "Low" + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer2Off.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer2Off.material new file mode 100644 index 0000000000..9413e35128 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer2Off.material @@ -0,0 +1,11 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "enableLayer2": false + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer3Off.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer3Off.material new file mode 100644 index 0000000000..93e0b21780 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_Layer3Off.material @@ -0,0 +1,11 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "enableLayer3": false + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material new file mode 100644 index 0000000000..6b062f6d1e --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material @@ -0,0 +1,14 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "blendSource": "Displacement_With_BlendMaskTexture" + }, + "layer1_parallax": { + "offset": -0.004000000189989805 + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material new file mode 100644 index 0000000000..0e6519afd4 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_AllSameHeight.material @@ -0,0 +1,23 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "displacementBlendDistance": 0.0010000000474974514 + }, + "layer1_parallax": { + "offset": -0.00800000037997961, + "textureMap": "" + }, + "layer2_parallax": { + "offset": -0.00800000037997961, + "textureMap": "" + }, + "layer3_parallax": { + "offset": -0.00800000037997961, + "textureMap": "" + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material new file mode 100644 index 0000000000..b5b5656084 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture_NoHeightmaps.material @@ -0,0 +1,20 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskTexture.material", + "propertyLayoutVersion": 3, + "properties": { + "layer1_parallax": { + "offset": -0.03200000151991844, + "textureMap": "" + }, + "layer2_parallax": { + "offset": -0.00800000037997961, + "textureMap": "" + }, + "layer3_parallax": { + "offset": -0.00800000037997961, + "textureMap": "" + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material new file mode 100644 index 0000000000..8461ea429c --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement_With_BlendMaskVertexColors.material @@ -0,0 +1,15 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardMultilayerPBR.materialtype", + "parentMaterial": "TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material", + "propertyLayoutVersion": 3, + "properties": { + "blend": { + "blendSource": "Displacement_With_BlendMaskVertexColors", + "displacementBlendDistance": 0.02387000061571598 + }, + "parallax": { + "enable": false + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Textures/Foliage_Leaves_0_BaseColor.dds.assetinfo b/Gems/Atom/TestData/TestData/Textures/Foliage_Leaves_0_BaseColor.dds.assetinfo index 2ec31e38ce..1aa896a8d7 100644 --- a/Gems/Atom/TestData/TestData/Textures/Foliage_Leaves_0_BaseColor.dds.assetinfo +++ b/Gems/Atom/TestData/TestData/Textures/Foliage_Leaves_0_BaseColor.dds.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg new file mode 100644 index 0000000000..04d871dd2b --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_AmbientOcclusion.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9ec269d03a9552c0ecf24778912fa6190c412b006433db8b7c40e1c0c83e6f7 +size 516915 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Color.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Color.jpg new file mode 100644 index 0000000000..d41658d177 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Color.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b53c4aca020d5833618a5b73b6578c8693dd14e603eb32681e2c7ecc90f59047 +size 1020622 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Displacement.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Displacement.jpg new file mode 100644 index 0000000000..913b35875c --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Displacement.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46ea8a9406ce6df21ce3a6045aac5b1421ce119919ff050951277dd76464ee2c +size 258716 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Normal.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Normal.jpg new file mode 100644 index 0000000000..7c216001a9 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Normal.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac1ad9bea240374bfc6aaaacc42e24eadfbf93c7185617fc1c52e610cb45cb69 +size 1292910 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Roughness.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Roughness.jpg new file mode 100644 index 0000000000..5ac9e78409 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Ground033_1K_Roughness.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8fce266a7445a4d4b5bb3fbf7cb3330e0580b058aeaf2ef7f265a01641dbbdc4 +size 637326 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg new file mode 100644 index 0000000000..772529329e --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_AmbientOcclusion.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca54f762bcddc10ab2d609f10864328cb5a567c43efb8c9bcfe9cb2955db9577 +size 433887 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Color.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Color.jpg new file mode 100644 index 0000000000..8d1d23451d --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Color.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b5f5ff297aef6470045d087cf0c3341f7782e36a750965a052d49d03dd37426 +size 1595449 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Displacement.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Displacement.jpg new file mode 100644 index 0000000000..22304c19dd --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Displacement.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c8753448320e0916a70036ef77a06bce746bfa45c14e62b2fbda0987a13bfbb3 +size 277114 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Normal.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Normal.jpg new file mode 100644 index 0000000000..129ecbb1b7 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Normal.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ea23ea8d85d1fffa119e481e6ac85ad3a3096470a5e12f252d37e1b293e5e37 +size 2119669 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Roughness.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Roughness.jpg new file mode 100644 index 0000000000..dc5f8c20a9 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Rocks002_1K_Roughness.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:caa6e94f904135461da4d200fc6c21c86dc99cc7d413ea740e678f7758b2b156 +size 555680 diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/CMakeLists.txt b/Gems/AtomLyIntegration/AtomBridge/Code/CMakeLists.txt index c431746b40..0723ca46b7 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/AtomBridge/Code/CMakeLists.txt @@ -106,5 +106,6 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) Gem::AtomFont Gem::AtomToolsFramework.Editor Gem::AtomViewportDisplayInfo + Gem::AtomViewportDisplayIcons.Editor ) endif() diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Include/AtomBridge/PerViewportDynamicDrawInterface.h b/Gems/AtomLyIntegration/AtomBridge/Code/Include/AtomBridge/PerViewportDynamicDrawInterface.h new file mode 100644 index 0000000000..f77e0b0b88 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Include/AtomBridge/PerViewportDynamicDrawInterface.h @@ -0,0 +1,44 @@ +/* +* 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 + +namespace AZ::AtomBridge +{ + //! A simple interface for allocating a DynamicDrawContext on-demand for every viewport, based on + //! a registered initialization function. + class PerViewportDynamicDrawInterface + { + public: + AZ_RTTI(PerViewportDynamicDrawInterface, "{1FF054F5-55FF-4ADB-A86D-640B15FA0395}"); + + using DrawContextFactory = AZStd::function)>; + //! Register a named dynamic draw context that can be retrieved on a per-viewport basis. + //! GetNamedDynamicDraw context can be called on a registered context name to retrieve a + //! valid DynamicDrawContext for a given viewport. + virtual void RegisterDynamicDrawContext(AZ::Name name, DrawContextFactory contextInitializer) = 0; + + //! Unregister a previously registered named per-viewport dynamic draw context. + //! This will dispose of all dynamic draw contexts currently associated with this name. + virtual void UnregisterDynamicDrawContext(AZ::Name name) = 0; + + //! Get a dynamic draw context associated with the specified viewport based on a factory registered with + //! RegisterNamedDynamicDrawContext. This dynamic draw context will be created if it does not already exist. + virtual RHI::Ptr GetDynamicDrawContextForViewport(AZ::Name name, AzFramework::ViewportId viewportId) = 0; + }; + + using PerViewportDynamicDraw = AZ::Interface; +} // namespace AZ::AtomBridge diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.cpp index 4a19c08174..5116d8a228 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -104,10 +105,12 @@ namespace AZ AzFramework::GameEntityContextRequestBus::BroadcastResult(m_entityContextId, &AzFramework::GameEntityContextRequestBus::Events::GetGameEntityContextId); AZ::Render::Bootstrap::NotificationBus::Handler::BusConnect(); + m_dynamicDrawManager = AZStd::make_unique(); } void AtomBridgeSystemComponent::Deactivate() { + m_dynamicDrawManager.reset(); AZ::RPI::ViewportContextManagerNotificationsBus::Handler::BusDisconnect(); RPI::Scene* scene = RPI::RPISystemInterface::Get()->GetDefaultScene().get(); // Check if scene is emptry since scene might be released already when running AtomSampleViewer diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.h b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.h index da75d3c35c..4d05ba9285 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.h +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.h @@ -33,6 +33,7 @@ namespace AZ { // forward declares class AtomDebugDisplayViewportInterface; + class PerViewportDynamicDrawManager; class AtomBridgeSystemComponent : public Component @@ -82,6 +83,7 @@ namespace AZ RPI::ViewPtr m_view = nullptr; AZStd::unordered_map > m_activeViewportsList; + AZStd::unique_ptr m_dynamicDrawManager; }; } } // namespace AZ diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/PerViewportDynamicDrawManager.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/PerViewportDynamicDrawManager.cpp new file mode 100644 index 0000000000..b6ff116a86 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/PerViewportDynamicDrawManager.cpp @@ -0,0 +1,119 @@ +/* +* 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 "PerViewportDynamicDrawManager.h" + +#include +#include + +namespace AZ::AtomBridge +{ + PerViewportDynamicDrawManager::PerViewportDynamicDrawManager() + { + PerViewportDynamicDraw::Register(this); + } + + PerViewportDynamicDrawManager::~PerViewportDynamicDrawManager() + { + PerViewportDynamicDraw::Unregister(this); + } + + void PerViewportDynamicDrawManager::RegisterDynamicDrawContext(AZ::Name name, DrawContextFactory contextInitializer) + { + AZStd::lock_guard lock(m_mutexDrawContexts); + + const bool alreadyRegistered = m_registeredDrawContexts.find(name) != m_registeredDrawContexts.end(); + AZ_Error("AtomBridge", !alreadyRegistered, "Attempted to call RegisterDynamicDrawContext for already registered name: \"%s\"", name.GetCStr()); + if (alreadyRegistered) + { + return; + } + m_registeredDrawContexts[name] = contextInitializer; + } + + void PerViewportDynamicDrawManager::UnregisterDynamicDrawContext(AZ::Name name) + { + AZStd::lock_guard lock(m_mutexDrawContexts); + + auto drawContextFactoryIt = m_registeredDrawContexts.find(name); + const bool registered = drawContextFactoryIt != m_registeredDrawContexts.end(); + AZ_Error("AtomBridge", registered, "Attempted to call UnregisterDynamicDrawContext for unregistered name: \"%s\"", name.GetCStr()); + if (!registered) + { + return; + } + m_registeredDrawContexts.erase(drawContextFactoryIt); + + for (auto& viewportData : m_viewportData) + { + viewportData.second.m_dynamicDrawContexts.erase(name); + } + } + + RHI::Ptr PerViewportDynamicDrawManager::GetDynamicDrawContextForViewport( + AZ::Name name, AzFramework::ViewportId viewportId) + { + AZStd::lock_guard lock(m_mutexDrawContexts); + + auto contextFactoryIt = m_registeredDrawContexts.find(name); + if (contextFactoryIt == m_registeredDrawContexts.end()) + { + return nullptr; + } + + auto viewportContextManager = RPI::ViewportContextRequests::Get(); + RPI::ViewportContextPtr viewportContext = viewportContextManager->GetViewportContextById(viewportId); + if (viewportContext == nullptr) + { + return nullptr; + } + + // Get or create a ViewportData if one doesn't already exist + ViewportData& viewportData = m_viewportData[viewportId]; + if (!viewportData.m_initialized) + { + viewportData.m_pipelineChangedHandler = AZ::Event::Handler([this, viewportId](RPI::RenderPipelinePtr pipeline) + { + AZStd::lock_guard lock(m_mutexDrawContexts); + ViewportData& viewportData = m_viewportData[viewportId]; + for (auto& context : viewportData.m_dynamicDrawContexts) + { + context.second->SetRenderPipeline(pipeline.get()); + } + }); + viewportData.m_viewportDestroyedHandler = AZ::Event::Handler([this, viewportId](AzFramework::ViewportId id) + { + AZStd::lock_guard lock(m_mutexDrawContexts); + m_viewportData.erase(id); + }); + + viewportContext->ConnectCurrentPipelineChangedHandler(viewportData.m_pipelineChangedHandler); + viewportContext->ConnectAboutToBeDestroyedHandler(viewportData.m_viewportDestroyedHandler); + + viewportData.m_initialized = true; + } + + RHI::Ptr& context = viewportData.m_dynamicDrawContexts[name]; + if (context == nullptr) + { + auto pipeline = viewportContext->GetCurrentPipeline().get(); + if (pipeline == nullptr) + { + return nullptr; + } + context = RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(pipeline); + contextFactoryIt->second(context); + } + + return context; + } +} //namespace AZ::AtomBridge diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/PerViewportDynamicDrawManager.h b/Gems/AtomLyIntegration/AtomBridge/Code/Source/PerViewportDynamicDrawManager.h new file mode 100644 index 0000000000..e2b442915c --- /dev/null +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/PerViewportDynamicDrawManager.h @@ -0,0 +1,48 @@ +/* +* 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::AtomBridge +{ + class PerViewportDynamicDrawManager final : public PerViewportDynamicDrawInterface + { + public: + AZ_TYPE_INFO(PerViewportDynamicDrawManager, "{BED66185-00A7-43F7-BD28-C56BC8E4C535}"); + + PerViewportDynamicDrawManager(); + ~PerViewportDynamicDrawManager(); + + // PerViewportDynamicDrawInterface overrides... + void RegisterDynamicDrawContext(AZ::Name name, DrawContextFactory contextInitializer) override; + void UnregisterDynamicDrawContext(AZ::Name name) override; + RHI::Ptr GetDynamicDrawContextForViewport(AZ::Name name, AzFramework::ViewportId viewportId) override; + + private: + struct ViewportData + { + AZStd::unordered_map> m_dynamicDrawContexts; + + // Event handlers + AZ::Event::Handler m_pipelineChangedHandler; + AZ::Event::Handler m_viewportDestroyedHandler; + + // Cached state + bool m_initialized = false; + }; + AZStd::map m_viewportData; + AZStd::unordered_map m_registeredDrawContexts; + AZStd::mutex m_mutexDrawContexts; + }; +} //namespace AZ::AtomBridge diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/atombridge_files.cmake b/Gems/AtomLyIntegration/AtomBridge/Code/atombridge_files.cmake index f272d323ae..969030f922 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/atombridge_files.cmake +++ b/Gems/AtomLyIntegration/AtomBridge/Code/atombridge_files.cmake @@ -12,10 +12,13 @@ set(FILES Include/AtomBridge/AtomBridgeBus.h Include/AtomBridge/FlyCameraInputBus.h + Include/AtomBridge/PerViewportDynamicDrawInterface.h Source/AtomBridgeSystemComponent.cpp Source/AtomBridgeSystemComponent.h - Source/FlyCameraInputComponent.cpp - Source/FlyCameraInputComponent.h Source/AtomDebugDisplayViewportInterface.cpp Source/AtomDebugDisplayViewportInterface.h + Source/FlyCameraInputComponent.cpp + Source/FlyCameraInputComponent.h + Source/PerViewportDynamicDrawManager.cpp + Source/PerViewportDynamicDrawManager.h ) diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp index 3c76a9c788..623a931ac9 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp @@ -896,7 +896,7 @@ AZ::RHI::Ptr AZ::AtomFont::GetOrCreateDynamicDrawFo shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("false"))); shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("true"))); dynamicDraw->InitShaderWithVariant(shader, &shaderOptions); - dynamicDraw->InitVertexFormat({{"POSITION", RHI::Format::R32G32B32_FLOAT}, {"COLOR", RHI::Format::R8G8B8A8_UNORM}, {"TEXCOORD0", RHI::Format::R32G32_FLOAT}}); + dynamicDraw->InitVertexFormat({{"POSITION", RHI::Format::R32G32B32_FLOAT}, {"COLOR", RHI::Format::B8G8R8A8_UNORM}, {"TEXCOORD0", RHI::Format::R32G32_FLOAT}}); dynamicDraw->EndInit(); // exclusive lock while writing diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index f8afaa7260..31eb089803 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -54,7 +54,6 @@ #include -static const AZ::Vector2 UiDraw_TextSizeFactor = AZ::Vector2(12.0f, 12.0f); static const int TabCharCount = 4; // set buffer sizes to hold max characters that can be drawn in 1 DrawString call static const size_t MaxVerts = 8 * 1024; // 2048 quads @@ -864,7 +863,7 @@ int AZ::FFont::CreateQuadsForText(const RHI::Viewport& viewport, float x, float if (drawFrame) { ColorB tempColor(255, 255, 255, 255); - uint32_t frameColor = tempColor.pack_abgr8888(); //note: this ends up in r,g,b,a order on little-endian machines + uint32_t frameColor = tempColor.pack_argb8888(); //note: this ends up in r,g,b,a order on little-endian machines Vec2 textSize = GetTextSizeUInternal(viewport, str, asciiMultiLine, ctx); @@ -1122,7 +1121,7 @@ int AZ::FFont::CreateQuadsForText(const RHI::Viewport& viewport, float x, float { ColorB tempColor = color; tempColor.a = ((uint32_t) tempColor.a * alphaBlend) >> 8; - packedColor = tempColor.pack_abgr8888(); //note: this ends up in r,g,b,a order on little-endian machines + packedColor = tempColor.pack_argb8888(); //note: this ends up in r,g,b,a order on little-endian machines } if (ctx.m_drawTextFlags & eDrawText_UseTransform) @@ -1673,6 +1672,12 @@ static void SetCommonContextFlags(AZ::TextDrawContext& ctx, const AzFramework::T { ctx.m_drawTextFlags |= eDrawText_FixedSize; } + + if (params.m_useTransform) + { + ctx.m_drawTextFlags |= eDrawText_UseTransform; + ctx.SetTransform(AZMatrix3x4ToLYMatrix3x4(params.m_transform)); + } } AZ::FFont::DrawParameters AZ::FFont::ExtractDrawParameters(const AzFramework::TextDrawParameters& params, AZStd::string_view text, bool forceCalculateSize) @@ -1696,22 +1701,25 @@ AZ::FFont::DrawParameters AZ::FFont::ExtractDrawParameters(const AzFramework::Te } internalParams.m_ctx.SetBaseState(GS_NODEPTHTEST); internalParams.m_ctx.SetColor(AZColorToLYColorF(params.m_color)); + internalParams.m_ctx.SetEffect(params.m_effectIndex); internalParams.m_ctx.SetCharWidthScale((params.m_monospace || params.m_scaleWithWindow) ? 0.5f : 1.0f); internalParams.m_ctx.EnableFrame(false); internalParams.m_ctx.SetProportional(!params.m_monospace && params.m_scaleWithWindow); internalParams.m_ctx.SetSizeIn800x600(params.m_scaleWithWindow && params.m_virtual800x600ScreenSize); - internalParams.m_ctx.SetSize(AZVec2ToLYVec2(UiDraw_TextSizeFactor * params.m_scale)); + internalParams.m_ctx.SetSize(AZVec2ToLYVec2(AZ::Vector2(params.m_textSizeFactor, params.m_textSizeFactor) * params.m_scale)); internalParams.m_ctx.SetLineSpacing(params.m_lineSpacing); - if (params.m_monospace || !params.m_scaleWithWindow) - { - ScaleCoord(viewport, posX, posY); - } if (params.m_hAlign != AzFramework::TextHorizontalAlignment::Left || params.m_vAlign != AzFramework::TextVerticalAlignment::Top || forceCalculateSize) { + // We align based on the size of the default font effect because we do not want the + // text to move when the font effect is changed + unsigned int effectIndex = internalParams.m_ctx.m_fxIdx; + internalParams.m_ctx.SetEffect(0); Vec2 textSize = GetTextSizeUInternal(viewport, text.data(), params.m_multiline, internalParams.m_ctx); + internalParams.m_ctx.SetEffect(effectIndex); + // If we're using virtual 800x600 coordinates, convert the text size from // pixels to that before using it as an offset. if (internalParams.m_ctx.m_sizeIn800x600) diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Assets/Shaders/TexturedIcon.azsl b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Assets/Shaders/TexturedIcon.azsl new file mode 100644 index 0000000000..c4367efe6b --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Assets/Shaders/TexturedIcon.azsl @@ -0,0 +1,77 @@ +/* + * 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 + +ShaderResourceGroup InstanceSrg : SRG_PerDraw +{ + float2 m_viewportSize; + Texture2D m_texture; + + Sampler m_sampler + { + MaxAnisotropy = 16; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; +}; + +struct VSInput +{ + float3 m_position : POSITION; + float4 m_color : COLOR0; + float2 m_uv : TEXCOORD0; +}; + +struct VSOutput +{ + float4 m_position : SV_Position; + float4 m_color : COLOR0; + float2 m_uv : TEXCOORD0; +}; + +VSOutput MainVS(VSInput IN) +{ + // Convert from screen space to clip space + float2 posXY = float2(IN.m_position.xy) / InstanceSrg::m_viewportSize * 2.0f - float2(1.0f, 1.0f); + posXY.y *= -1.0f; + float4 posPS = float4(posXY, IN.m_position.z, 1.0f); + + VSOutput OUT; + OUT.m_position = posPS; + OUT.m_color = IN.m_color; + OUT.m_uv = IN.m_uv; + return OUT; +}; + +struct PSOutput +{ + float4 m_color : SV_Target0; +}; + +PSOutput MainPS(VSOutput IN) +{ + PSOutput OUT; + + float4 tex; + + tex = InstanceSrg::m_texture.Sample(InstanceSrg::m_sampler, IN.m_uv); + float opacity = IN.m_color.a * tex.a; + + // We use pre-multiplied alpha here since it is more flexible. For example, it enables alpha-blended rendering to + // a render target and then alpha blending that render target into another render target + OUT.m_color.rgb = IN.m_color.rgb * tex.rgb * opacity; + + OUT.m_color.a = opacity; + return OUT; +}; diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Assets/Shaders/TexturedIcon.shader b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Assets/Shaders/TexturedIcon.shader new file mode 100644 index 0000000000..601a2664b5 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Assets/Shaders/TexturedIcon.shader @@ -0,0 +1,39 @@ +{ + "Source" : "TexturedIcon", + + "DepthStencilState" : { + "Depth" : { + "Enable" : false, + "CompareFunc" : "Always" + } + }, + + "RasterState" : { + "DepthClipEnable" : false, + "CullMode" : "None" + }, + + "BlendState" : { + "Enable" : true, + "BlendSource" : "One", + "BlendDest" : "AlphaSourceInverse", + "BlendOp" : "Add" + }, + + "DrawList" : "2dpass", + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + }, + { + "name": "MainPS", + "type": "Fragment" + } + ] + } +} diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/CMakeLists.txt b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/CMakeLists.txt new file mode 100644 index 0000000000..20a680bce9 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# 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. +# + +add_subdirectory(Code) diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/CMakeLists.txt b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/CMakeLists.txt new file mode 100644 index 0000000000..b3e176c7a3 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/CMakeLists.txt @@ -0,0 +1,35 @@ +# +# 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. +# + +if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_add_target( + NAME AtomViewportDisplayIcons.Editor ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} + NAMESPACE Gem + FILES_CMAKE + atomviewportdisplayicons_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Source + BUILD_DEPENDENCIES + PRIVATE + AZ::AzCore + AZ::AzFramework + AZ::AzToolsFramework + AZ::AtomCore + 3rdParty::Qt::Core + 3rdParty::Qt::Gui + 3rdParty::Qt::Svg + Gem::Atom_RHI.Reflect + Gem::Atom_RPI.Public + Gem::Atom_Bootstrap.Headers + Gem::Atom_AtomBridge.Static + ) +endif() diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp new file mode 100644 index 0000000000..dce83c3072 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp @@ -0,0 +1,339 @@ +/* + * 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 "AtomViewportDisplayIconsSystemComponent.h" + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace AZ::Render +{ + void AtomViewportDisplayIconsSystemComponent::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serialize = azrtti_cast(context)) + { + serialize->Class() + ->Version(0) + ; + + if (AZ::EditContext* ec = serialize->GetEditContext()) + { + ec->Class("Viewport Display Icons", "Provides an interface for drawing simple icons to the Editor viewport") + ->ClassElement(Edit::ClassElements::EditorData, "") + ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) + ->Attribute(Edit::Attributes::AutoExpand, true) + ; + } + } + } + + void AtomViewportDisplayIconsSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC("ViewportDisplayIconsService")); + } + + void AtomViewportDisplayIconsSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC("ViewportDisplayIconsService")); + } + + void AtomViewportDisplayIconsSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + required.push_back(AZ_CRC("RPISystem", 0xf2add773)); + required.push_back(AZ_CRC("AtomBridgeService", 0xdb816a99)); + } + + void AtomViewportDisplayIconsSystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent) + { + } + + void AtomViewportDisplayIconsSystemComponent::Activate() + { + AzToolsFramework::EditorViewportIconDisplay::Register(this); + + Bootstrap::NotificationBus::Handler::BusConnect(); + } + + void AtomViewportDisplayIconsSystemComponent::Deactivate() + { + Bootstrap::NotificationBus::Handler::BusDisconnect(); + + auto perViewportDynamicDrawInterface = AtomBridge::PerViewportDynamicDraw::Get(); + if (!perViewportDynamicDrawInterface) + { + return; + } + if (perViewportDynamicDrawInterface) + { + perViewportDynamicDrawInterface->UnregisterDynamicDrawContext(m_drawContextName); + } + + AzToolsFramework::EditorViewportIconDisplay::Unregister(this); + } + + void AtomViewportDisplayIconsSystemComponent::DrawIcon(const DrawParameters& drawParameters) + { + // Ensure we have a valid viewport context & dynamic draw interface + auto viewportContext = RPI::ViewportContextRequests::Get()->GetViewportContextById(drawParameters.m_viewport); + if (viewportContext == nullptr) + { + return; + } + + auto perViewportDynamicDrawInterface = + AtomBridge::PerViewportDynamicDraw::Get(); + if (!perViewportDynamicDrawInterface) + { + return; + } + + RHI::Ptr dynamicDraw = + perViewportDynamicDrawInterface->GetDynamicDrawContextForViewport(m_drawContextName, drawParameters.m_viewport); + if (dynamicDraw == nullptr) + { + return; + } + + // Find our icon, falling back on a grey placeholder if its image is unavailable + AZ::Data::Instance image = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::Grey); + if (auto iconIt = m_iconData.find(drawParameters.m_icon); iconIt != m_iconData.end()) + { + auto& iconData = iconIt->second; + if (iconData.m_image) + { + image = iconData.m_image; + } + } + else + { + return; + } + + // Initialize our shader + auto viewportSize = viewportContext->GetViewportSize(); + AZ::Data::Instance drawSrg = dynamicDraw->NewDrawSrg(); + drawSrg->SetConstant(m_viewportSizeIndex, AZ::Vector2(aznumeric_cast(viewportSize.m_width), aznumeric_cast(viewportSize.m_height))); + drawSrg->SetImageView(m_textureParameterIndex, image->GetImageView()); + drawSrg->Compile(); + + AZ::Vector3 screenPosition; + if (drawParameters.m_positionSpace == CoordinateSpace::ScreenSpace) + { + screenPosition = drawParameters.m_position; + } + else if (drawParameters.m_positionSpace == CoordinateSpace::WorldSpace) + { + using ViewportRequestBus = AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus; + AzFramework::ScreenPoint position; + ViewportRequestBus::EventResult(position, drawParameters.m_viewport, &ViewportRequestBus::Events::ViewportWorldToScreen, drawParameters.m_position); + screenPosition.SetX(aznumeric_cast(position.m_x)); + screenPosition.SetY(aznumeric_cast(position.m_y)); + } + + struct Vertex + { + float m_position[3]; + AZ::u32 m_color; + float m_uv[2]; + }; + using Indice = AZ::u16; + + // Create a vertex offset from the position to draw from based on the icon size + // Vertex positions are in screen space coordinates + auto createVertex = [&](float offsetX, float offsetY, float u, float v) -> Vertex + { + Vertex vertex; + screenPosition.StoreToFloat3(vertex.m_position); + vertex.m_position[0] += offsetX * drawParameters.m_size.GetX(); + vertex.m_position[1] += offsetY * drawParameters.m_size.GetY(); + vertex.m_color = drawParameters.m_color.ToU32(); + vertex.m_uv[0] = u; + vertex.m_uv[1] = v; + return vertex; + }; + + AZStd::array vertices = { + createVertex(-0.5f, -0.5f, 0.f, 0.f), + createVertex(0.5f, -0.5f, 1.f, 0.f), + createVertex(0.5f, 0.5f, 1.f, 1.f), + createVertex(-0.5f, 0.5f, 0.f, 1.f) + }; + AZStd::array indices = {0, 1, 2, 0, 2, 3}; + dynamicDraw->DrawIndexed(&vertices, vertices.size(), &indices, indices.size(), RHI::IndexFormat::Uint16, drawSrg); + } + + QString AtomViewportDisplayIconsSystemComponent::FindAssetPath(const QString& sourceRelativePath) const + { + bool found = false; + AZStd::vector scanFolders; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult( + found, &AzToolsFramework::AssetSystemRequestBus::Events::GetScanFolders, scanFolders); + if (!found) + { + AZ_Error("AtomViewportDisplayIconSystemComponent", false, "Failed to load asset scan folders"); + return QString(); + } + + for (const auto& folder : scanFolders) + { + QDir dir(folder.data()); + if (dir.exists(sourceRelativePath)) + { + return dir.absoluteFilePath(sourceRelativePath); + } + } + + return QString(); + } + + QImage AtomViewportDisplayIconsSystemComponent::RenderSvgToImage(const QString& svgPath) const + { + // Set up our SVG renderer + QSvgRenderer renderer(svgPath); + renderer.setAspectRatioMode(Qt::KeepAspectRatio); + + // Set up our target image + QSize size = renderer.defaultSize().expandedTo(MinimumRenderedSvgSize); + QImage image(size, QtImageFormat); + image.fill(0x00000000); + + // Render the SVG + QPainter painter(&image); + renderer.render(&painter); + return image; + } + + AZ::Data::Instance AtomViewportDisplayIconsSystemComponent::ConvertToAtomImage(AZ::Uuid assetId, QImage image) const + { + // Ensure our image is in the correct pixel format so we can memcpy it to our renderer image + image.convertTo(QtImageFormat); + Data::Instance streamingImagePool = RPI::ImageSystemInterface::Get()->GetSystemStreamingPool(); + return RPI::StreamingImage::CreateFromCpuData( + *streamingImagePool.get(), + RHI::ImageDimension::Image2D, + RHI::Size(image.width(), image.height(), 1), + RHI::Format::R8G8B8A8_UNORM_SRGB, + image.bits(), + image.sizeInBytes(), + assetId); + } + + AzToolsFramework::EditorViewportIconDisplayInterface::IconId AtomViewportDisplayIconsSystemComponent::GetOrLoadIconForPath( + AZStd::string_view path) + { + AZ_Error( + "AtomViewportDisplayIconsSystemComponent", AzFramework::StringFunc::Path::IsRelative(path.data()), + "GetOrLoadIconForPath assumes that it will always be given a relative path, but got '%s'", path.data()); + + // Check our cache to see if the image is already loaded + auto existingEntryIt = AZStd::find_if(m_iconData.begin(), m_iconData.end(), [&path](const auto& iconData) + { + return iconData.second.m_path == path; + }); + if (existingEntryIt != m_iconData.end()) + { + return existingEntryIt->first; + } + + AZ::Uuid assetId = AZ::Uuid::CreateName(path.data()); + + // Find the asset to load on disk + QString assetPath = FindAssetPath(path.data()); + if (assetPath.isEmpty()) + { + AZ_Error("AtomViewportDisplayIconSystemComponent", false, "Failed to locate icon on disk: \"%s\"", path.data()); + return InvalidIconId; + } + + QImage loadedImage; + + AZStd::string extension; + AzFramework::StringFunc::Path::GetExtension(path.data(), extension, false); + // For SVGs, we need to actually rasterize to an image + if (extension == "svg") + { + loadedImage = RenderSvgToImage(assetPath); + } + // For everything else, we can just load it through QImage via its image plugins + else + { + const bool loaded = loadedImage.load(assetPath); + if (!loaded) + { + AZ_Error("AtomViewportDisplayIconSystemComponent", false, "Failed to load icon: \"%s\"", assetPath.toUtf8().constData()); + return InvalidIconId; + } + } + + // Cache our loaded icon + IconId id = m_currentId++; + IconData& iconData = m_iconData[id]; + iconData.m_path = path; + iconData.m_image = ConvertToAtomImage(assetId, loadedImage); + return id; + } + + AzToolsFramework::EditorViewportIconDisplayInterface::IconLoadStatus AtomViewportDisplayIconsSystemComponent::GetIconLoadStatus( + IconId icon) + { + auto iconIt = m_iconData.find(icon); + if (iconIt == m_iconData.end()) + { + return IconLoadStatus::Unloaded; + } + if (iconIt->second.m_image) + { + return IconLoadStatus::Loaded; + } + return IconLoadStatus::Error; + } + + void AtomViewportDisplayIconsSystemComponent::OnBootstrapSceneReady([[maybe_unused]]AZ::RPI::Scene* bootstrapScene) + { + AtomBridge::PerViewportDynamicDraw::Get()->RegisterDynamicDrawContext(m_drawContextName, [](RPI::Ptr drawContext) + { + auto shader = RPI::LoadShader(DrawContextShaderPath); + drawContext->InitShader(shader); + drawContext->InitVertexFormat( + {{"POSITION", RHI::Format::R32G32B32_FLOAT}, + {"COLOR", RHI::Format::R8G8B8A8_UNORM}, + {"TEXCOORD", RHI::Format::R32G32_FLOAT}}); + drawContext->EndInit(); + }); + } +} // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h new file mode 100644 index 0000000000..0c7366f23b --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h @@ -0,0 +1,82 @@ +/* + * 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 + +#include +#include +#include + +namespace AZ +{ + class TickRequests; + + namespace Render + { + class AtomViewportDisplayIconsSystemComponent + : public AZ::Component + , public AzToolsFramework::EditorViewportIconDisplayInterface + , public AZ::Render::Bootstrap::NotificationBus::Handler + { + public: + AZ_COMPONENT(AtomViewportDisplayIconsSystemComponent, "{AEC1D3E1-1D9A-437A-B4C6-CFAEE620C160}"); + + 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); + + protected: + // AZ::Component overrides... + void Activate() override; + void Deactivate() override; + + // AzToolsFramework::EditorViewportIconDisplayInterface overrides... + void DrawIcon(const DrawParameters& drawParameters) override; + IconId GetOrLoadIconForPath(AZStd::string_view path) override; + IconLoadStatus GetIconLoadStatus(IconId icon) override; + + // AZ::Render::Bootstrap::NotificationBus::Handler overrides... + void OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) override; + + private: + static constexpr const char* DrawContextShaderPath = "Shaders/TexturedIcon.azshader"; + static constexpr QSize MinimumRenderedSvgSize = QSize(128, 128); + static constexpr QImage::Format QtImageFormat = QImage::Format_RGBA8888; + + QString FindAssetPath(const QString& sourceRelativePath) const; + QImage RenderSvgToImage(const QString& svgPath) const; + AZ::Data::Instance ConvertToAtomImage(AZ::Uuid assetId, QImage image) const; + + Name m_drawContextName = Name("ViewportIconDisplay"); + bool m_shaderIndexesInitialized = false; + RHI::ShaderInputNameIndex m_textureParameterIndex = "m_texture"; + RHI::ShaderInputNameIndex m_viewportSizeIndex = "m_viewportSize"; + + struct IconData + { + AZStd::string m_path; + AZ::Data::Instance m_image = nullptr; + }; + AZStd::unordered_map m_iconData; + IconId m_currentId = 0; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/Module.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/Module.cpp new file mode 100644 index 0000000000..db7672186a --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/Module.cpp @@ -0,0 +1,51 @@ +/* + * 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 "AtomViewportDisplayIconsSystemComponent.h" + +namespace AZ +{ + namespace Render + { + class AtomViewportDisplayInfoModule + : public AZ::Module + { + public: + AZ_RTTI(AtomViewportDisplayInfoModule, "{8D72F14E-958D-4225-B3BC-C5C87BDDD426}", AZ::Module); + AZ_CLASS_ALLOCATOR(AtomViewportDisplayInfoModule, AZ::SystemAllocator, 0); + + AtomViewportDisplayInfoModule() + : AZ::Module() + { + m_descriptors.insert(m_descriptors.end(), { + AtomViewportDisplayIconsSystemComponent::CreateDescriptor(), + }); + } + + AZ::ComponentTypeList GetRequiredSystemComponents() const override + { + return AZ::ComponentTypeList{ + azrtti_typeid(), + }; + } + }; + } // namespace Render +} // namespace AZ + +// DO NOT MODIFY THIS LINE UNLESS YOU RENAME THE GEM +// The first parameter should be GemName_GemIdLower +// The second should be the fully qualified name of the class above +AZ_DECLARE_MODULE_CLASS(Gem_AtomViewportDisplayInfo, AZ::Render::AtomViewportDisplayInfoModule) diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/atomviewportdisplayicons_files.cmake b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/atomviewportdisplayicons_files.cmake new file mode 100644 index 0000000000..f02aed0856 --- /dev/null +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/atomviewportdisplayicons_files.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(FILES + Source/AtomViewportDisplayIconsSystemComponent.cpp + Source/AtomViewportDisplayIconsSystemComponent.h + Source/Module.cpp +) diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json deleted file mode 100644 index dd92a99ea9..0000000000 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "gem_name": "AtomLyIntegration_AtomViewportDisplayInfo", - "display_name": "Atom Viewport Display Info Overlay", - "summary": "Provides a diagnostic viewport overlay for the default O3DE Atom viewport.", - "canonical_tags": [ - "Gem" - ], - "user_tags": [ - "AtomLyIntegration", - "AtomViewportDisplayInfo" - ] -} \ No newline at end of file diff --git a/Gems/AtomLyIntegration/CMakeLists.txt b/Gems/AtomLyIntegration/CMakeLists.txt index 35022e643b..ff6800a7ff 100644 --- a/Gems/AtomLyIntegration/CMakeLists.txt +++ b/Gems/AtomLyIntegration/CMakeLists.txt @@ -17,3 +17,4 @@ add_subdirectory(AtomFont) add_subdirectory(TechnicalArt) add_subdirectory(AtomBridge) add_subdirectory(AtomViewportDisplayInfo) +add_subdirectory(AtomViewportDisplayIcons) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/DiffuseProbeGridComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/DiffuseProbeGridComponentController.cpp index 0ddace1f87..5fb835de15 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/DiffuseProbeGridComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/DiffuseProbeGridComponentController.cpp @@ -44,7 +44,17 @@ namespace AZ ->Field("AmbientMultiplier", &DiffuseProbeGridComponentConfig::m_ambientMultiplier) ->Field("ViewBias", &DiffuseProbeGridComponentConfig::m_viewBias) ->Field("NormalBias", &DiffuseProbeGridComponentConfig::m_normalBias) - ; + ->Field("EditorMode", &DiffuseProbeGridComponentConfig::m_editorMode) + ->Field("RuntimeMode", &DiffuseProbeGridComponentConfig::m_runtimeMode) + ->Field("BakedIrradianceTextureRelativePath", &DiffuseProbeGridComponentConfig::m_bakedIrradianceTextureRelativePath) + ->Field("BakedDistanceTextureRelativePath", &DiffuseProbeGridComponentConfig::m_bakedDistanceTextureRelativePath) + ->Field("BakedRelocationTextureRelativePath", &DiffuseProbeGridComponentConfig::m_bakedRelocationTextureRelativePath) + ->Field("BakedClassificationTextureRelativePath", &DiffuseProbeGridComponentConfig::m_bakedClassificationTextureRelativePath) + ->Field("BakedIrradianceTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedIrradianceTextureAsset) + ->Field("BakedDistanceTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedDistanceTextureAsset) + ->Field("BakedRelocationTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedRelocationTextureAsset) + ->Field("BakedClassificationTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedClassificationTextureAsset) + ; } } @@ -110,6 +120,26 @@ namespace AZ m_boxShapeInterface = LmbrCentral::BoxShapeComponentRequestsBus::FindFirstHandler(m_entityId); AZ_Assert(m_boxShapeInterface, "DiffuseProbeGridComponentController was unable to find box shape component"); + // special handling is required if this component is being cloned in the editor: + // check to see if the baked textures are already referenced by another DiffuseProbeGrid + if (m_featureProcessor->AreBakedTexturesReferenced( + m_configuration.m_bakedIrradianceTextureRelativePath, + m_configuration.m_bakedDistanceTextureRelativePath, + m_configuration.m_bakedRelocationTextureRelativePath, + m_configuration.m_bakedClassificationTextureRelativePath)) + { + // clear the baked texture paths and assets, since they belong to the original entity (not the clone) + m_configuration.m_bakedIrradianceTextureRelativePath.clear(); + m_configuration.m_bakedDistanceTextureRelativePath.clear(); + m_configuration.m_bakedRelocationTextureRelativePath.clear(); + m_configuration.m_bakedClassificationTextureRelativePath.clear(); + + m_configuration.m_bakedIrradianceTextureAsset.Reset(); + m_configuration.m_bakedDistanceTextureAsset.Reset(); + m_configuration.m_bakedRelocationTextureAsset.Reset(); + m_configuration.m_bakedClassificationTextureAsset.Reset(); + } + // add this diffuse probe grid to the feature processor const AZ::Transform& transform = m_transformInterface->GetWorldTM(); m_handle = m_featureProcessor->AddProbeGrid(transform, m_configuration.m_extents, m_configuration.m_probeSpacing); @@ -118,11 +148,61 @@ namespace AZ m_featureProcessor->SetViewBias(m_handle, m_configuration.m_viewBias); m_featureProcessor->SetNormalBias(m_handle, m_configuration.m_normalBias); + // load the baked texture assets, but only if they are all valid + if (m_configuration.m_bakedIrradianceTextureAsset.GetId().IsValid() && + m_configuration.m_bakedDistanceTextureAsset.GetId().IsValid() && + m_configuration.m_bakedRelocationTextureAsset.GetId().IsValid() && + m_configuration.m_bakedClassificationTextureAsset.GetId().IsValid()) + { + Data::AssetBus::MultiHandler::BusConnect(m_configuration.m_bakedIrradianceTextureAsset.GetId()); + Data::AssetBus::MultiHandler::BusConnect(m_configuration.m_bakedDistanceTextureAsset.GetId()); + Data::AssetBus::MultiHandler::BusConnect(m_configuration.m_bakedRelocationTextureAsset.GetId()); + Data::AssetBus::MultiHandler::BusConnect(m_configuration.m_bakedClassificationTextureAsset.GetId()); + + m_configuration.m_bakedIrradianceTextureAsset.QueueLoad(); + m_configuration.m_bakedDistanceTextureAsset.QueueLoad(); + m_configuration.m_bakedRelocationTextureAsset.QueueLoad(); + m_configuration.m_bakedClassificationTextureAsset.QueueLoad(); + } + else if (m_configuration.m_runtimeMode == DiffuseProbeGridMode::Baked || + m_configuration.m_runtimeMode == DiffuseProbeGridMode::AutoSelect || + m_configuration.m_editorMode == DiffuseProbeGridMode::Baked || + m_configuration.m_editorMode == DiffuseProbeGridMode::AutoSelect) + { + AZ_Error("DiffuseProbeGrid", false, "DiffuseProbeGrid mdoe is set to Baked or Auto-Select, but it does not have baked texture assets. Please re-bake this DiffuseProbeGrid."); + } + + m_featureProcessor->SetMode(m_handle, m_configuration.m_runtimeMode); + // set box shape component dimensions from the configuration // this will invoke the OnShapeChanged() handler and set the outer extents on the feature processor m_boxShapeInterface->SetBoxDimensions(m_configuration.m_extents); } + void DiffuseProbeGridComponentController::OnAssetReady(Data::Asset asset) + { + // if all assets are ready we can set the baked texture images + if (m_configuration.m_bakedIrradianceTextureAsset.IsReady() && + m_configuration.m_bakedDistanceTextureAsset.IsReady() && + m_configuration.m_bakedRelocationTextureAsset.IsReady() && + m_configuration.m_bakedClassificationTextureAsset.IsReady()) + { + Data::AssetBus::MultiHandler::BusDisconnect(m_configuration.m_bakedIrradianceTextureAsset.GetId()); + Data::AssetBus::MultiHandler::BusDisconnect(m_configuration.m_bakedDistanceTextureAsset.GetId()); + Data::AssetBus::MultiHandler::BusDisconnect(m_configuration.m_bakedRelocationTextureAsset.GetId()); + Data::AssetBus::MultiHandler::BusDisconnect(m_configuration.m_bakedClassificationTextureAsset.GetId()); + + UpdateBakedTextures(); + } + } + + void DiffuseProbeGridComponentController::OnAssetError(Data::Asset asset) + { + Data::AssetBus::MultiHandler::BusDisconnect(asset.GetId()); + + AZ_Error("DiffuseProbeGrid", false, "Failed to load baked texture [%s], please re-bake this DiffuseProbeGrid.", asset.GetId().ToString().c_str()); + } + void DiffuseProbeGridComponentController::Deactivate() { if (m_featureProcessor) @@ -212,20 +292,96 @@ namespace AZ void DiffuseProbeGridComponentController::SetAmbientMultiplier(float ambientMultiplier) { + if (!m_featureProcessor) + { + return; + } + m_configuration.m_ambientMultiplier = ambientMultiplier; m_featureProcessor->SetAmbientMultiplier(m_handle, m_configuration.m_ambientMultiplier); } void DiffuseProbeGridComponentController::SetViewBias(float viewBias) { + if (!m_featureProcessor) + { + return; + } + m_configuration.m_viewBias = viewBias; m_featureProcessor->SetViewBias(m_handle, m_configuration.m_viewBias); } void DiffuseProbeGridComponentController::SetNormalBias(float normalBias) { + if (!m_featureProcessor) + { + return; + } + m_configuration.m_normalBias = normalBias; m_featureProcessor->SetNormalBias(m_handle, m_configuration.m_normalBias); } + + void DiffuseProbeGridComponentController::SetEditorMode(DiffuseProbeGridMode editorMode) + { + if (!m_featureProcessor) + { + return; + } + + // update the configuration and change the DiffuseProbeGrid mode + m_configuration.m_editorMode = editorMode; + m_featureProcessor->SetMode(m_handle, m_configuration.m_editorMode); + } + + void DiffuseProbeGridComponentController::SetRuntimeMode(DiffuseProbeGridMode runtimeMode) + { + if (!m_featureProcessor) + { + return; + } + + // only update the configuration + m_configuration.m_runtimeMode = runtimeMode; + } + + void DiffuseProbeGridComponentController::BakeTextures(DiffuseProbeGridBakeTexturesCallback callback) + { + if (!m_featureProcessor) + { + return; + } + + m_featureProcessor->BakeTextures( + m_handle, + callback, + m_configuration.m_bakedIrradianceTextureRelativePath, + m_configuration.m_bakedDistanceTextureRelativePath, + m_configuration.m_bakedRelocationTextureRelativePath, + m_configuration.m_bakedClassificationTextureRelativePath); + } + + void DiffuseProbeGridComponentController::UpdateBakedTextures() + { + if (!m_featureProcessor) + { + return; + } + + DiffuseProbeGridBakedTextures bakedTextures; + bakedTextures.m_irradianceImage = RPI::StreamingImage::FindOrCreate(m_configuration.m_bakedIrradianceTextureAsset); + bakedTextures.m_irradianceImageRelativePath = m_configuration.m_bakedIrradianceTextureRelativePath; + bakedTextures.m_distanceImage = RPI::StreamingImage::FindOrCreate(m_configuration.m_bakedDistanceTextureAsset); + bakedTextures.m_distanceImageRelativePath = m_configuration.m_bakedDistanceTextureRelativePath; + bakedTextures.m_relocationImageDescriptor = m_configuration.m_bakedRelocationTextureAsset->GetImageDescriptor(); + bakedTextures.m_relocationImageData = m_configuration.m_bakedRelocationTextureAsset->GetSubImageData(0, 0); + bakedTextures.m_relocationImageRelativePath = m_configuration.m_bakedRelocationTextureRelativePath; + bakedTextures.m_classificationImageDescriptor = m_configuration.m_bakedClassificationTextureAsset->GetImageDescriptor(); + bakedTextures.m_classificationImageData = m_configuration.m_bakedClassificationTextureAsset->GetSubImageData(0, 0); + bakedTextures.m_classificationImageRelativePath = m_configuration.m_bakedClassificationTextureRelativePath; + + m_featureProcessor->SetBakedTextures(m_handle, bakedTextures); + } } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/DiffuseProbeGridComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/DiffuseProbeGridComponentController.h index 2bcb4132e9..4122a07ba2 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/DiffuseProbeGridComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/DiffuseProbeGridComponentController.h @@ -39,6 +39,19 @@ namespace AZ float m_ambientMultiplier = DefaultDiffuseProbeGridAmbientMultiplier; float m_viewBias = DefaultDiffuseProbeGridViewBias; float m_normalBias = DefaultDiffuseProbeGridNormalBias; + + DiffuseProbeGridMode m_editorMode = DiffuseProbeGridMode::RealTime; + DiffuseProbeGridMode m_runtimeMode = DiffuseProbeGridMode::RealTime; + + AZStd::string m_bakedIrradianceTextureRelativePath; + AZStd::string m_bakedDistanceTextureRelativePath; + AZStd::string m_bakedRelocationTextureRelativePath; + AZStd::string m_bakedClassificationTextureRelativePath; + + Data::Asset m_bakedIrradianceTextureAsset; + Data::Asset m_bakedDistanceTextureAsset; + Data::Asset m_bakedRelocationTextureAsset; + Data::Asset m_bakedClassificationTextureAsset; }; class DiffuseProbeGridComponentController final @@ -79,12 +92,24 @@ namespace AZ // ShapeComponentNotificationsBus overrides void OnShapeChanged(ShapeChangeReasons changeReason) override; + // AssetBus overrides + void OnAssetReady(Data::Asset asset) override; + void OnAssetError(Data::Asset asset) override; + // Property handlers bool ValidateProbeSpacing(const AZ::Vector3& newSpacing); void SetProbeSpacing(const AZ::Vector3& probeSpacing); void SetAmbientMultiplier(float ambientMultiplier); void SetViewBias(float viewBias); void SetNormalBias(float normalBias); + void SetEditorMode(DiffuseProbeGridMode editorMode); + void SetRuntimeMode(DiffuseProbeGridMode runtimeMode); + + // Bake the diffuse probe grid textures to assets + void BakeTextures(DiffuseProbeGridBakeTexturesCallback callback); + + // Update the baked texture assets from the configuration + void UpdateBakedTextures(); // box shape component, used for defining the outer extents of the probe area LmbrCentral::BoxShapeComponentRequests* m_boxShapeInterface = nullptr; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/EditorDiffuseProbeGridComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/EditorDiffuseProbeGridComponent.cpp index ae22ec06c9..1e5b959803 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/EditorDiffuseProbeGridComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/EditorDiffuseProbeGridComponent.cpp @@ -16,6 +16,14 @@ #include #include #include +#include +#include +#include + +AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT +#include +#include +AZ_POP_DISABLE_WARNING namespace AZ { @@ -35,7 +43,9 @@ namespace AZ ->Field("ambientMultiplier", &EditorDiffuseProbeGridComponent::m_ambientMultiplier) ->Field("viewBias", &EditorDiffuseProbeGridComponent::m_viewBias) ->Field("normalBias", &EditorDiffuseProbeGridComponent::m_normalBias) - ; + ->Field("editorMode", &EditorDiffuseProbeGridComponent::m_editorMode) + ->Field("runtimeMode", &EditorDiffuseProbeGridComponent::m_runtimeMode) + ; if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { @@ -48,25 +58,26 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo::Uuid()) - ->ClassElement(AZ::Edit::ClassElements::Group, "Probe Spacing") + ->ClassElement(AZ::Edit::ClassElements::Group, "Probe Spacing (meters between probes)") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorDiffuseProbeGridComponent::m_probeSpacingX, "X", "Probe spacing on the X-axis") + ->DataElement(AZ::Edit::UIHandlers::Default, &EditorDiffuseProbeGridComponent::m_probeSpacingX, "X", "Probe spacing on the X-axis, in meters") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorDiffuseProbeGridComponent::OnProbeSpacingValidateX) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnProbeSpacingChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorDiffuseProbeGridComponent::m_probeSpacingY, "Y", "Probe spacing on the Y-axis") + ->DataElement(AZ::Edit::UIHandlers::Default, &EditorDiffuseProbeGridComponent::m_probeSpacingY, "Y", "Probe spacing on the Y-axis, in meters") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorDiffuseProbeGridComponent::OnProbeSpacingValidateY) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnProbeSpacingChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorDiffuseProbeGridComponent::m_probeSpacingZ, "Z", "Probe spacing on the Z-axis") + ->DataElement(AZ::Edit::UIHandlers::Default, &EditorDiffuseProbeGridComponent::m_probeSpacingZ, "Z", "Probe spacing on the Z-axis, in meters") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorDiffuseProbeGridComponent::OnProbeSpacingValidateZ) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnProbeSpacingChanged) ->ClassElement(AZ::Edit::ClassElements::Group, "Grid Settings") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(AZ::Edit::UIHandlers::Slider, &EditorDiffuseProbeGridComponent::m_ambientMultiplier, "Ambient Multiplier", "Multiplier for the irradiance intensity") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnAmbientMultiplierChanged) - ->Attribute(Edit::Attributes::Decimals, 0) - ->Attribute(Edit::Attributes::Step, 1.0f) + ->Attribute(Edit::Attributes::Decimals, 1) + ->Attribute(Edit::Attributes::Step, 0.1f) ->Attribute(Edit::Attributes::Min, 0.0f) ->Attribute(Edit::Attributes::Max, 10.0f) ->DataElement(AZ::Edit::UIHandlers::Slider, &EditorDiffuseProbeGridComponent::m_viewBias, "View Bias", "View bias adjustment") @@ -81,6 +92,27 @@ namespace AZ ->Attribute(Edit::Attributes::Step, 0.1f) ->Attribute(Edit::Attributes::Min, 0.0f) ->Attribute(Edit::Attributes::Max, 1.0f) + ->ClassElement(AZ::Edit::ClassElements::EditorData, "Grid mode") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(Edit::UIHandlers::ComboBox, &EditorDiffuseProbeGridComponent::m_editorMode, "Editor Mode", "Controls whether the editor uses RealTime or Baked diffuse GI. RealTime requires a ray-tracing capable GPU. Auto-Select will fallback to Baked if ray-tracing is not available") + ->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorDiffuseProbeGridComponent::OnModeChangeValidate) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnEditorModeChanged) + ->EnumAttribute(DiffuseProbeGridMode::RealTime, "Real Time (Ray-Traced)") + ->EnumAttribute(DiffuseProbeGridMode::Baked, "Baked") + ->EnumAttribute(DiffuseProbeGridMode::AutoSelect, "Auto Select") + ->DataElement(Edit::UIHandlers::ComboBox, &EditorDiffuseProbeGridComponent::m_runtimeMode, "Runtime Mode", "Controls whether the runtime uses RealTime or Baked diffuse GI. RealTime requires a ray-tracing capable GPU. Auto-Select will fallback to Baked if ray-tracing is not available") + ->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorDiffuseProbeGridComponent::OnModeChangeValidate) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnRuntimeModeChanged) + ->EnumAttribute(DiffuseProbeGridMode::RealTime, "Real Time (Ray-Traced)") + ->EnumAttribute(DiffuseProbeGridMode::Baked, "Baked") + ->EnumAttribute(DiffuseProbeGridMode::AutoSelect, "Auto Select") + ->ClassElement(AZ::Edit::ClassElements::Group, "Bake Textures") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->UIElement(AZ::Edit::UIHandlers::Button, "Bake Textures", "Bake the Diffuse Probe Grid textures to static assets that will be used when the mode is set to Baked") + ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") + ->Attribute(AZ::Edit::Attributes::ButtonText, "Bake Textures") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::BakeDiffuseProbeGrid) + ->Attribute(AZ::Edit::Attributes::Visibility, &EditorDiffuseProbeGridComponent::GetBakeDiffuseProbeGridVisibilitySetting) ; editContext->Class( @@ -90,12 +122,6 @@ namespace AZ ->DataElement(AZ::Edit::UIHandlers::Default, &DiffuseProbeGridComponentController::m_configuration, "Configuration", "") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ; - - editContext->Class( - "DiffuseProbeGridComponentConfig", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ; } } @@ -121,15 +147,73 @@ namespace AZ BaseClass::Activate(); AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId()); AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId()); + AZ::TickBus::Handler::BusConnect(); + AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusConnect(); } void EditorDiffuseProbeGridComponent::Deactivate() { + AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusDisconnect(); + AZ::TickBus::Handler::BusDisconnect(); AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect(); AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); BaseClass::Deactivate(); } + void EditorDiffuseProbeGridComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) + { + if (!m_controller.m_featureProcessor) + { + return; + } + + DiffuseProbeGridComponentConfig& configuration = m_controller.m_configuration; + + // set the editor mode, which will override the runtime mode set by the controller + if (!m_editorModeSet) + { + m_controller.m_featureProcessor->SetMode(m_controller.m_handle, configuration.m_editorMode); + m_editorModeSet = true; + } + + CheckTextureAssetNotification(configuration.m_bakedIrradianceTextureRelativePath, configuration.m_bakedIrradianceTextureAsset); + CheckTextureAssetNotification(configuration.m_bakedDistanceTextureRelativePath, configuration.m_bakedDistanceTextureAsset); + CheckTextureAssetNotification(configuration.m_bakedRelocationTextureRelativePath, configuration.m_bakedRelocationTextureAsset); + CheckTextureAssetNotification(configuration.m_bakedClassificationTextureRelativePath, configuration.m_bakedClassificationTextureAsset); + } + + void EditorDiffuseProbeGridComponent::CheckTextureAssetNotification(const AZStd::string& relativePath, Data::Asset& configurationAsset) + { + Data::Asset textureAsset; + DiffuseProbeGridTextureNotificationType notificationType = DiffuseProbeGridTextureNotificationType::None; + if (m_controller.m_featureProcessor->CheckTextureAssetNotification(relativePath + ".streamingimage", textureAsset, notificationType)) + { + if (notificationType == DiffuseProbeGridTextureNotificationType::Ready) + { + // bake is complete, update configuration with the new baked texture asset + AzToolsFramework::ScopedUndoBatch undoBatch("DiffuseProbeGrid Texture Bake"); + configurationAsset = { textureAsset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; + SetDirty(); + + if (m_controller.m_configuration.m_bakedIrradianceTextureAsset.IsReady() && + m_controller.m_configuration.m_bakedDistanceTextureAsset.IsReady() && + m_controller.m_configuration.m_bakedClassificationTextureAsset.IsReady() && + m_controller.m_configuration.m_bakedRelocationTextureAsset.IsReady()) + { + m_controller.UpdateBakedTextures(); + } + } + else if (notificationType == DiffuseProbeGridTextureNotificationType::Error) + { + QMessageBox::information( + QApplication::activeWindow(), + "Diffuse Probe Grid", + "Diffuse Probe Grid texture failed to bake, please check the Asset Processor for more information.", + QMessageBox::Ok); + } + } + } + AZ::Aabb EditorDiffuseProbeGridComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo) { return m_controller.GetAabb(); @@ -140,11 +224,19 @@ namespace AZ return false; } + void EditorDiffuseProbeGridComponent::OnEntityInfoUpdatedVisibility(AZ::EntityId entityId, bool visible) + { + if ((GetEntityId() == entityId) && !visible) + { + m_editorModeSet = false; + } + } + AZ::Outcome EditorDiffuseProbeGridComponent::OnProbeSpacingValidateX(void* newValue, [[maybe_unused]] const AZ::Uuid& valueType) { if (!m_controller.m_featureProcessor) { - return AZ::Failure(AZStd::string("Unable to adjust probe spacing, please try again")); + return AZ::Failure(AZStd::string("This Diffuse Probe Grid entity is hidden, it must be visible in order to change the probe spacing.")); } float newProbeSpacingX = *(reinterpret_cast(newValue)); @@ -152,7 +244,7 @@ namespace AZ Vector3 newSpacing(newProbeSpacingX, m_probeSpacingY, m_probeSpacingZ); if (!m_controller.ValidateProbeSpacing(newSpacing)) { - return AZ::Failure(AZStd::string("Probe spacing exceeds max allowable grid size with current extents")); + return AZ::Failure(AZStd::string("Probe spacing exceeds max allowable grid size with current extents.")); } return AZ::Success(); @@ -162,7 +254,7 @@ namespace AZ { if (!m_controller.m_featureProcessor) { - return AZ::Failure(AZStd::string("Unable to adjust probe spacing, please try again")); + return AZ::Failure(AZStd::string("This Diffuse Probe Grid entity is hidden, it must be visible in order to change the probe spacing.")); } float newProbeSpacingY = *(reinterpret_cast(newValue)); @@ -170,7 +262,7 @@ namespace AZ Vector3 newSpacing(m_probeSpacingX, newProbeSpacingY, m_probeSpacingZ); if (!m_controller.ValidateProbeSpacing(newSpacing)) { - return AZ::Failure(AZStd::string("Probe spacing exceeds max allowable grid size with current extents")); + return AZ::Failure(AZStd::string("Probe spacing exceeds max allowable grid size with current extents.")); } return AZ::Success(); @@ -180,7 +272,7 @@ namespace AZ { if (!m_controller.m_featureProcessor) { - return AZ::Failure(AZStd::string("Unable to adjust probe spacing, please try again")); + return AZ::Failure(AZStd::string("This Diffuse Probe Grid entity is hidden, it must be visible in order to change the probe spacing.")); } float newProbeSpacingZ = *(reinterpret_cast(newValue)); @@ -188,7 +280,7 @@ namespace AZ Vector3 newSpacing(m_probeSpacingX, m_probeSpacingY, newProbeSpacingZ); if (!m_controller.ValidateProbeSpacing(newSpacing)) { - return AZ::Failure(AZStd::string("Probe spacing exceeds max allowable grid size with current extents")); + return AZ::Failure(AZStd::string("Probe spacing exceeds max allowable grid size with current extents.")); } return AZ::Success(); @@ -218,5 +310,226 @@ namespace AZ m_controller.SetNormalBias(m_normalBias); return AZ::Edit::PropertyRefreshLevels::None; } + + AZ::u32 EditorDiffuseProbeGridComponent::OnEditorModeChanged() + { + // this will update the configuration and also change the DiffuseProbeGrid mode + m_controller.SetEditorMode(m_editorMode); + return AZ::Edit::PropertyRefreshLevels::EntireTree; + } + + AZ::u32 EditorDiffuseProbeGridComponent::OnRuntimeModeChanged() + { + // this will only update the configuration + m_controller.SetRuntimeMode(m_runtimeMode); + return AZ::Edit::PropertyRefreshLevels::None; + } + + AZ::Outcome EditorDiffuseProbeGridComponent::OnModeChangeValidate([[maybe_unused]] void* newValue, [[maybe_unused]] const AZ::Uuid& valueType) + { + DiffuseProbeGridMode newMode = (*(reinterpret_cast(newValue))); + + if (newMode == DiffuseProbeGridMode::Baked || newMode == DiffuseProbeGridMode::AutoSelect) + { + if (!m_controller.m_configuration.m_bakedIrradianceTextureAsset.GetId().IsValid() || + !m_controller.m_configuration.m_bakedDistanceTextureAsset.GetId().IsValid() || + !m_controller.m_configuration.m_bakedRelocationTextureAsset.GetId().IsValid() || + !m_controller.m_configuration.m_bakedClassificationTextureAsset.GetId().IsValid()) + { + return AZ::Failure(AZStd::string("Please bake textures before changing the Diffuse Probe Grid to Baked or Auto-Select mode.")); + } + } + + return AZ::Success(); + } + + AZ::u32 EditorDiffuseProbeGridComponent::GetBakeDiffuseProbeGridVisibilitySetting() + { + // the Bake button is visible only when the editor mode is set to RealTime + return m_editorMode == DiffuseProbeGridMode::RealTime ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; + } + + AZ::u32 EditorDiffuseProbeGridComponent::BakeDiffuseProbeGrid() + { + if (m_bakeInProgress) + { + return AZ::Edit::PropertyRefreshLevels::None; + } + + // retrieve entity visibility + bool isHidden = false; + AzToolsFramework::EditorEntityInfoRequestBus::EventResult( + isHidden, + GetEntityId(), + &AzToolsFramework::EditorEntityInfoRequestBus::Events::IsHidden); + + // the entity must be visible in order to bake + if (isHidden) + { + QMessageBox::information( + QApplication::activeWindow(), + "Diffuse Probe Grid", + "This Diffuse Probe Grid entity is hidden, it must be visible in order to bake textures.", + QMessageBox::Ok); + + return AZ::Edit::PropertyRefreshLevels::None; + } + + DiffuseProbeGridComponentConfig& configuration = m_controller.m_configuration; + + // retrieve the source image paths from the configuration + // Note: we need to make sure to use the same source image for each bake + AZStd::string irradianceTextureRelativePath = ValidateOrCreateNewTexturePath(configuration.m_bakedIrradianceTextureRelativePath, DiffuseProbeGridIrradianceFileName); + AZStd::string distanceTextureRelativePath = ValidateOrCreateNewTexturePath(configuration.m_bakedDistanceTextureRelativePath, DiffuseProbeGridDistanceFileName); + AZStd::string relocationTextureRelativePath = ValidateOrCreateNewTexturePath(configuration.m_bakedRelocationTextureRelativePath, DiffuseProbeGridRelocationFileName); + AZStd::string classificationTextureRelativePath = ValidateOrCreateNewTexturePath(configuration.m_bakedClassificationTextureRelativePath, DiffuseProbeGridClassificationFileName); + + // create the full paths + char projectPath[AZ_MAX_PATH_LEN]; + AZ::IO::FileIOBase::GetInstance()->ResolvePath("@devassets@", projectPath, AZ_MAX_PATH_LEN); + + AZStd::string irradianceTextureFullPath; + AzFramework::StringFunc::Path::Join(projectPath, irradianceTextureRelativePath.c_str(), irradianceTextureFullPath, true, true); + AZStd::string distanceTextureFullPath; + AzFramework::StringFunc::Path::Join(projectPath, distanceTextureRelativePath.c_str(), distanceTextureFullPath, true, true); + AZStd::string relocationTextureFullPath; + AzFramework::StringFunc::Path::Join(projectPath, relocationTextureRelativePath.c_str(), relocationTextureFullPath, true, true); + AZStd::string classificationTextureFullPath; + AzFramework::StringFunc::Path::Join(projectPath, classificationTextureRelativePath.c_str(), classificationTextureFullPath, true, true); + + // make sure the folder is created + AZStd::string diffuseProbeGridFolder; + AzFramework::StringFunc::Path::GetFolderPath(irradianceTextureFullPath.data(), diffuseProbeGridFolder); + AZ::IO::SystemFile::CreateDir(diffuseProbeGridFolder.c_str()); + + // check out the files in source control + CheckoutSourceTextureFile(irradianceTextureFullPath); + CheckoutSourceTextureFile(distanceTextureFullPath); + CheckoutSourceTextureFile(relocationTextureFullPath); + CheckoutSourceTextureFile(classificationTextureFullPath); + + // update the configuration + AzToolsFramework::ScopedUndoBatch undoBatch("DiffuseProbeGrid bake"); + configuration.m_bakedIrradianceTextureRelativePath = irradianceTextureRelativePath; + configuration.m_bakedDistanceTextureRelativePath = distanceTextureRelativePath; + configuration.m_bakedRelocationTextureRelativePath = relocationTextureRelativePath; + configuration.m_bakedClassificationTextureRelativePath = classificationTextureRelativePath; + SetDirty(); + + // callback for the texture readback + DiffuseProbeGridBakeTexturesCallback bakeTexturesCallback = [=]( + DiffuseProbeGridTexture irradianceTexture, + DiffuseProbeGridTexture distanceTexture, + DiffuseProbeGridTexture relocationTexture, + DiffuseProbeGridTexture classificationTexture) + { + // irradiance + { + AZ::DdsFile::DdsFileData fileData = { irradianceTexture.m_size, irradianceTexture.m_format, irradianceTexture.m_data.get() }; + [[maybe_unused]] const auto outcome = AZ::DdsFile::WriteFile(irradianceTextureFullPath, fileData); + AZ_Assert(outcome.IsSuccess(), "Failed to write Irradiance texture .dds file [%s]", irradianceTextureFullPath.c_str()); + } + + // distance + { + AZ::DdsFile::DdsFileData fileData = { distanceTexture.m_size, distanceTexture.m_format, distanceTexture.m_data.get() }; + [[maybe_unused]] const auto outcome = AZ::DdsFile::WriteFile(distanceTextureFullPath, fileData); + AZ_Assert(outcome.IsSuccess(), "Failed to write Distance texture .dds file [%s]", distanceTextureFullPath.c_str()); + } + + // relocation + { + AZ::DdsFile::DdsFileData fileData = { relocationTexture.m_size, relocationTexture.m_format, relocationTexture.m_data.get() }; + [[maybe_unused]] const auto outcome = AZ::DdsFile::WriteFile(relocationTextureFullPath, fileData); + AZ_Assert(outcome.IsSuccess(), "Failed to write Relocation texture .dds file [%s]", relocationTextureFullPath.c_str()); + } + + // classification + { + AZ::DdsFile::DdsFileData fileData = { classificationTexture.m_size, classificationTexture.m_format, classificationTexture.m_data.get() }; + [[maybe_unused]] const auto outcome = AZ::DdsFile::WriteFile(classificationTextureFullPath, fileData); + AZ_Assert(outcome.IsSuccess(), "Failed to write Classification texture .dds file [%s]", classificationTextureFullPath.c_str()); + } + + m_bakeInProgress = false; + }; + + m_bakeInProgress = true; + m_controller.BakeTextures(bakeTexturesCallback); + + while (m_bakeInProgress) + { + QApplication::processEvents(); + AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(100)); + } + + QMessageBox::information( + QApplication::activeWindow(), + "Diffuse Probe Grid", + "Successfully baked Diffuse Probe Grid textures.", + QMessageBox::Ok); + + return AZ::Edit::PropertyRefreshLevels::None; + } + + AZStd::string EditorDiffuseProbeGridComponent::ValidateOrCreateNewTexturePath(const AZStd::string& configurationRelativePath, const char* fileSuffix) + { + AZStd::string relativePath = configurationRelativePath; + AZStd::string fullPath; + + char projectPath[AZ_MAX_PATH_LEN]; + AZ::IO::FileIOBase::GetInstance()->ResolvePath("@devassets@", projectPath, AZ_MAX_PATH_LEN); + + if (!relativePath.empty()) + { + // test to see if the texture file is actually there, if it was removed we need to + // generate a new filename, otherwise it will cause an error in the asset system + AzFramework::StringFunc::Path::Join(projectPath, configurationRelativePath.c_str(), fullPath, true, true); + + if (!AZ::IO::FileIOBase::GetInstance()->Exists(fullPath.c_str())) + { + // file does not exist, clear the relative path so we generate a new name + relativePath.clear(); + } + } + + // build a new image path if necessary + if (relativePath.empty()) + { + // the file name is a combination of the entity name, a UUID, and the filemask + Entity* entity = GetEntity(); + AZ_Assert(entity, "DiffuseProbeGrid entity is null"); + + AZ::Uuid uuid = AZ::Uuid::CreateRandom(); + AZStd::string uuidString; + uuid.ToString(uuidString); + + relativePath = "DiffuseProbeGrids/" + entity->GetName() + uuidString + fileSuffix; + + // replace any invalid filename characters + auto invalidCharacters = [](char letter) + { + return + letter == ':' || letter == '"' || letter == '\'' || + letter == '{' || letter == '}' || + letter == '<' || letter == '>'; + }; + AZStd::replace_if(relativePath.begin(), relativePath.end(), invalidCharacters, '_'); + } + + return relativePath; + } + + void EditorDiffuseProbeGridComponent::CheckoutSourceTextureFile(const AZStd::string& fullPath) + { + bool checkedOutSuccessfully = false; + using ApplicationBus = AzToolsFramework::ToolsApplicationRequestBus; + ApplicationBus::BroadcastResult( + checkedOutSuccessfully, + &ApplicationBus::Events::RequestEditForFileBlocking, + fullPath.c_str(), + "Checking out for edit...", + ApplicationBus::Events::RequestEditProgressCallback()); + } } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/EditorDiffuseProbeGridComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/EditorDiffuseProbeGridComponent.h index 2a50c47b81..15c46d45ba 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/EditorDiffuseProbeGridComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseProbeGrid/EditorDiffuseProbeGridComponent.h @@ -12,8 +12,10 @@ #pragma once +#include #include #include +#include #include #include #include @@ -26,6 +28,8 @@ namespace AZ : public EditorRenderComponentAdapter , private AzToolsFramework::EditorComponentSelectionRequestsBus::Handler , private AzFramework::EntityDebugDisplayEventBus::Handler + , private AZ::TickBus::Handler + , private AzToolsFramework::EditorEntityInfoNotificationBus::Handler { public: using BaseClass = EditorRenderComponentAdapter; @@ -41,10 +45,22 @@ namespace AZ void Deactivate() override; private: + + // AZ::TickBus overrides + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + // EditorComponentSelectionRequestsBus overrides AZ::Aabb GetEditorSelectionBoundsViewport(const AzFramework::ViewportInfo& viewportInfo) override; bool SupportsEditorRayIntersect() override; + // EditorEntityInfoNotifications overrides + void OnEntityInfoUpdatedVisibility(AZ::EntityId entityId, bool visible) override; + + // helper functions + AZStd::string ValidateOrCreateNewTexturePath(const AZStd::string& relativePath, const char* fileSuffix); + void CheckoutSourceTextureFile(const AZStd::string& fullPath); + void CheckTextureAssetNotification(const AZStd::string& relativePath, Data::Asset& configurationAsset); + // property change notifications AZ::Outcome OnProbeSpacingValidateX(void* newValue, const AZ::Uuid& valueType); AZ::Outcome OnProbeSpacingValidateY(void* newValue, const AZ::Uuid& valueType); @@ -53,6 +69,13 @@ namespace AZ AZ::u32 OnAmbientMultiplierChanged(); AZ::u32 OnViewBiasChanged(); AZ::u32 OnNormalBiasChanged(); + AZ::u32 OnEditorModeChanged(); + AZ::u32 OnRuntimeModeChanged(); + AZ::Outcome OnModeChangeValidate(void* newValue, const AZ::Uuid& valueType); + + // Button handler + AZ::u32 BakeDiffuseProbeGrid(); + AZ::u32 GetBakeDiffuseProbeGridVisibilitySetting(); // properties float m_probeSpacingX = DefaultDiffuseProbeGridSpacing; @@ -61,6 +84,12 @@ namespace AZ float m_ambientMultiplier = DefaultDiffuseProbeGridAmbientMultiplier; float m_viewBias = DefaultDiffuseProbeGridViewBias; float m_normalBias = DefaultDiffuseProbeGridNormalBias; + DiffuseProbeGridMode m_editorMode = DiffuseProbeGridMode::RealTime; + DiffuseProbeGridMode m_runtimeMode = DiffuseProbeGridMode::RealTime; + + // flags + bool m_editorModeSet = false; + AZStd::atomic_bool m_bakeInProgress = false; }; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.cpp index bad7c2fe38..ef82792f32 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/ReleaseResourcesStep.cpp @@ -32,32 +32,29 @@ namespace AZ void ReleaseResourcesStep::Start() { - m_context->GetData()->m_defaultMaterialAsset.Release(); - m_context->GetData()->m_defaultModelAsset.Release(); - m_context->GetData()->m_materialAsset.Release(); - m_context->GetData()->m_modelAsset.Release(); + auto data = m_context->GetData(); + + data->m_defaultMaterialAsset.Release(); + data->m_defaultModelAsset.Release(); + data->m_materialAsset.Release(); + data->m_modelAsset.Release(); + data->m_lightingPresetAsset.Release(); - if (m_context->GetData()->m_modelEntity) + if (data->m_modelEntity) { - AzFramework::EntityContextRequestBus::Event(m_context->GetData()->m_entityContext->GetContextId(), - &AzFramework::EntityContextRequestBus::Events::DestroyEntity, m_context->GetData()->m_modelEntity); - m_context->GetData()->m_modelEntity = nullptr; + AzFramework::EntityContextRequestBus::Event(data->m_entityContext->GetContextId(), + &AzFramework::EntityContextRequestBus::Events::DestroyEntity, data->m_modelEntity); + data->m_modelEntity = nullptr; } - m_context->GetData()->m_frameworkScene->UnsetSubsystem(); - - m_context->GetData()->m_scene->Deactivate(); - m_context->GetData()->m_scene->RemoveRenderPipeline(m_context->GetData()->m_renderPipeline->GetId()); - RPI::RPISystemInterface::Get()->UnregisterScene(m_context->GetData()->m_scene); - - auto sceneSystem = AzFramework::SceneSystemInterface::Get(); - AZ_Assert(sceneSystem, "Thumbnail system failed to get scene system implementation."); - [[maybe_unused]] bool sceneRemovedSuccessfully = sceneSystem->RemoveScene(m_context->GetData()->m_sceneName); - AZ_Assert( - sceneRemovedSuccessfully, "Thumbnail system was unable to remove scene '%s' from the scene system.", - m_context->GetData()->m_sceneName.c_str()); - m_context->GetData()->m_scene = nullptr; - m_context->GetData()->m_renderPipeline = nullptr; + data->m_scene->Deactivate(); + data->m_scene->RemoveRenderPipeline(data->m_renderPipeline->GetId()); + RPI::RPISystemInterface::Get()->UnregisterScene(data->m_scene); + data->m_frameworkScene->UnsetSubsystem(data->m_scene); + data->m_frameworkScene->UnsetSubsystem(data->m_entityContext.get()); + data->m_scene = nullptr; + data->m_frameworkScene = nullptr; + data->m_renderPipeline = nullptr; } } // namespace Thumbnails } // namespace LyIntegration diff --git a/Gems/AudioEngineWwise/Code/Source/Builder/AudioControlBuilderWorker.cpp b/Gems/AudioEngineWwise/Code/Source/Builder/AudioControlBuilderWorker.cpp index f7b54a44d9..b08aa6fa1d 100644 --- a/Gems/AudioEngineWwise/Code/Source/Builder/AudioControlBuilderWorker.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Builder/AudioControlBuilderWorker.cpp @@ -57,11 +57,11 @@ namespace AudioControlBuilder { atlPlatform = "windows"; } - else if (platform == "es3") + else if (platform == "android") { atlPlatform = "android"; } - else if (platform == "osx_gl") + else if (platform == "mac") { atlPlatform = "mac"; } diff --git a/Gems/AudioEngineWwise/Code/Source/Engine/Config_wwise.h b/Gems/AudioEngineWwise/Code/Source/Engine/Config_wwise.h index ad2ba28269..7fabfb75b3 100644 --- a/Gems/AudioEngineWwise/Code/Source/Engine/Config_wwise.h +++ b/Gems/AudioEngineWwise/Code/Source/Engine/Config_wwise.h @@ -46,7 +46,7 @@ namespace Audio::Wwise ~PlatformMapping() = default; // Serialized Data... - AZStd::string m_assetPlatform; // LY Asset Platform name (i.e. "pc", "osx_gl", "es3", ...) + AZStd::string m_assetPlatform; // LY Asset Platform name (i.e. "pc", "mac", "android", ...) AZStd::string m_altAssetPlatform; // Some platforms can be run using a different asset platform. Useful for builder worker. AZStd::string m_enginePlatform; // LY Engine Platform name (i.e. "Windows", "Mac", "Android", ...) AZStd::string m_wwisePlatform; // Wwise Platform name (i.e. "Windows", "Mac", "Android", ...) diff --git a/Gems/AudioEngineWwise/Tools/WwiseConfig/Platform/Android/wwise_config_android.json b/Gems/AudioEngineWwise/Tools/WwiseConfig/Platform/Android/wwise_config_android.json index 22cc632cbd..38f6ff142e 100644 --- a/Gems/AudioEngineWwise/Tools/WwiseConfig/Platform/Android/wwise_config_android.json +++ b/Gems/AudioEngineWwise/Tools/WwiseConfig/Platform/Android/wwise_config_android.json @@ -1,5 +1,5 @@ { - "assetPlatform": "es3", + "assetPlatform": "android", "altAssetPlatform": "", "enginePlatform": "Android", "wwisePlatform": "Android", diff --git a/Gems/AudioEngineWwise/Tools/WwiseConfig/Platform/Mac/wwise_config_mac.json b/Gems/AudioEngineWwise/Tools/WwiseConfig/Platform/Mac/wwise_config_mac.json index 4069d8add7..a996b85150 100644 --- a/Gems/AudioEngineWwise/Tools/WwiseConfig/Platform/Mac/wwise_config_mac.json +++ b/Gems/AudioEngineWwise/Tools/WwiseConfig/Platform/Mac/wwise_config_mac.json @@ -1,5 +1,5 @@ { - "assetPlatform": "osx_gl", + "assetPlatform": "mac", "altAssetPlatform": "", "enginePlatform": "Mac", "wwisePlatform": "Mac", diff --git a/Gems/Blast/Code/Tests/Mocks/BlastMocks.h b/Gems/Blast/Code/Tests/Mocks/BlastMocks.h index bd03a442d9..00aa12cb84 100644 --- a/Gems/Blast/Code/Tests/Mocks/BlastMocks.h +++ b/Gems/Blast/Code/Tests/Mocks/BlastMocks.h @@ -644,19 +644,7 @@ namespace Blast MOCK_METHOD0(GetLocalX, float()); MOCK_METHOD0(GetLocalY, float()); MOCK_METHOD0(GetLocalZ, float()); - MOCK_METHOD1(SetRotation, void(const AZ::Vector3&)); - MOCK_METHOD1(SetRotationX, void(float)); - MOCK_METHOD1(SetRotationY, void(float)); - MOCK_METHOD1(SetRotationZ, void(float)); - MOCK_METHOD1(SetRotationQuaternion, void(const AZ::Quaternion&)); - MOCK_METHOD1(RotateByX, void(float)); - MOCK_METHOD1(RotateByY, void(float)); - MOCK_METHOD1(RotateByZ, void(float)); - MOCK_METHOD0(GetRotationEulerRadians, AZ::Vector3()); - MOCK_METHOD0(GetRotationQuaternion, AZ::Quaternion()); - MOCK_METHOD0(GetRotationX, float()); - MOCK_METHOD0(GetRotationY, float()); - MOCK_METHOD0(GetRotationZ, float()); + MOCK_METHOD1(SetWorldRotationQuaternion, void(const AZ::Quaternion&)); MOCK_METHOD0(GetWorldRotation, AZ::Vector3()); MOCK_METHOD0(GetWorldRotationQuaternion, AZ::Quaternion()); MOCK_METHOD1(SetLocalRotation, void(const AZ::Vector3&)); diff --git a/Gems/LmbrCentral/Code/Tests/Builders/CopyDependencyBuilderTest.cpp b/Gems/LmbrCentral/Code/Tests/Builders/CopyDependencyBuilderTest.cpp index f082ef74f9..44fe70af80 100644 --- a/Gems/LmbrCentral/Code/Tests/Builders/CopyDependencyBuilderTest.cpp +++ b/Gems/LmbrCentral/Code/Tests/Builders/CopyDependencyBuilderTest.cpp @@ -217,6 +217,9 @@ protected: const char* GetAbsoluteDevGameFolderPath() override { return ""; } const char* GetAbsoluteDevRootFolderPath() override { return ""; } bool GetRelativeProductPathFromFullSourceOrProductPath([[maybe_unused]] const AZStd::string& fullPath, [[maybe_unused]] AZStd::string& relativeProductPath) { return true; } + bool GenerateRelativeSourcePath( + [[maybe_unused]] const AZStd::string& sourcePath, [[maybe_unused]] AZStd::string& relativePath, + [[maybe_unused]] AZStd::string& watchFolder) { return true; } bool GetFullSourcePathFromRelativeProductPath([[maybe_unused]] const AZStd::string& relPath, [[maybe_unused]] AZStd::string& fullSourcePath) { return true; } bool GetAssetInfoById([[maybe_unused]] const AZ::Data::AssetId& assetId, [[maybe_unused]] const AZ::Data::AssetType& assetType, [[maybe_unused]] const AZStd::string& platformName, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& rootFilePath) { return true; } bool GetSourceInfoBySourcePath([[maybe_unused]] const char* sourcePath, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& watchFolder) { return true; } diff --git a/Gems/LyShine/Assets/Editor/Icons/Viewport/Canvas_Background.tif.assetinfo b/Gems/LyShine/Assets/Editor/Icons/Viewport/Canvas_Background.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShine/Assets/Editor/Icons/Viewport/Canvas_Background.tif.assetinfo +++ b/Gems/LyShine/Assets/Editor/Icons/Viewport/Canvas_Background.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShine/Code/Editor/ViewportHelpers.cpp b/Gems/LyShine/Code/Editor/ViewportHelpers.cpp index 428554a461..2195d2c9d4 100644 --- a/Gems/LyShine/Code/Editor/ViewportHelpers.cpp +++ b/Gems/LyShine/Code/Editor/ViewportHelpers.cpp @@ -30,6 +30,11 @@ namespace ViewportHelpers return isControlledByParent; } + float GetDpiScaledSize(float size) + { + return size * ViewportIcon::GetDpiScaleFactor(); + } + bool IsHorizontallyFit(const AZ::Entity* element) { bool isHorizontallyFit = false; @@ -332,11 +337,12 @@ namespace ViewportHelpers AZ::Vector2 pivotPos; EBUS_EVENT_ID_RESULT(pivotPos, element->GetId(), UiTransformBus, GetViewportSpacePivot); - AZ::Vector2 rotationStringPos(pivotPos.GetX(), pivotPos.GetY() - ((viewportPivot->GetSize().GetY() * 0.5f) + 4.0f)); + float offset = (viewportPivot->GetSize().GetY() * 0.5f) + (GetDpiScaledSize(4.0f)); + AZ::Vector2 rotationStringPos(pivotPos.GetX(), pivotPos.GetY() - offset); draw2d.SetTextAlignment(IDraw2d::HAlign::Center, IDraw2d::VAlign::Bottom); draw2d.SetTextRotation(0.0f); - draw2d.DrawText(rotationString.toUtf8().data(), rotationStringPos, 16.0f, 1.0f); + draw2d.DrawText(rotationString.toUtf8().data(), rotationStringPos, GetDpiScaledSize(16.0f), 1.0f); } } @@ -350,6 +356,6 @@ namespace ViewportHelpers draw2d.SetTextAlignment(IDraw2d::HAlign::Left, IDraw2d::VAlign::Bottom); draw2d.SetTextRotation(0.0f); - draw2d.DrawText(textLabel.c_str(), textPos, 16.0f, 1.0f); + draw2d.DrawText(textLabel.c_str(), textPos, GetDpiScaledSize(16.0f), 1.0f); } } // namespace ViewportHelpers diff --git a/Gems/LyShine/Code/Editor/ViewportIcon.cpp b/Gems/LyShine/Code/Editor/ViewportIcon.cpp index b1866efb00..4be06b2543 100644 --- a/Gems/LyShine/Code/Editor/ViewportIcon.cpp +++ b/Gems/LyShine/Code/Editor/ViewportIcon.cpp @@ -303,7 +303,7 @@ void ViewportIcon::DrawDistanceLine(Draw2dHelper& draw2d, AZ::Vector2 start, AZ: draw2d.SetTextAlignment(IDraw2d::HAlign::Center, IDraw2d::VAlign::Bottom); draw2d.SetTextRotation(rotation); - draw2d.DrawText(textBuf, textPos, 16.0f, 1.0f); + draw2d.DrawText(textBuf, textPos, 16.0f * ViewportIcon::GetDpiScaleFactor(), 1.0f); } void ViewportIcon::DrawAnchorLinesSplit(Draw2dHelper& draw2d, AZ::Vector2 anchorPos1, AZ::Vector2 anchorPos2, diff --git a/Gems/LyShine/Code/Include/LyShine/Draw2d.h b/Gems/LyShine/Code/Include/LyShine/Draw2d.h index 8270461e73..b83ec4794b 100644 --- a/Gems/LyShine/Code/Include/LyShine/Draw2d.h +++ b/Gems/LyShine/Code/Include/LyShine/Draw2d.h @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -256,9 +257,8 @@ protected: // types and constants const Draw2dShaderData& shaderData, AZ::RPI::ViewportContextPtr viewportContext) const override; - STextDrawContext m_fontContext; - IFFont* m_font; - AZ::Vector2 m_position; + AzFramework::TextDrawParameters m_drawParameters; + AzFramework::FontId m_fontId; std::string m_string; }; @@ -288,7 +288,7 @@ protected: // member functions void RotatePointsAboutPivot(AZ::Vector2* points, int numPoints, AZ::Vector2 pivot, float angle) const; //! Helper function to render a text string - void DrawTextInternal(const char* textString, IFFont* font, unsigned int effectIndex, + void DrawTextInternal(const char* textString, AzFramework::FontId fontId, unsigned int effectIndex, AZ::Vector2 position, float pointSize, AZ::Color color, float rotation, HAlign horizontalAlignment, VAlign verticalAlignment, int baseState); @@ -298,6 +298,9 @@ protected: // member functions //! Draw or defer a line void DrawOrDeferLine(const DeferredLine* line); + //! Draw or defer a text string + void DrawOrDeferTextString(const DeferredText* text); + //! Draw or defer a rect outline void DrawOrDeferRectOutline(const DeferredRectOutline* outlineRect); @@ -491,7 +494,7 @@ public: // member functions void SetImageBaseState(int state) { m_imageOptions.baseState = state; } //! Set the text font. - void SetTextFont(IFFont* font) { m_textOptions.font = font; } + void SetTextFont(AZStd::string_view fontName) { m_textOptions.fontName = fontName; } //! Set the text font effect index. void SetTextEffectIndex(unsigned int effectIndex) { m_textOptions.effectIndex = effectIndex; } diff --git a/Gems/LyShine/Code/Source/Draw2d.cpp b/Gems/LyShine/Code/Source/Draw2d.cpp index 1a639ea299..6feb47419d 100644 --- a/Gems/LyShine/Code/Source/Draw2d.cpp +++ b/Gems/LyShine/Code/Source/Draw2d.cpp @@ -11,11 +11,13 @@ */ #include "LyShine_precompiled.h" #include "IFont.h" +#include // for SVF_P3F_C4B_T2F which will be removed in a coming PR #include #include #include +#include #include #include @@ -55,7 +57,7 @@ CDraw2d::CDraw2d(AZ::RPI::ViewportContextPtr viewportContext) m_defaultImageOptions.pixelRounding = Rounding::Nearest; m_defaultImageOptions.baseState = g_defaultBaseState; - m_defaultTextOptions.font = (gEnv && gEnv->pCryFont != nullptr) ? gEnv->pCryFont->GetFont("default") : nullptr; + m_defaultTextOptions.fontName = "default"; m_defaultTextOptions.effectIndex = 0; m_defaultTextOptions.color.Set(1.0f, 1.0f, 1.0f); m_defaultTextOptions.horizontalAlignment = HAlign::Left; @@ -283,13 +285,20 @@ void CDraw2d::DrawText(const char* textString, AZ::Vector2 position, float point { TextOptions* actualTextOptions = (textOptions) ? textOptions : &m_defaultTextOptions; + AzFramework::FontId fontId = AzFramework::InvalidFontId; + AzFramework::FontQueryInterface* fontQueryInterface = AZ::Interface::Get(); + if (fontQueryInterface) + { + fontId = fontQueryInterface->GetFontId(actualTextOptions->fontName); + } + // render the drop shadow, if needed if ((actualTextOptions->dropShadowColor.GetA() > 0.0f) && (actualTextOptions->dropShadowOffset.GetX() || actualTextOptions->dropShadowOffset.GetY())) { // calculate the drop shadow pos and render it AZ::Vector2 dropShadowPosition(position + actualTextOptions->dropShadowOffset); - DrawTextInternal(textString, actualTextOptions->font, actualTextOptions->effectIndex, + DrawTextInternal(textString, fontId, actualTextOptions->effectIndex, dropShadowPosition, pointSize, actualTextOptions->dropShadowColor, actualTextOptions->rotation, actualTextOptions->horizontalAlignment, actualTextOptions->verticalAlignment, @@ -298,7 +307,7 @@ void CDraw2d::DrawText(const char* textString, AZ::Vector2 position, float point // draw the text string AZ::Color textColor = AZ::Color::CreateFromVector3AndFloat(actualTextOptions->color, opacity); - DrawTextInternal(textString, actualTextOptions->font, actualTextOptions->effectIndex, + DrawTextInternal(textString, fontId, actualTextOptions->effectIndex, position, pointSize, textColor, actualTextOptions->rotation, actualTextOptions->horizontalAlignment, actualTextOptions->verticalAlignment, @@ -398,20 +407,35 @@ void CDraw2d::DrawRectOutlineTextured(AZ::Data::Instance image, //////////////////////////////////////////////////////////////////////////////////////////////////// AZ::Vector2 CDraw2d::GetTextSize(const char* textString, float pointSize, TextOptions* textOptions) { - TextOptions* actualTextOptions = (textOptions) ? textOptions : &m_defaultTextOptions; - - if (!actualTextOptions->font) + AzFramework::FontDrawInterface* fontDrawInterface = nullptr; + AzFramework::FontQueryInterface* fontQueryInterface = AZ::Interface::Get(); + if (fontQueryInterface) + { + TextOptions* actualTextOptions = (textOptions) ? textOptions : &m_defaultTextOptions; + AzFramework::FontId fontId = fontQueryInterface->GetFontId(actualTextOptions->fontName); + fontDrawInterface = fontQueryInterface->GetFontDrawInterface(fontId); + } + if (!fontDrawInterface) { return AZ::Vector2(0.0f, 0.0f); } - STextDrawContext fontContext; - fontContext.SetEffect(actualTextOptions->effectIndex); - fontContext.SetSizeIn800x600(false); - fontContext.SetSize(vector2f(pointSize, pointSize)); + // Set up draw parameters + AzFramework::TextDrawParameters drawParams; + drawParams.m_drawViewportId = GetViewportContext()->GetId(); + drawParams.m_position = AZ::Vector3(0.0f, 0.0f, 1.0f); + drawParams.m_effectIndex = 0; + drawParams.m_textSizeFactor = pointSize; + drawParams.m_scale = AZ::Vector2(1.0f, 1.0f); + drawParams.m_lineSpacing = 1.0f; + drawParams.m_monospace = false; + drawParams.m_depthTest = false; + drawParams.m_virtual800x600ScreenSize = false; + drawParams.m_scaleWithWindow = false; + drawParams.m_multiline = true; - Vec2 textSize = actualTextOptions->font->GetTextSize(textString, true, fontContext); - return AZ::Vector2(textSize.x, textSize.y); + AZ::Vector2 textSize = fontDrawInterface->GetTextSize(drawParams, textString); + return textSize; } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -559,100 +583,89 @@ void CDraw2d::RotatePointsAboutPivot(AZ::Vector2* points, [[maybe_unused]] int n } //////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::DrawTextInternal(const char* textString, IFFont* font, unsigned int effectIndex, +void CDraw2d::DrawTextInternal(const char* textString, AzFramework::FontId fontId, unsigned int effectIndex, AZ::Vector2 position, float pointSize, AZ::Color color, float rotation, - HAlign horizontalAlignment, VAlign verticalAlignment, int baseState) + HAlign horizontalAlignment, VAlign verticalAlignment, [[maybe_unused]] int baseState) { - if (!font) - { - return; - } - - STextDrawContext fontContext; - fontContext.SetEffect(effectIndex); - fontContext.SetSizeIn800x600(false); - fontContext.SetSize(vector2f(pointSize, pointSize)); - fontContext.SetColor(ColorF(color.GetR(), color.GetG(), color.GetB(), color.GetA())); - fontContext.m_baseState = baseState; - fontContext.SetOverrideViewProjMatrices(false); - // FFont.cpp uses the alpha value of the color to decide whether to use the color, if the alpha value is zero // (in a ColorB format) then the color set via SetColor is ignored and it usually ends up drawing with an alpha of 1. // This is not what we want so in this case do not draw at all. - if (!fontContext.IsColorOverridden()) + if (AZ::IsClose(color.GetA(), 0.0f)) { return; } - AZ::Vector2 alignedPosition; - if (horizontalAlignment == HAlign::Left && verticalAlignment == VAlign::Top) + // Convert Draw2d alignment to text alignment + AzFramework::TextHorizontalAlignment hAlignment = AzFramework::TextHorizontalAlignment::Left; + switch (horizontalAlignment) { - alignedPosition = position; - } - else - { - // we align based on the size of the default font effect, because we do not want the - // text to move when the font effect is changed - unsigned int fontEffectIndex = fontContext.m_fxIdx; - fontContext.SetEffect(0); - Vec2 textSize = font->GetTextSize(textString, true, fontContext); - fontContext.SetEffect(fontEffectIndex); - - alignedPosition = Align(position, AZ::Vector2(textSize.x, textSize.y), horizontalAlignment, verticalAlignment); + case HAlign::Left: + hAlignment = AzFramework::TextHorizontalAlignment::Left; + break; + case HAlign::Center: + hAlignment = AzFramework::TextHorizontalAlignment::Center; + break; + case HAlign::Right: + hAlignment = AzFramework::TextHorizontalAlignment::Right; + break; + default: + AZ_Assert(false, "Attempting to draw text with unsupported horizontal alignment."); + break; } - int flags = 0; + AzFramework::TextVerticalAlignment vAlignment = AzFramework::TextVerticalAlignment::Top; + switch (verticalAlignment) + { + case VAlign::Top: + vAlignment = AzFramework::TextVerticalAlignment::Top; + break; + case VAlign::Center: + vAlignment = AzFramework::TextVerticalAlignment::Center; + break; + case VAlign::Bottom: + vAlignment = AzFramework::TextVerticalAlignment::Bottom; + break; + default: + AZ_Assert(false, "Attempting to draw text with unsupported vertical alignment."); + break; + } + + // Set up draw parameters for font interface + AzFramework::TextDrawParameters drawParams; + drawParams.m_drawViewportId = GetViewportContext()->GetId(); + drawParams.m_position = AZ::Vector3(position.GetX(), position.GetY(), 1.0f); + drawParams.m_color = color; + drawParams.m_effectIndex = effectIndex; + drawParams.m_textSizeFactor = pointSize; + drawParams.m_scale = AZ::Vector2(1.0f, 1.0f); + drawParams.m_lineSpacing = 1.0f; //!< Spacing between new lines, as a percentage of m_scale. + drawParams.m_hAlign = hAlignment; + drawParams.m_vAlign = vAlignment; + drawParams.m_monospace = false; + drawParams.m_depthTest = false; + drawParams.m_virtual800x600ScreenSize = false; + drawParams.m_scaleWithWindow = false; + drawParams.m_multiline = true; + if (rotation != 0.0f) { // rotate around the position (if aligned to center will rotate about center etc) float rotRad = DEG2RAD(rotation); - Vec3 pivot(position.GetX(), position.GetY(), 0.0f); - Matrix34A moveToPivotSpaceMat = Matrix34A::CreateTranslationMat(-pivot); - Matrix34A rotMat = Matrix34A::CreateRotationZ(rotRad); - Matrix34A moveFromPivotSpaceMat = Matrix34A::CreateTranslationMat(pivot); + AZ::Vector3 pivot(position.GetX(), position.GetY(), 0.0f); + AZ::Matrix3x4 moveToPivotSpaceMat = AZ::Matrix3x4::CreateTranslation(-pivot); + AZ::Matrix3x4 rotMat = AZ::Matrix3x4::CreateRotationZ(rotRad); + AZ::Matrix3x4 moveFromPivotSpaceMat = AZ::Matrix3x4::CreateTranslation(pivot); - Matrix34A transform = moveFromPivotSpaceMat * rotMat * moveToPivotSpaceMat; - fontContext.SetTransform(transform); - flags |= eDrawText_UseTransform; + drawParams.m_transform = moveFromPivotSpaceMat * rotMat * moveToPivotSpaceMat; + drawParams.m_useTransform = true; } - // The font system uses these alignment flags to force text to be in the safe zone - // depending on overscan etc - if (horizontalAlignment == HAlign::Center) - { - flags |= eDrawText_Center; - } - else if (horizontalAlignment == HAlign::Right) - { - flags |= eDrawText_Right; - } + DeferredText newText; + newText.m_drawParameters = drawParams; + newText.m_fontId = fontId; + newText.m_string = textString; - if (verticalAlignment == VAlign::Center) - { - flags |= eDrawText_CenterV; - } - else if (verticalAlignment == VAlign::Bottom) - { - flags |= eDrawText_Bottom; - } - - fontContext.SetFlags(flags); - - if (m_deferCalls) - { - DeferredText* newText = new DeferredText; - - newText->m_fontContext = fontContext; - newText->m_font = font; - newText->m_position = alignedPosition; - newText->m_string = textString; - - m_deferredPrimitives.push_back(newText); - } - else - { - font->DrawString(alignedPosition.GetX(), alignedPosition.GetY(), textString, true, fontContext); - } + DrawOrDeferTextString(&newText); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -685,6 +698,20 @@ void CDraw2d::DrawOrDeferLine(const DeferredLine* line) } } +void CDraw2d::DrawOrDeferTextString(const DeferredText* text) +{ + if (m_deferCalls) + { + DeferredText* newText = new DeferredText; + *newText = *text; + m_deferredPrimitives.push_back(newText); + } + else + { + text->Draw(m_dynamicDraw, m_shaderData, GetViewportContext()); + } +} + void CDraw2d::DrawOrDeferRectOutline(const DeferredRectOutline* rectOutline) { if (m_deferCalls) @@ -919,6 +946,15 @@ void CDraw2d::DeferredText::Draw([[maybe_unused]] AZ::RHI::PtrDrawString(m_position.GetX(), m_position.GetY(), m_string.c_str(), true, m_fontContext); + AzFramework::FontDrawInterface* fontDrawInterface = nullptr; + AzFramework::FontQueryInterface* fontQueryInterface = AZ::Interface::Get(); + if (fontQueryInterface) + { + fontDrawInterface = fontQueryInterface->GetFontDrawInterface(m_fontId); + if (fontDrawInterface) + { + fontDrawInterface->DrawScreenAlignedText2d(m_drawParameters, m_string.c_str()); + } + } } diff --git a/Gems/LyShine/Code/Source/LyShine.cpp b/Gems/LyShine/Code/Source/LyShine.cpp index 679cae3421..fb6dcb2628 100644 --- a/Gems/LyShine/Code/Source/LyShine.cpp +++ b/Gems/LyShine/Code/Source/LyShine.cpp @@ -454,7 +454,6 @@ void CLyShine::Render() GetUiRenderer()->EndUiFrameRender(); -#ifdef LYSHINE_ATOM_TODO // convert debug info to Atom #ifndef _RELEASE if (CV_ui_DisplayElemBounds) { @@ -474,7 +473,6 @@ void CLyShine::Render() m_uiCanvasManager->DebugDisplayDrawCallData(); } #endif -#endif } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/LyShine/Code/Source/LyShineDebug.cpp b/Gems/LyShine/Code/Source/LyShineDebug.cpp index 76b4030106..44e0e187ec 100644 --- a/Gems/LyShine/Code/Source/LyShineDebug.cpp +++ b/Gems/LyShine/Code/Source/LyShineDebug.cpp @@ -12,6 +12,7 @@ #include "LyShine_precompiled.h" #include "LyShineDebug.h" #include "IConsole.h" +#include "IRenderer.h" #include #include @@ -392,15 +393,15 @@ static void DebugDrawColoredBox(AZ::Vector2 pos, AZ::Vector2 size, AZ::Color col //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) -static void DebugDrawStringWithSizeBox(IFFont* font, unsigned int effectIndex, const char* sizeString, +static void DebugDrawStringWithSizeBox(AZStd::string_view font, unsigned int effectIndex, const char* sizeString, const char* testString, AZ::Vector2 pos, float spacing, float size) { CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); IDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions(); - if (font) + if (!font.empty()) { - textOptions.font = font; + textOptions.fontName = font; } textOptions.effectIndex = effectIndex; @@ -427,7 +428,7 @@ static void DebugDrawStringWithSizeBox(IFFont* font, unsigned int effectIndex, c //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) -static void DebugDraw2dFontSizes(IFFont* font, unsigned int effectIndex, const char* fontName) +static void DebugDraw2dFontSizes(AZStd::string_view font, unsigned int effectIndex) { CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); @@ -436,7 +437,7 @@ static void DebugDraw2dFontSizes(IFFont* font, unsigned int effectIndex, const c float xSpacing = 20.0f; char buffer[32]; - sprintf_s(buffer, "Font = %s, effect = %d", fontName, effectIndex); + sprintf_s(buffer, "Font = %s, effect = %d", font.data(), effectIndex); draw2d->DrawText(buffer, AZ::Vector2(xOffset, yOffset), 32); yOffset += 40.0f; draw2d->DrawText("NOTE: if the effect includes a drop shadow baked into font then the pixel size", @@ -1441,10 +1442,10 @@ void LyShineDebug::RenderDebug() switch (CV_r_DebugUIDraw2dFont) { case 1: // test font sizes (default font, effect 0) - DebugDraw2dFontSizes(0, 0, "default"); + DebugDraw2dFontSizes("default", 0); break; case 2: // test font sizes (default font, effect 1) - DebugDraw2dFontSizes(0, 1, "default"); + DebugDraw2dFontSizes("default", 1); break; case 3: // test font alignment DebugDraw2dFontAlignment(); diff --git a/Gems/LyShine/Code/Source/LyShineDebug.h b/Gems/LyShine/Code/Source/LyShineDebug.h index ed03fd10b2..e50689710a 100644 --- a/Gems/LyShine/Code/Source/LyShineDebug.h +++ b/Gems/LyShine/Code/Source/LyShineDebug.h @@ -14,7 +14,9 @@ #ifndef _RELEASE #include -class ITexture; +#include +#include + #endif //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -66,7 +68,7 @@ public: // static member functions struct DebugInfoTextureUsage { - ITexture* m_texture; + AZ::Data::Instance m_texture; bool m_isClampTextureUsage; int m_numCanvasesUsed; int m_numDrawCallsUsed; diff --git a/Gems/LyShine/Code/Source/RenderGraph.cpp b/Gems/LyShine/Code/Source/RenderGraph.cpp index e5ac6c7b8f..d5a1df7b15 100644 --- a/Gems/LyShine/Code/Source/RenderGraph.cpp +++ b/Gems/LyShine/Code/Source/RenderGraph.cpp @@ -18,6 +18,7 @@ #include #ifndef _RELEASE +#include #include #endif @@ -1115,7 +1116,7 @@ namespace LyShine m_wasBuiltThisFrame = false; - AZStd::set uniqueTextures; + AZStd::set> uniqueTextures; // If we are rendering to the render targets this frame then record the stats for doing that if (m_renderToRenderTargetCount < 2) @@ -1144,13 +1145,11 @@ namespace LyShine } //////////////////////////////////////////////////////////////////////////////////////////////////// - void RenderGraph::GetDebugInfoRenderNodeList(const AZStd::vector& renderNodeList, LyShineDebug::DebugInfoRenderGraph& info, AZStd::set& uniqueTextures) const + void RenderGraph::GetDebugInfoRenderNodeList( + const AZStd::vector& renderNodeList, + LyShineDebug::DebugInfoRenderGraph& info, + AZStd::set>& uniqueTextures) const { - AZ_UNUSED(renderNodeList); - AZ_UNUSED(info); - AZ_UNUSED(uniqueTextures); - -#ifdef LYSHINE_ATOM_TODO // keeping this code for future phase (convert debug info to use Atom) const PrimitiveListRenderNode* prevPrimListNode = nullptr; bool isFirstNode = true; bool wasLastNodeAMask = false; @@ -1235,7 +1234,6 @@ namespace LyShine isFirstNode = false; } -#endif } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1290,13 +1288,6 @@ namespace LyShine void* context, const AZStd::string& indent) const { - AZ_UNUSED(renderNodeList); - AZ_UNUSED(fileHandle); - AZ_UNUSED(reportInfo); - AZ_UNUSED(context); - AZ_UNUSED(indent); - -#ifdef LYSHINE_ATOM_TODO // keeping this code for future phase (convert debug info to use Atom) AZStd::string logLine; bool previousNodeAlreadyCounted = false; @@ -1355,10 +1346,10 @@ namespace LyShine { for (int i = 0; i < prevPrimListNode->GetNumTextures(); ++i) { - ITexture* texture = prevPrimListNode->GetTexture(i); + AZ::Data::Instance texture = prevPrimListNode->GetTexture(i); if (!texture) { - texture = gEnv->pRenderer->GetWhiteTexture(); + texture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); } bool isClampTextureUsage = prevPrimListNode->GetTextureIsClampMode(i); @@ -1405,17 +1396,19 @@ namespace LyShine for (int i = 0; i < primListRenderNode->GetNumTextures(); ++i) { - ITexture* texture = primListRenderNode->GetTexture(i); + AZ::Data::Instance texture = primListRenderNode->GetTexture(i); if (!texture) { - texture = gEnv->pRenderer->GetWhiteTexture(); + texture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); } bool isClampTextureUsage = primListRenderNode->GetTextureIsClampMode(i); LyShineDebug::DebugInfoTextureUsage* matchingTextureUsage = nullptr; // Write line to logfile for this texture - logLine = AZStd::string::format("%s %s\r\n", indent.c_str(), texture->GetName()); + AZStd::string textureName; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(textureName, &AZ::Data::AssetCatalogRequests::GetAssetPathById, texture->GetAssetId()); + logLine = AZStd::string::format("%s %s\r\n", indent.c_str(), textureName.c_str()); AZ::IO::LocalFileIO::GetInstance()->Write(fileHandle, logLine.c_str(), logLine.size()); // see if texture is in reportInfo @@ -1459,7 +1452,6 @@ namespace LyShine prevPrimListNode = primListRenderNode; } } -#endif } #endif diff --git a/Gems/LyShine/Code/Source/RenderGraph.h b/Gems/LyShine/Code/Source/RenderGraph.h index f9d16cf8b7..2f1586e857 100644 --- a/Gems/LyShine/Code/Source/RenderGraph.h +++ b/Gems/LyShine/Code/Source/RenderGraph.h @@ -13,7 +13,6 @@ #pragma once #include -#include #include #include #include @@ -294,7 +293,10 @@ namespace LyShine void ValidateGraph(); void GetDebugInfoRenderGraph(LyShineDebug::DebugInfoRenderGraph& info) const; - void GetDebugInfoRenderNodeList(const AZStd::vector& renderNodeList, LyShineDebug::DebugInfoRenderGraph& info, AZStd::set& uniqueTextures) const; + void GetDebugInfoRenderNodeList( + const AZStd::vector& renderNodeList, + LyShineDebug::DebugInfoRenderGraph& info, + AZStd::set>& uniqueTextures) const; void DebugReportDrawCalls(AZ::IO::HandleType fileHandle, LyShineDebug::DebugInfoDrawCallReport& reportInfo, void* context) const; void DebugReportDrawCallsRenderNodeList(const AZStd::vector& renderNodeList, AZ::IO::HandleType fileHandle, diff --git a/Gems/LyShine/Code/Source/UiCanvasManager.cpp b/Gems/LyShine/Code/Source/UiCanvasManager.cpp index 4115feaf22..b64a13280f 100644 --- a/Gems/LyShine/Code/Source/UiCanvasManager.cpp +++ b/Gems/LyShine/Code/Source/UiCanvasManager.cpp @@ -1425,7 +1425,8 @@ void UiCanvasManager::DebugReportDrawCalls(const AZStd::string& name) const if (reportTextureUsage.m_numCanvasesUsed > 1 && reportTextureUsage.m_numDrawCallsWhereExceedingMaxTextures) { - AZStd::string textureName = reportTextureUsage.m_texture->GetName(); + AZStd::string textureName; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(textureName, &AZ::Data::AssetCatalogRequests::GetAssetPathById, reportTextureUsage.m_texture->GetAssetId()); if (textureName.compare(0, fontTexturePrefix.length(), fontTexturePrefix) != 0) { logLine = AZStd::string::format("%s\r\n", textureName.c_str()); @@ -1457,7 +1458,8 @@ void UiCanvasManager::DebugReportDrawCalls(const AZStd::string& name) const reportTextureUsage.m_lastContextUsed == canvas && reportTextureUsage.m_numDrawCallsWhereExceedingMaxTextures) { - AZStd::string textureName = reportTextureUsage.m_texture->GetName(); + AZStd::string textureName; + AZ::Data::AssetCatalogRequestBus::BroadcastResult(textureName, &AZ::Data::AssetCatalogRequests::GetAssetPathById, reportTextureUsage.m_texture->GetAssetId()); // exclude font textures if (textureName.compare(0, fontTexturePrefix.length(), fontTexturePrefix) != 0) diff --git a/Gems/LyShine/Code/Source/UiRenderer.cpp b/Gems/LyShine/Code/Source/UiRenderer.cpp index 2a2c950e82..57acbed5d5 100644 --- a/Gems/LyShine/Code/Source/UiRenderer.cpp +++ b/Gems/LyShine/Code/Source/UiRenderer.cpp @@ -12,6 +12,7 @@ #include "LyShine_precompiled.h" #include "UiRenderer.h" +#include #include #include #include @@ -24,7 +25,7 @@ #include #include -#include +#include //////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC MEMBER FUNCTIONS @@ -353,7 +354,6 @@ void UiRenderer::DebugDisplayTextureData(int recordingOption) { if (recordingOption > 0) { -#ifdef LYSHINE_ATOM_TODO // compute the total area of all the textures, also create a vector that we can sort by area AZStd::vector textures; int totalArea = 0; @@ -374,15 +374,14 @@ void UiRenderer::DebugDisplayTextureData(int recordingOption) return lhs->GetDataSize() > rhs->GetDataSize(); }); - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); // setup to render lines of text for the debug display - draw2d->BeginDraw2d(false); float xOffset = 20.0f; float yOffset = 20.0f; - int blackTexture = gEnv->pRenderer->GetBlackTextureId(); + auto blackTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::Black); float textOpacity = 1.0f; float backgroundRectOpacity = 0.75f; const float lineSpacing = 20.0f; @@ -432,9 +431,6 @@ void UiRenderer::DebugDisplayTextureData(int recordingOption) texture->GetWidth(), texture->GetHeight(), texture->GetDataSize(), texture->GetFormatName(), texture->GetName()); WriteLine(buffer, white); } - - draw2d->EndDraw2d(); -#endif } } diff --git a/Gems/LyShine/Code/Source/UiRenderer.h b/Gems/LyShine/Code/Source/UiRenderer.h index 260bd8278c..888c88586a 100644 --- a/Gems/LyShine/Code/Source/UiRenderer.h +++ b/Gems/LyShine/Code/Source/UiRenderer.h @@ -20,6 +20,8 @@ #include #endif +class ITexture; + //////////////////////////////////////////////////////////////////////////////////////////////////// //! UI render interface // @@ -136,8 +138,6 @@ protected: // attributes #ifndef _RELEASE int m_debugTextureDataRecordLevel = 0; -#ifdef LYSHINE_ATOM_TODO // Convert debug code to Atom - AZStd::unordered_set m_texturesUsedInFrame; -#endif + AZStd::unordered_set m_texturesUsedInFrame; // LYSHINE_ATOM_TODO - convert to RPI::Image #endif }; diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleFrame.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleFrame.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleFrame.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleFrame.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleGradient.png.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleGradient.png.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleGradient.png.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleGradient.png.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/Circle_Shadow.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/Circle_Shadow.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/Circle_Shadow.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/Circle_Shadow.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTest.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTest.tif.assetinfo index c6f6ca1e9c..c8704c4e0d 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTest.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTest.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTestPow2.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTestPow2.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTestPow2.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTestPow2.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ParticleGlow.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ParticleGlow.tif.assetinfo index dd1d22706e..e508d7465a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ParticleGlow.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ParticleGlow.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/button.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/button.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/button.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/button.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonPressed.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonPressed.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonPressed.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonPressed.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonSlider.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonSlider.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonSlider.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonSlider.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkbox_spritesheet.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkbox_spritesheet.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkbox_spritesheet.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkbox_spritesheet.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkered3.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkered3.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkered3.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkered3.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/empty_icon.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/empty_icon.tif.assetinfo index dd1d22706e..e508d7465a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/empty_icon.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/empty_icon.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/fixed_image.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/fixed_image.tif.assetinfo index c6f6ca1e9c..c8704c4e0d 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/fixed_image.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/fixed_image.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/flipbook_walking.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/flipbook_walking.tif.assetinfo index c6f6ca1e9c..c8704c4e0d 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/flipbook_walking.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/flipbook_walking.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/mask.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/mask.tif.assetinfo index dd1d22706e..e508d7465a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/mask.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/mask.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outline.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outline.tif.assetinfo index c6f6ca1e9c..c8704c4e0d 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outline.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outline.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outlineRounded.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outlineRounded.tif.assetinfo index c6f6ca1e9c..c8704c4e0d 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outlineRounded.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outlineRounded.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/panelBkgd.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/panelBkgd.tif.assetinfo index c6f6ca1e9c..c8704c4e0d 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/panelBkgd.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/panelBkgd.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02_big.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02_big.tif.assetinfo index dd1d22706e..e508d7465a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02_big.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02_big.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical_big.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical_big.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical_big.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical_big.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03_big.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03_big.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03_big.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03_big.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_1.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_1.tif.assetinfo index dd1d22706e..e508d7465a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_1.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_1.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_10.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_10.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_10.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_10.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_2.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_2.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_2.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_2.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_3.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_3.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_3.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_3.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_4.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_4.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_4.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_4.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_5.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_5.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_5.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_5.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_6.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_6.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_6.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_6.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_7.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_7.tif.assetinfo index dd1d22706e..e508d7465a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_7.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_7.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_8.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_8.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_8.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_8.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_9.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_9.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_9.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_9.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_map.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_map.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_map.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_map.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/selected.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/selected.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/selected.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/selected.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInside2.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInside2.tif.assetinfo index dd1d22706e..e508d7465a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInside2.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInside2.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInsideSquare.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInsideSquare.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInsideSquare.tif.assetinfo +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInsideSquare.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken_diff.png.imagesettings b/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken_diff.png.imagesettings index dd621c891f..adbf7d20f9 100644 --- a/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken_diff.png.imagesettings +++ b/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken_diff.png.imagesettings @@ -17,7 +17,7 @@ - + @@ -36,7 +36,7 @@ - + diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_diff.tif.exportsettings index 8d01ab1ac2..e97c4e452c 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_diff.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_diff.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="es3:0,ios:0,osx_gl:0,pc:2,provo:0,wiiu:0" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="android:0,ios:0,mac:0,pc:2,provo:0,wiiu:0" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel_ddna.tif.exportsettings index f1f2f06410..a098bdcad9 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel_ddna.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel_ddna.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="es3:1,ios:1,osx_gl:1,pc:0,provo:1,wiiu:1" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather_diff.tif.exportsettings index 2a29854fae..19e899701a 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather_diff.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather_diff.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="es3:1,ios:1,osx_gl:1,pc:0,provo:1,wiiu:1" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_spec.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_spec.tif.exportsettings index 93bcddc494..08861692ea 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_spec.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_spec.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Reflectance /reduce="es3:0,ios:0,osx_gl:0,pc:1,provo:0,wiiu:0" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Reflectance /reduce="android:0,ios:0,mac:0,pc:1,provo:0,wiiu:0" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/leather_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/leather_ddna.tif.exportsettings index f1f2f06410..a098bdcad9 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/leather_ddna.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/leather_ddna.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="es3:1,ios:1,osx_gl:1,pc:0,provo:1,wiiu:1" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather_diff.tif.exportsettings index 2a29854fae..19e899701a 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather_diff.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather_diff.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="es3:1,ios:1,osx_gl:1,pc:0,provo:1,wiiu:1" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_ddna.tif.exportsettings index f1f2f06410..a098bdcad9 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_ddna.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_ddna.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="es3:1,ios:1,osx_gl:1,pc:0,provo:1,wiiu:1" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_diff.tif.exportsettings index 2a29854fae..19e899701a 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_diff.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_diff.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="es3:1,ios:1,osx_gl:1,pc:0,provo:1,wiiu:1" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/red_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/red_diff.tif.exportsettings index 54586c2db1..48c18e1fe4 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/red_diff.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/red_diff.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="es3:0,ios:0,osx_gl:0,pc:3,provo:0,wiiu:0" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="android:0,ios:0,mac:0,pc:3,provo:0,wiiu:0" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rotary_brushed_steel_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rotary_brushed_steel_ddna.tif.exportsettings index f1f2f06410..a098bdcad9 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rotary_brushed_steel_ddna.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rotary_brushed_steel_ddna.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="es3:1,ios:1,osx_gl:1,pc:0,provo:1,wiiu:1" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_ddna.tif.exportsettings index f1f2f06410..a098bdcad9 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_ddna.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_ddna.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="es3:1,ios:1,osx_gl:1,pc:0,provo:1,wiiu:1" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_diff.tif.exportsettings index 2a29854fae..19e899701a 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_diff.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_diff.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="es3:1,ios:1,osx_gl:1,pc:0,provo:1,wiiu:1" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_ddna.tif.exportsettings index f1f2f06410..a098bdcad9 100644 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_ddna.tif.exportsettings +++ b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_ddna.tif.exportsettings @@ -1 +1 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="es3:1,ios:1,osx_gl:1,pc:0,provo:1,wiiu:1" +/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PhysX/Code/Source/Pipeline/MeshExporter.cpp b/Gems/PhysX/Code/Source/Pipeline/MeshExporter.cpp index 7069f9a05d..3aeb3ad797 100644 --- a/Gems/PhysX/Code/Source/Pipeline/MeshExporter.cpp +++ b/Gems/PhysX/Code/Source/Pipeline/MeshExporter.cpp @@ -328,7 +328,7 @@ namespace PhysX physx::PxMeshMidPhase::Enum ret = physx::PxMeshMidPhase::eBVH34; // Fallback to 3.3 on Android and iOS platforms since they don't support SSE2, which is required for 3.4 - if (platformIdentifier == "es3" || platformIdentifier == "ios") + if (platformIdentifier == "android" || platformIdentifier == "ios") { ret = physx::PxMeshMidPhase::eBVH33; } diff --git a/Gems/PhysX/Code/Source/RigidBodyComponent.cpp b/Gems/PhysX/Code/Source/RigidBodyComponent.cpp index feb35ea07d..40cac1e19e 100644 --- a/Gems/PhysX/Code/Source/RigidBodyComponent.cpp +++ b/Gems/PhysX/Code/Source/RigidBodyComponent.cpp @@ -201,7 +201,7 @@ namespace PhysX AZ::Quaternion newRotation = AZ::Quaternion::CreateIdentity(); m_interpolator->GetInterpolated(newPosition, newRotation, deltaTime); - AZ::TransformBus::Event(GetEntityId(), &AZ::TransformInterface::SetRotationQuaternion, newRotation); + AZ::TransformBus::Event(GetEntityId(), &AZ::TransformInterface::SetWorldRotationQuaternion, newRotation); AZ::TransformBus::Event(GetEntityId(), &AZ::TransformInterface::SetWorldTranslation, newPosition); } } @@ -256,7 +256,7 @@ namespace PhysX } else { - AZ::TransformBus::Event(GetEntityId(), &AZ::TransformInterface::SetRotationQuaternion, rigidBody->GetOrientation()); + AZ::TransformBus::Event(GetEntityId(), &AZ::TransformInterface::SetWorldRotationQuaternion, rigidBody->GetOrientation()); AZ::TransformBus::Event(GetEntityId(), &AZ::TransformInterface::SetWorldTranslation, rigidBody->GetPosition()); } m_isLastMovementFromKinematicSource = false; diff --git a/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_ddna.tif.imagesettings b/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_ddna.tif.imagesettings index c2fe2400cb..9da169c456 100644 --- a/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_ddna.tif.imagesettings +++ b/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_ddna.tif.imagesettings @@ -17,7 +17,7 @@ - + @@ -81,7 +81,7 @@ - + diff --git a/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_spec.tif.imagesettings b/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_spec.tif.imagesettings index c3632028c2..43410a50df 100644 --- a/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_spec.tif.imagesettings +++ b/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_spec.tif.imagesettings @@ -17,7 +17,7 @@ - + @@ -81,7 +81,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Normal.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Normal.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Normal.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Normal.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Pressed.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Pressed.tif.assetinfo index dd1d22706e..e508d7465a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Pressed.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Pressed.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Selected.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Selected.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Selected.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Selected.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Normal.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Normal.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Normal.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Normal.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Pressed.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Pressed.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Pressed.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Pressed.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Selected.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Selected.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Selected.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Selected.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check_Background.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check_Background.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check_Background.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check_Background.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Cross.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Cross.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Cross.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Cross.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Off.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Off.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Off.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Off.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_On.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_On.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_On.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_On.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Disabled.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Disabled.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Disabled.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Disabled.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Hover.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Hover.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Hover.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Hover.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Normal.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Normal.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Normal.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Normal.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Checkered.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Checkered.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Checkered.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Checkered.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Disabled.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Disabled.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Disabled.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Disabled.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Hover.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Hover.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Hover.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Hover.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Normal.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Normal.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Normal.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Normal.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Sliced.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Sliced.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Sliced.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Sliced.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Stretch.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Stretch.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Stretch.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Stretch.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Manipulator.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Manipulator.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Slider_Manipulator.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Manipulator.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Sliced.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Sliced.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Sliced.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Sliced.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Stretch.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Stretch.tif.assetinfo index dd1d22706e..e508d7465a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Stretch.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Stretch.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Normal.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Normal.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Normal.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Normal.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Pressed.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Pressed.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Pressed.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Pressed.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Selected.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Selected.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Selected.tif.assetinfo +++ b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Selected.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Arrow.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Arrow.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Arrow.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Arrow.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowL.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowL.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowL.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowL.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowR.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowR.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowR.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowR.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowU.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowU.tif.assetinfo index dd1d22706e..e508d7465a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowU.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowU.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Button.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Button.tif.assetinfo index 95b548a2eb..f808dda121 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Button.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Button.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Menu.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Menu.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Menu.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Menu.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Disabled.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Disabled.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Disabled.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Hover.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Hover.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Hover.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Hover.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Normal.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Normal.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Normal.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Dot.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Dot.tif.assetinfo index c6f6ca1e9c..c8704c4e0d 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Dot.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Dot.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/button_disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/button_disabled.tif.assetinfo index c6f6ca1e9c..c8704c4e0d 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/button_disabled.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/button_disabled.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/button_normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/button_normal.tif.assetinfo index c6f6ca1e9c..c8704c4e0d 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/button_normal.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/button_normal.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_disabled.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_disabled.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_disabled.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_hover.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_hover.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_hover.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_hover.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_normal.tif.assetinfo index 2eb5be8e93..54e075dd32 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_normal.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_normal.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -56,7 +56,7 @@ - + @@ -64,7 +64,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_check.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_check.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_check.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_check.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_handle.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_handle.tif.assetinfo index 95b548a2eb..f808dda121 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_handle.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_handle.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_horiz_track.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_horiz_track.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_horiz_track.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_horiz_track.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_vert_track.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_vert_track.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_vert_track.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_vert_track.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_disabled.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_disabled.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_disabled.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_normal.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_normal.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_normal.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_disabled.tif.assetinfo index 95b548a2eb..f808dda121 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_disabled.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_disabled.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_normal.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_normal.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_normal.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_disabled.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_disabled.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_disabled.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_normal.tif.assetinfo index 61b2832ff3..47b628d60a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_normal.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_normal.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_disabled.tif.assetinfo index c6f6ca1e9c..c8704c4e0d 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_disabled.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_disabled.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_hover.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_hover.tif.assetinfo index c6f6ca1e9c..c8704c4e0d 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_hover.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_hover.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_normal.tif.assetinfo index c6f6ca1e9c..c8704c4e0d 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_normal.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_normal.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/tooltip_sliced.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/tooltip_sliced.tif.assetinfo index dd1d22706e..e508d7465a 100644 --- a/Gems/UiBasics/Assets/UI/Textures/Prefab/tooltip_sliced.tif.assetinfo +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/tooltip_sliced.tif.assetinfo @@ -17,7 +17,7 @@ - + @@ -38,7 +38,7 @@ - + diff --git a/Registry/AssetProcessorPlatformConfig.setreg b/Registry/AssetProcessorPlatformConfig.setreg index 5f397db06b..2147842da7 100644 --- a/Registry/AssetProcessorPlatformConfig.setreg +++ b/Registry/AssetProcessorPlatformConfig.setreg @@ -24,13 +24,13 @@ "Platform pc": { "tags": "tools,renderer,dx12,vulkan,null" }, - "Platform es3": { + "Platform android": { "tags": "android,mobile,renderer,vulkan" }, "Platform ios": { "tags": "mobile,renderer,metal" }, - "Platform osx_gl": { + "Platform mac": { "tags": "tools,renderer,metal,null" }, // this is an example of a headless platform that has no renderer. @@ -43,9 +43,9 @@ // To enable any additional platform, just uncomment the appropriate line below. "Platforms": { //"pc": "enabled", - //"es3": "enabled", + //"android": "enabled", //"ios": "enabled", - //"osx_gl": "enabled", + //"mac": "enabled", //"server": "enabled" }, // ---- The number of worker jobs, 0 means use the number of Logical Cores @@ -95,11 +95,11 @@ // "exclude": "(comma seperated platform tags or identifiers)" // } // For example if you want to include a scan folder only for platforms that have the platform tags tools and renderer - // but omit it for platform osx_gl, you will have a scanfolder rule like + // but omit it for platform mac, you will have a scanfolder rule like // "ScanFolder (unique identifier)": { // "watch": "@ROOT@/foo", // "include": "tools, renderer", - // "exclude": "osx_gl" + // "exclude": "mac" // } "ScanFolder Game": { diff --git a/Registry/bootstrap.setreg b/Registry/bootstrap.setreg index b0c954a127..ccbf744232 100644 --- a/Registry/bootstrap.setreg +++ b/Registry/bootstrap.setreg @@ -8,9 +8,9 @@ "ios_remote_filesystem": 0, "mac_remote_filesystem": 0, "assets": "pc", - "android_assets": "es3", + "android_assets": "android", "ios_assets": "ios", - "mac_assets": "osx_gl", + "mac_assets": "mac", "allowed_list": "", "remote_ip": "127.0.0.1", "remote_port": 45643, diff --git a/Templates/DefaultProject/Template/preview.png b/Templates/DefaultProject/Template/preview.png index 2191a0ebc2..3d4fe78063 100644 --- a/Templates/DefaultProject/Template/preview.png +++ b/Templates/DefaultProject/Template/preview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a18fae4040a22d2bb359a8ca642b97bb8f6468eeb52e2826b3b029bd8f1350b6 -size 5466 +oid sha256:40949893ed7009eeaa90b7ce6057cb6be9dfaf7b162e3c26ba9dadf985939d7d +size 2038 diff --git a/Tools/LyTestTools/ly_test_tools/_internal/managers/platforms/mac.py b/Tools/LyTestTools/ly_test_tools/_internal/managers/platforms/mac.py index 453e80ac41..4e19a3955a 100755 --- a/Tools/LyTestTools/ly_test_tools/_internal/managers/platforms/mac.py +++ b/Tools/LyTestTools/ly_test_tools/_internal/managers/platforms/mac.py @@ -21,8 +21,8 @@ from ly_test_tools._internal.managers.abstract_resource_locator import AbstractR logger = logging.getLogger(__name__) -CACHE_DIR = 'osx_gl' -CONFIG_FILE = 'system_osx_osx_gl.cfg' +CACHE_DIR = 'mac' +CONFIG_FILE = 'system_osx_mac.cfg' class _MacResourceLocator(AbstractResourceLocator): @@ -33,7 +33,7 @@ class _MacResourceLocator(AbstractResourceLocator): def platform_config_file(self): """ Return the path to the platform config file. - ex. engine_root/dev/system_osx_osx_gl.cfg + ex. engine_root/dev/system_osx_mac.cfg :return: path to the platform config file """ return os.path.join(self.engine_root(), CONFIG_FILE) diff --git a/Tools/LyTestTools/ly_test_tools/_internal/managers/platforms/windows.py b/Tools/LyTestTools/ly_test_tools/_internal/managers/platforms/windows.py index 80ac413dbb..db6e7d713d 100755 --- a/Tools/LyTestTools/ly_test_tools/_internal/managers/platforms/windows.py +++ b/Tools/LyTestTools/ly_test_tools/_internal/managers/platforms/windows.py @@ -39,7 +39,7 @@ class _WindowsResourceLocator(AbstractResourceLocator): def platform_config_file(self): """ Return the path to the platform config file. - ex. engine_root/dev/system_osx_osx_gl.cfg + ex. engine_root/dev/system_osx_mac.cfg :return: path to the platform config file """ return os.path.join(self.engine_root(), CONFIG_FILE) diff --git a/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py index d8b08cad24..8e2b93c20a 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py @@ -36,10 +36,10 @@ DEFAULT_TIMEOUT_HOURS = 8 DEFAULT_TIMEOUT_SECONDS = 300 ASSET_PROCESSOR_PLATFORM_MAP = { - 'android': 'es3', + 'android': 'android', 'ios': 'ios', 'linux': 'linux', # Not fully implemented, see SPEC-2501 - 'mac': 'osx_gl', + 'mac': 'mac', 'windows': 'pc', } diff --git a/cmake/Platform/Android/PAL_android.cmake b/cmake/Platform/Android/PAL_android.cmake index bb4ac5f32b..5f35767f98 100644 --- a/cmake/Platform/Android/PAL_android.cmake +++ b/cmake/Platform/Android/PAL_android.cmake @@ -35,7 +35,7 @@ else() endif() # Set the default asset type for deployment -set(LY_ASSET_DEPLOY_ASSET_TYPE "es3" CACHE STRING "Set the asset type for deployment.") +set(LY_ASSET_DEPLOY_ASSET_TYPE "android" CACHE STRING "Set the asset type for deployment.") # Set the python cmd tool if(PAL_HOST_PLATFORM_NAME_LOWERCASE STREQUAL "windows") diff --git a/cmake/Platform/Mac/PAL_mac.cmake b/cmake/Platform/Mac/PAL_mac.cmake index f6cf034312..988d36af14 100644 --- a/cmake/Platform/Mac/PAL_mac.cmake +++ b/cmake/Platform/Mac/PAL_mac.cmake @@ -35,7 +35,7 @@ else() endif() # Set the default asset type for deployment -set(LY_ASSET_DEPLOY_ASSET_TYPE "osx_gl" CACHE STRING "Set the asset type for deployment.") +set(LY_ASSET_DEPLOY_ASSET_TYPE "mac" CACHE STRING "Set the asset type for deployment.") # Set the python cmd tool ly_set(LY_PYTHON_CMD ${CMAKE_CURRENT_SOURCE_DIR}/python/python.sh) diff --git a/cmake/Tools/Platform/Android/android_deployment.py b/cmake/Tools/Platform/Android/android_deployment.py index 8a76270df1..eb8361ec18 100755 --- a/cmake/Tools/Platform/Android/android_deployment.py +++ b/cmake/Tools/Platform/Android/android_deployment.py @@ -62,7 +62,7 @@ class AndroidDeployment(object): :param deployment_type: The type of deployment (DEPLOY_APK_ONLY, DEPLOY_ASSETS_ONLY, or DEPLOY_BOTH) :param game_name: The name of the game whose assets are being deployed. None if is_test_project is True :param asset_mode: The asset mode of deployment (LOOSE, PAK, VFS). None if is_test_project is True - :param asset_type: The asset type (for android, 'es3'). None if is_test_project is True + :param asset_type: The asset type. None if is_test_project is True :param embedded_assets: Boolean to indicate if the assets are embedded in the APK or not :param is_unit_test: Boolean to indicate if this is a unit test deployment """ diff --git a/cmake/Tools/Platform/Android/generate_android_project.py b/cmake/Tools/Platform/Android/generate_android_project.py index f3f6a3acda..9a0e2760f5 100755 --- a/cmake/Tools/Platform/Android/generate_android_project.py +++ b/cmake/Tools/Platform/Android/generate_android_project.py @@ -118,7 +118,7 @@ ASSET_MODE_LOOSE = 'LOOSE' ASSET_MODE_VFS = 'VFS' ALL_ASSET_MODES = [ASSET_MODE_PAK, ASSET_MODE_LOOSE, ASSET_MODE_VFS] ASSET_TYPE_ARGUMENT_NAME = '--asset-type' -DEFAULT_ASSET_TYPE = 'es3' +DEFAULT_ASSET_TYPE = 'android' def wrap_parsed_args(parsed_args): diff --git a/cmake/Tools/Platform/Android/unit_test_android_deployment.py b/cmake/Tools/Platform/Android/unit_test_android_deployment.py index 011033649a..5ee168ca30 100755 --- a/cmake/Tools/Platform/Android/unit_test_android_deployment.py +++ b/cmake/Tools/Platform/Android/unit_test_android_deployment.py @@ -21,7 +21,7 @@ from cmake.Tools.Platform.Android import android_deployment TEST_GAME_NAME = "Foo" TEST_DEV_ROOT = pathlib.Path("Foo") TEST_ASSET_MODE = 'LOOSE' -TEST_ASSET_TYPE = 'es3' +TEST_ASSET_TYPE = 'android' TEST_ANDROID_SDK_PATH = pathlib.Path('c:\\AndroidSDK') TEST_BUILD_DIR = 'android_gradle_test' TEST_DEVICE_ID = '9A201FFAZ000ER' @@ -661,10 +661,10 @@ def test_execute_success(tmpdir, test_config, test_package_name, test_device_sto @pytest.mark.parametrize( "test_game_name, test_config, test_package_name, test_device_storage_path, test_asset_type", [ - pytest.param('game1','profile', 'com.amazon.lumberyard.foo', '/data/fool_storage', 'es3'), - pytest.param('game1','debug', 'com.amazon.lumberyard.foo', '/data/fool_storage', 'es3'), - pytest.param('game2','profile', 'com.amazon.lumberyard.bar', '/data/fool_storage', 'es3'), - pytest.param('game2','debug', 'com.amazon.lumberyard.bar', '/data/fool_storage', 'es3'), + pytest.param('game1','profile', 'com.amazon.lumberyard.foo', '/data/fool_storage', 'android'), + pytest.param('game1','debug', 'com.amazon.lumberyard.foo', '/data/fool_storage', 'android'), + pytest.param('game2','profile', 'com.amazon.lumberyard.bar', '/data/fool_storage', 'android'), + pytest.param('game2','debug', 'com.amazon.lumberyard.bar', '/data/fool_storage', 'android'), pytest.param('game3','profile', 'com.amazon.lumberyard.foo', '/data/fool_storage2', 'pc'), pytest.param('game3','debug', 'com.amazon.lumberyard.foo', '/data/fool_storage2', 'pc'), pytest.param('game4','profile', 'com.amazon.lumberyard.bar', '/data/fool_storage2', 'pc'), diff --git a/scripts/build/Platform/Android/build_config.json b/scripts/build/Platform/Android/build_config.json index d0fce80964..fe5e223612 100644 --- a/scripts/build/Platform/Android/build_config.json +++ b/scripts/build/Platform/Android/build_config.json @@ -99,7 +99,7 @@ "CMAKE_NATIVE_BUILD_ARGS": "/m /nologo", "ASSET_PROCESSOR_BINARY": "bin\\profile\\AssetProcessorBatch.exe", "ASSET_PROCESSOR_OPTIONS": "/zeroAnalysisMode --regset=\"/Amazon/AssetProcessor/Settings/Exclude Android/pattern=.*/DiffuseGlobalIllumination/.*precompiledshader\"", - "ASSET_PROCESSOR_PLATFORMS":"es3" + "ASSET_PROCESSOR_PLATFORMS":"android" } }, "release": { diff --git a/scripts/build/Platform/Mac/build_config.json b/scripts/build/Platform/Mac/build_config.json index f312279fe6..bcaffce880 100644 --- a/scripts/build/Platform/Mac/build_config.json +++ b/scripts/build/Platform/Mac/build_config.json @@ -86,7 +86,7 @@ "CMAKE_TARGET": "AssetProcessorBatch", "ASSET_PROCESSOR_BINARY": "bin/profile/AssetProcessorBatch", "ASSET_PROCESSOR_OPTIONS": "/zeroAnalysisMode", - "ASSET_PROCESSOR_PLATFORMS": "osx_gl" + "ASSET_PROCESSOR_PLATFORMS": "mac" } }, "periodic_test_profile": { diff --git a/scripts/build/lambda/trigger_first_build.py b/scripts/build/lambda/trigger_first_build.py index 6ebe09f7ee..3b4587e737 100755 --- a/scripts/build/lambda/trigger_first_build.py +++ b/scripts/build/lambda/trigger_first_build.py @@ -53,7 +53,7 @@ def lambda_handler(event, context): backoff = 30 status_list = [404] # Retry if the branch doesn't exist yet and provide time for Jenkins to discover it. method_list = ['POST'] - retry_config = Retry(total=retries, backoff_factor=backoff, status_forcelist=status_list, method_whitelist=method_list) + retry_config = Retry(total=retries, backoff_factor=backoff, status_forcelist=status_list, allowed_methods=method_list) session = requests.Session() session.mount('https://', HTTPAdapter(max_retries=retry_config)) diff --git a/scripts/bundler/gen_shaders.py b/scripts/bundler/gen_shaders.py index 46857179b1..bfb60287af 100644 --- a/scripts/bundler/gen_shaders.py +++ b/scripts/bundler/gen_shaders.py @@ -163,11 +163,11 @@ def add_shaders_types(): shaders.append(gl4) gles3 = _ShaderType('GLES3', 'GLSL_HLSLcc') - gles3.add_configuration('Android', 'es3') + gles3.add_configuration('Android', 'android') shaders.append(gles3) metal = _ShaderType('METAL', 'METAL_LLVM_DXC') - metal.add_configuration('Mac', 'osx_gl') + metal.add_configuration('Mac', 'mac') metal.add_configuration('iOS', 'ios') shaders.append(metal) diff --git a/system_android_es3.cfg b/system_android_android.cfg similarity index 93% rename from system_android_es3.cfg rename to system_android_android.cfg index 46ab50f558..d5bfddeb73 100644 --- a/system_android_es3.cfg +++ b/system_android_android.cfg @@ -1,4 +1,4 @@ --- config file used when the android platform is running off 'es3' assets. +-- config file used when the android platform is running off 'android' assets. sys_float_exceptions=0 log_IncludeTime=1 sys_PakLogInvalidFileAccess=1 diff --git a/system_mac_osx_gl.cfg b/system_mac_mac.cfg similarity index 100% rename from system_mac_osx_gl.cfg rename to system_mac_mac.cfg