diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py
index 34b2217916..6f3113d771 100644
--- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py
+++ b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py
@@ -14,6 +14,7 @@ from datetime import datetime
import ly_test_tools.log.log_monitor
from AWS.common import constants
+from AWS.common.resource_mappings import AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY
from .aws_metrics_custom_thread import AWSMetricsThread
# fixture imports
@@ -200,6 +201,59 @@ class TestAWSMetricsWindows(object):
for thread in operational_threads:
thread.join()
+ @pytest.mark.parametrize('level', ['AWS/Metrics'])
+ def test_realtime_and_batch_analytics_no_global_accountid(self,
+ level: str,
+ launcher: pytest.fixture,
+ asset_processor: pytest.fixture,
+ workspace: pytest.fixture,
+ aws_utils: pytest.fixture,
+ resource_mappings: pytest.fixture,
+ aws_metrics_utils: pytest.fixture):
+ """
+ Verify that the metrics events are sent to CloudWatch and S3 for analytics.
+ """
+ # Remove top-level account ID from resource mappings
+ resource_mappings.clear_select_keys([AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY])
+ # Start Kinesis analytics application on a separate thread to avoid blocking the test.
+ kinesis_analytics_application_thread = AWSMetricsThread(target=update_kinesis_analytics_application_status,
+ args=(aws_metrics_utils, resource_mappings, True))
+ kinesis_analytics_application_thread.start()
+
+ log_monitor = setup(launcher, asset_processor)
+
+ # Kinesis analytics application needs to be in the running state before we start the game launcher.
+ kinesis_analytics_application_thread.join()
+ launcher.args = ['+LoadLevel', level]
+ launcher.args.extend(['-rhi=null'])
+ start_time = datetime.utcnow()
+ with launcher.start(launch_ap=False):
+ monitor_metrics_submission(log_monitor)
+
+ # Verify that real-time analytics metrics are delivered to CloudWatch.
+ aws_metrics_utils.verify_cloud_watch_delivery(
+ AWS_METRICS_FEATURE_NAME,
+ 'TotalLogins',
+ [],
+ start_time)
+ logger.info('Real-time metrics are sent to CloudWatch.')
+
+ # Run time-consuming operations on separate threads to avoid blocking the test.
+ operational_threads = list()
+ operational_threads.append(
+ AWSMetricsThread(target=query_metrics_from_s3,
+ args=(aws_metrics_utils, resource_mappings)))
+ operational_threads.append(
+ AWSMetricsThread(target=verify_operational_metrics,
+ args=(aws_metrics_utils, resource_mappings, start_time)))
+ operational_threads.append(
+ AWSMetricsThread(target=update_kinesis_analytics_application_status,
+ args=(aws_metrics_utils, resource_mappings, False)))
+ for thread in operational_threads:
+ thread.start()
+ for thread in operational_threads:
+ thread.join()
+
@pytest.mark.parametrize('level', ['AWS/Metrics'])
def test_unauthorized_user_request_rejected(self,
level: str,
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/core/test_aws_resource_interaction.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/core/test_aws_resource_interaction.py
index 949186ad50..59c517fd1c 100644
--- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/core/test_aws_resource_interaction.py
+++ b/AutomatedTesting/Gem/PythonTests/AWS/Windows/core/test_aws_resource_interaction.py
@@ -18,6 +18,7 @@ import ly_test_tools.environment.process_utils as process_utils
import ly_test_tools.o3de.asset_processor_utils as asset_processor_utils
from AWS.common import constants
+from AWS.common.resource_mappings import AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY
# fixture imports
from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor
@@ -141,3 +142,51 @@ class TestAWSCoreAWSResourceInteraction(object):
'The expected file wasn\'t successfully downloaded.'
# clean up the file directories.
shutil.rmtree(s3_download_dir)
+
+ @pytest.mark.parametrize('expected_lines', [
+ ['(Script) - [S3] Head object request is done',
+ '(Script) - [S3] Head object success: Object example.txt is found.',
+ '(Script) - [S3] Get object success: Object example.txt is downloaded.',
+ '(Script) - [Lambda] Completed Invoke',
+ '(Script) - [Lambda] Invoke success: {"statusCode": 200, "body": {}}',
+ '(Script) - [DynamoDB] Results finished']])
+ @pytest.mark.parametrize('unexpected_lines', [
+ ['(Script) - [S3] Head object error: No response body.',
+ '(Script) - [S3] Get object error: Request validation failed, output file directory doesn\'t exist.',
+ '(Script) - Request validation failed, output file miss full path.',
+ '(Script) - ']])
+ def test_scripting_behavior_no_global_accountid(self,
+ level: str,
+ launcher: pytest.fixture,
+ workspace: pytest.fixture,
+ asset_processor: pytest.fixture,
+ resource_mappings: pytest.fixture,
+ aws_utils: pytest.fixture,
+ expected_lines: typing.List[str],
+ unexpected_lines: typing.List[str]):
+ """
+ Setup: Updates resource mapping file using existing CloudFormation stacks.
+ Tests: Interact with AWS S3, DynamoDB and Lambda services.
+ Verification: Script canvas nodes can communicate with AWS services successfully.
+ """
+
+ resource_mappings.clear_select_keys([AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY])
+ log_monitor, s3_download_dir = setup(launcher, asset_processor)
+ write_test_data_to_dynamodb_table(resource_mappings, aws_utils)
+
+ launcher.args = ['+LoadLevel', level]
+ launcher.args.extend(['-rhi=null'])
+
+ with launcher.start(launch_ap=False):
+ result = log_monitor.monitor_log_for_lines(
+ expected_lines=expected_lines,
+ unexpected_lines=unexpected_lines,
+ halt_on_unexpected=True
+ )
+
+ assert result, "Expected lines weren't found."
+
+ assert os.path.exists(os.path.join(s3_download_dir, 'output.txt')), \
+ 'The expected file wasn\'t successfully downloaded.'
+ # clean up the file directories.
+ shutil.rmtree(s3_download_dir)
diff --git a/AutomatedTesting/Gem/PythonTests/AWS/common/resource_mappings.py b/AutomatedTesting/Gem/PythonTests/AWS/common/resource_mappings.py
index 5f01ecdbf8..988d5bf1fc 100644
--- a/AutomatedTesting/Gem/PythonTests/AWS/common/resource_mappings.py
+++ b/AutomatedTesting/Gem/PythonTests/AWS/common/resource_mappings.py
@@ -102,3 +102,17 @@ class ResourceMappings:
def get_resource_name_id(self, resource_key: str):
return self._resource_mappings[AWS_RESOURCE_MAPPINGS_KEY][resource_key]['Name/ID']
+
+ def clear_select_keys(self, resource_keys=None) -> None:
+ """
+ Clears values from select resource mapping keys.
+ :param resource_keys: list of keys to clear out
+ """
+ with open(self._resource_mapping_file_path) as file_content:
+ resource_mappings = json.load(file_content)
+
+ for key in resource_keys:
+ resource_mappings[key] = ''
+
+ with open(self._resource_mapping_file_path, 'w') as file_content:
+ json.dump(resource_mappings, file_content, indent=4)
\ No newline at end of file
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 ff362c732c..9281d5947e 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
@@ -158,7 +158,7 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
else:
cmd.append(f"--{key}")
if append_defaults:
- cmd.append(f"--project-path={workspace.project}")
+ cmd.append(f"--project-path={workspace.paths.project()}")
return cmd
# ******
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 7f85e5e317..f5e5642573 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
@@ -88,214 +88,6 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
bundler_batch_helper.call_bundles(help="")
bundler_batch_helper.call_bundleSeed(help="")
- @pytest.mark.BAT
- @pytest.mark.assetpipeline
- @pytest.mark.test_case_id("C16877175")
- @pytest.mark.skip("'animations/animationeditorfiles/sample1.animgraph' missing, needs investigation")
- def test_WindowsAndMac_CreateAssetList_DependenciesCorrect(self, workspace, bundler_batch_helper):
- r"""
- Tests that an asset list created maps dependencies correctly.
- testdependencieslevel\level.pak and lists of known dependencies are used for validation
-
- Test Steps:
- 1. Create an asset list from the level.pak
- 2. Create Lists of expected assets in the level.pak
- 3. Add lists of expected assets to a single list
- 4. Compare list of expected assets to actual assets
- """
- helper = bundler_batch_helper
-
- # Create the asset list file
- helper.call_assetLists(
- addSeed=r"levels\testdependencieslevel\level.pak",
- assetListFile=helper['asset_info_file_request']
- )
-
- assert os.path.isfile(helper["asset_info_file_result"])
-
- # Lists of known relative locations of assets
- default_level_assets = [
- "engineassets/texturemsg/defaultnouvs.dds",
- "engineassets/texturemsg/defaultnouvs.dds.1",
- "engineassets/texturemsg/defaultnouvs.dds.2",
- "engineassets/texturemsg/defaultnouvs.dds.3",
- "engineassets/texturemsg/defaultnouvs.dds.4",
- "engineassets/texturemsg/defaultnouvs.dds.5",
- "engineassets/texturemsg/defaultnouvs.dds.6",
- "engineassets/texturemsg/defaultnouvs.dds.7",
- "engineassets/texturemsg/defaultnouvs_ddn.dds",
- "engineassets/texturemsg/defaultnouvs_ddn.dds.1",
- "engineassets/texturemsg/defaultnouvs_ddn.dds.2",
- "engineassets/texturemsg/defaultnouvs_ddn.dds.3",
- "engineassets/texturemsg/defaultnouvs_ddn.dds.4",
- "engineassets/texturemsg/defaultnouvs_ddn.dds.5",
- "engineassets/texturemsg/defaultnouvs_spec.dds",
- "engineassets/texturemsg/defaultnouvs_spec.dds.1",
- "engineassets/texturemsg/defaultnouvs_spec.dds.2",
- "engineassets/texturemsg/defaultnouvs_spec.dds.3",
- "engineassets/texturemsg/defaultnouvs_spec.dds.4",
- "engineassets/texturemsg/defaultnouvs_spec.dds.5",
- "engineassets/textures/defaults/16_grey.dds",
- "engineassets/textures/cubemap/default_level_cubemap.dds",
- "engineassets/textures/cubemap/default_level_cubemap.dds.1",
- "engineassets/textures/cubemap/default_level_cubemap.dds.2",
- "engineassets/textures/cubemap/default_level_cubemap.dds.3",
- "engineassets/textures/cubemap/default_level_cubemap.dds.4",
- "engineassets/textures/cubemap/default_level_cubemap_diff.dds",
- "engineassets/materials/water/ocean_default.mtl",
- "engineassets/textures/defaults/spot_default.dds",
- "engineassets/textures/defaults/spot_default.dds.1",
- "engineassets/textures/defaults/spot_default.dds.2",
- "engineassets/textures/defaults/spot_default.dds.3",
- "engineassets/textures/defaults/spot_default.dds.4",
- "engineassets/textures/defaults/spot_default.dds.5",
- "materials/material_terrain_default.mtl",
- "textures/skys/night/half_moon.dds",
- "textures/skys/night/half_moon.dds.1",
- "textures/skys/night/half_moon.dds.2",
- "textures/skys/night/half_moon.dds.3",
- "textures/skys/night/half_moon.dds.4",
- "textures/skys/night/half_moon.dds.5",
- "textures/skys/night/half_moon.dds.6",
- "engineassets/materials/sky/sky.mtl",
- "levels/testdependencieslevel/level.pak",
- "levels/testdependencieslevel/terrain/cover.ctc",
- "levels/testdependencieslevel/terraintexture.pak",
- ]
-
- sequence_material_cube_assets = [
- "textures/test_texture_sequence/test_texture_sequence000.dds",
- "textures/test_texture_sequence/test_texture_sequence001.dds",
- "textures/test_texture_sequence/test_texture_sequence002.dds",
- "textures/test_texture_sequence/test_texture_sequence003.dds",
- "textures/test_texture_sequence/test_texture_sequence004.dds",
- "textures/test_texture_sequence/test_texture_sequence005.dds",
- "objects/_primitives/_box_1x1.cgf",
- "materials/test_texture_sequence.mtl",
- "objects/_primitives/_box_1x1.mtl",
- "textures/_primitives/middle_gray_checker.dds",
- "textures/_primitives/middle_gray_checker.dds.1",
- "textures/_primitives/middle_gray_checker.dds.2",
- "textures/_primitives/middle_gray_checker.dds.3",
- "textures/_primitives/middle_gray_checker.dds.4",
- "textures/_primitives/middle_gray_checker.dds.5",
- "textures/_primitives/middle_gray_checker_ddn.dds",
- "textures/_primitives/middle_gray_checker_ddn.dds.1",
- "textures/_primitives/middle_gray_checker_ddn.dds.2",
- "textures/_primitives/middle_gray_checker_ddn.dds.3",
- "textures/_primitives/middle_gray_checker_ddn.dds.4",
- "textures/_primitives/middle_gray_checker_ddn.dds.5",
- "textures/_primitives/middle_gray_checker_spec.dds",
- "textures/_primitives/middle_gray_checker_spec.dds.1",
- "textures/_primitives/middle_gray_checker_spec.dds.2",
- "textures/_primitives/middle_gray_checker_spec.dds.3",
- "textures/_primitives/middle_gray_checker_spec.dds.4",
- "textures/_primitives/middle_gray_checker_spec.dds.5",
- ]
-
- character_with_simplified_material_assets = [
- "objects/characters/jack/jack.actor",
- "objects/characters/jack/jack.mtl",
- "objects/characters/jack/textures/jack_diff.dds",
- "objects/characters/jack/textures/jack_diff.dds.1",
- "objects/characters/jack/textures/jack_diff.dds.2",
- "objects/characters/jack/textures/jack_diff.dds.3",
- "objects/characters/jack/textures/jack_diff.dds.4",
- "objects/characters/jack/textures/jack_diff.dds.5",
- "objects/characters/jack/textures/jack_diff.dds.6",
- "objects/characters/jack/textures/jack_diff.dds.7",
- "objects/characters/jack/textures/jack_spec.dds",
- "objects/characters/jack/textures/jack_spec.dds.1",
- "objects/characters/jack/textures/jack_spec.dds.2",
- "objects/characters/jack/textures/jack_spec.dds.3",
- "objects/characters/jack/textures/jack_spec.dds.4",
- "objects/characters/jack/textures/jack_spec.dds.5",
- "objects/characters/jack/textures/jack_spec.dds.6",
- "objects/characters/jack/textures/jack_spec.dds.7",
- "objects/default/editorprimitive.mtl",
- "engineassets/textures/grey.dds",
- "animations/animationeditorfiles/sample0.animgraph",
- "animations/motions/jack_death_fall_back_zup.motion",
- "animations/animationeditorfiles/sample1.animgraph",
- "animations/animationeditorfiles/sample0.motionset",
- "animations/motions/rin_jump.motion",
- "animations/animationeditorfiles/sample1.motionset",
- "animations/motions/rin_idle.motion",
- "animations/motions/jack_idle_aim_zup.motion",
- ]
-
- spawner_assets = [
- "slices/sphere.dynamicslice",
- "objects/default/primitive_sphere.cgf",
- "test1.luac",
- "test2.luac",
- ]
-
- ui_canvas_assets = [
- "fonts/vera.ttf",
- "fonts/vera.font",
- "scriptcanvas/mainmenu.scriptcanvas_compiled",
- "fonts/vera.fontfamily",
- "ui/canvas/start.uicanvas",
- "fonts/vera-italic.font",
- "ui/textureatlas/sample.texatlasidx",
- "fonts/vera-bold-italic.ttf",
- "fonts/vera-bold.font",
- "ui/textures/prefab/button_normal.dds",
- "ui/textures/prefab/button_normal.sprite",
- "fonts/vera-italic.ttf",
- "ui/textureatlas/sample.dds",
- "fonts/vera-bold-italic.font",
- "fonts/vera-bold.ttf",
- "ui/textures/prefab/button_disabled.dds",
- "ui/textures/prefab/button_disabled.sprite",
- ]
-
- wwise_and_atl_assets = [
- "libs/gameaudio/wwise/levels/testdependencieslevel/test_dependencies_level.xml",
- "sounds/wwise/test_bank3.bnk",
- "sounds/wwise/test_bank4.bnk",
- "sounds/wwise/test_bank5.bnk",
- "sounds/wwise/test_bank1.bnk",
- "sounds/wwise/init.bnk",
- "sounds/wwise/499820003.wem",
- "sounds/wwise/196049145.wem",
- ]
-
- particle_library_assets = [
- "libs/particles/milestone2particles.xml",
- "textures/milestone2/particles/fx_launchermuzzlering_01.dds",
- "textures/milestone2/particles/fx_launchermuzzlering_01.dds.1",
- "textures/milestone2/particles/fx_launchermuzzlering_01.dds.2",
- "textures/milestone2/particles/fx_launchermuzzlering_01.dds.3",
- "textures/milestone2/particles/fx_launchermuzzlering_01.dds.4",
- "textures/milestone2/particles/fx_launchermuzzlering_01.dds.5",
- "textures/milestone2/particles/fx_sparkstreak_01.dds",
- "textures/milestone2/particles/fx_launchermuzzlefront_01.dds",
- "textures/milestone2/particles/fx_launchermuzzlefront_01.dds.1",
- "textures/milestone2/particles/fx_launchermuzzlefront_01.dds.2",
- "textures/milestone2/particles/fx_launchermuzzlefront_01.dds.3",
- "textures/milestone2/particles/fx_launchermuzzlefront_01.dds.4",
- "textures/milestone2/particles/fx_launchermuzzlefront_01.dds.5",
- ]
-
- lens_flares_library_assets = ["libs/flares/flares.xml", "textures/lights/flare01.dds"]
-
- expected_assets_list = default_level_assets
- expected_assets_list.extend(sequence_material_cube_assets)
- expected_assets_list.extend(character_with_simplified_material_assets)
- expected_assets_list.extend(spawner_assets)
- expected_assets_list.extend(ui_canvas_assets)
- expected_assets_list.extend(wwise_and_atl_assets)
- expected_assets_list.extend(particle_library_assets)
- expected_assets_list.extend(lens_flares_library_assets) # All expected assets
-
- # Get actual calculated dependencies from the asset list created
- actual_assets_list = []
- for rel_path in helper.get_asset_relative_paths(helper["asset_info_file_result"]):
- actual_assets_list.append(rel_path)
-
- assert sorted(actual_assets_list) == sorted(expected_assets_list)
@pytest.mark.BAT
@pytest.mark.assetpipeline
@@ -310,9 +102,9 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
3. Read and store contents of asset list into memory
4. Attempt to create a new asset list in without using --allowOverwrites
5. Verify that Asset Bundler returns false
- 6. Verify that file contents of the orignally created asset list did not change from what was stored in memory
+ 6. Verify that file contents of the originally created asset list did not change from what was stored in memory
7. Attempt to create a new asset list without debug while allowing overwrites
- 8. Verify that file contents of the orignally created asset list changed from what was stored in memory
+ 8. Verify that file contents of the originally created asset list changed from what was stored in memory
"""
helper = bundler_batch_helper
seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed") # Engine seed list
@@ -919,7 +711,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
# Extra arguments for pattern comparison
cmd.extend([f"--filePatternType={pattern_type}", f"--filePattern={pattern}"])
if workspace.project:
- cmd.append(f'--project-path={project_name}')
+ cmd.append(f'--project-path={workspace.paths.project()}')
return cmd
# End generate_compare_command()
@@ -960,7 +752,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
output_mac_asset_list = helper.platform_file_name(last_output_arg, platform)
# Build execution command
- cmd = generate_compare_command(platform_arg, workspace.project)
+ cmd = generate_compare_command(platform_arg, workspace.paths.project())
# Execute command
subprocess.check_call(cmd)
@@ -995,7 +787,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
f"--comparisonRulesFile={rule_file}",
f"--comparisonType={args[1]}",
r"--addComparison",
- f"--project-path={workspace.project}",
+ f"--project-path={workspace.paths.project()}",
]
if args[1] == "4":
# If pattern comparison, append a few extra arguments
@@ -1117,7 +909,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
"--addDefaultSeedListFiles",
"--platform=pc",
"--print",
- f"--project-path={workspace.project}"
+ f"--project-path={workspace.paths.project()}"
],
universal_newlines=True,
)
@@ -1189,7 +981,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
# Make sure file gets deleted on teardown
request.addfinalizer(lambda: fs.delete([bundle_result_path], True, False))
- bundles_folder = os.path.join(workspace.paths.engine_root(), workspace.project, "Bundles")
+ bundles_folder = os.path.join(workspace.paths.project(), "Bundles")
level_pak = r"levels\testdependencieslevel\level.pak"
bundle_request_path = os.path.join(bundles_folder, "bundle.pak")
bundle_result_path = os.path.join(bundles_folder,
@@ -1243,23 +1035,64 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
2. Verify file was created
3. Verify that only the expected assets are present in the created asset list
"""
- expected_assets = [
+ expected_assets = sorted([
"ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas",
- "ui/textures/prefab/button_normal.sprite"
- ]
+ "ui/textures/prefab/button_disabled.tif.streamingimage",
+ "ui/textures/prefab/tooltip_sliced.tif.streamingimage",
+ "ui/textures/prefab/button_normal.tif.streamingimage"
+ ])
+ # Printing these lists out can save a step in debugging if this test fails on Jenkins.
+ logger.info(f"expected_assets: {expected_assets}")
+
+ skip_assets = sorted([
+ "ui/scripts/lyshineexamples/animation/multiplesequences.luac",
+ "ui/scripts/lyshineexamples/unloadthiscanvasbutton.luac",
+ "fonts/vera.fontfamily",
+ "fonts/vera-italic.font",
+ "fonts/vera.font",
+ "fonts/vera-bold.font",
+ "fonts/vera-bold-italic.font",
+ "fonts/vera-italic.ttf",
+ "fonts/vera.ttf",
+ "fonts/vera-bold.ttf",
+ "fonts/vera-bold-italic.ttf"
+ ])
+ logger.info(f"skip_assets: {skip_assets}")
+
+ expected_and_skip_assets = sorted(expected_assets + skip_assets)
+ # Printing both together to make it quick to compare the results in the logs for a test failure on Jenkins
+ logger.info(f"expected_and_skip_assets: {expected_and_skip_assets}")
+
+ # First, generate an asset info file without skipping, to get a list that can be used as a baseline to verify
+ # the files were actually skipped, and not just missing.
+ bundler_batch_helper.call_assetLists(
+ assetListFile=bundler_batch_helper['asset_info_file_request'],
+ addSeed="ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas"
+ )
+ assert os.path.isfile(bundler_batch_helper["asset_info_file_result"])
+ assets_in_no_skip_list = []
+ for rel_path in bundler_batch_helper.get_asset_relative_paths(bundler_batch_helper["asset_info_file_result"]):
+ assets_in_no_skip_list.append(rel_path)
+ assets_in_no_skip_list = sorted(assets_in_no_skip_list)
+ logger.info(f"assets_in_no_skip_list: {assets_in_no_skip_list}")
+ assert assets_in_no_skip_list == expected_and_skip_assets
+
+ # Now generate an asset info file using the skip command, and verify the skip files are not in the list.
bundler_batch_helper.call_assetLists(
assetListFile=bundler_batch_helper['asset_info_file_request'],
addSeed="ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas",
- skip="ui/textures/prefab/button_disabled.sprite,ui/scripts/lyshineexamples/animation/multiplesequences.luac,"
- "ui/textures/prefab/tooltip_sliced.sprite,ui/scripts/lyshineexamples/unloadthiscanvasbutton.luac,fonts/vera.fontfamily,fonts/vera-italic.font,"
- "fonts/vera.font,fonts/vera-bold.font,fonts/vera-bold-italic.font,fonts/vera-italic.ttf,fonts/vera.ttf,fonts/vera-bold.ttf,fonts/vera-bold-italic.ttf"
+ allowOverwrites="",
+ skip=','.join(skip_assets)
)
+
assert os.path.isfile(bundler_batch_helper["asset_info_file_result"])
assets_in_list = []
for rel_path in bundler_batch_helper.get_asset_relative_paths(bundler_batch_helper["asset_info_file_result"]):
assets_in_list.append(rel_path)
+ assets_in_list = sorted(assets_in_list)
+ logger.info(f"assets_in_list: {assets_in_list}")
+ assert assets_in_list == expected_assets
- assert sorted(assets_in_list) == sorted(expected_assets)
@pytest.mark.BAT
@pytest.mark.assetpipeline
diff --git a/Code/Editor/AboutDialog.ui b/Code/Editor/AboutDialog.ui
index a6c5bb5d52..a36d65e35b 100644
--- a/Code/Editor/AboutDialog.ui
+++ b/Code/Editor/AboutDialog.ui
@@ -125,7 +125,7 @@
- General Availability
+ Stable 21.11
Qt::AutoText
diff --git a/Code/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp b/Code/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp
index 1c2be16a3d..6fc10e379a 100644
--- a/Code/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp
+++ b/Code/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp
@@ -199,41 +199,6 @@ namespace AzAssetBrowserRequestHandlerPrivate
}
}
}
-
- // Helper utility - determines if the thing being dragged is a FBX from the scene import pipeline
- // This is important to differentiate.
- // when someone drags a MTL file directly into the viewport, even from a FBX, we want to spawn it as a decal
- // but when someone drags a FBX that contains MTL files, we want only to spawn the meshes.
- // so we have to specifically differentiate here between the mimeData type that contains the source as the root
- // (dragging the fbx file itself)
- // and one which contains the actual product at its root.
-
- bool IsDragOfFBX(const QMimeData* mimeData)
- {
- AZStd::vector entries;
- if (!AssetBrowserEntry::FromMimeData(mimeData, entries))
- {
- // if mimedata does not even contain entries, no point in proceeding.
- return false;
- }
-
- for (auto entry : entries)
- {
- if (entry->GetEntryType() != AssetBrowserEntry::AssetEntryType::Source)
- {
- continue;
- }
- // this is a source file. Is it the filetype we're looking for?
- if (SourceAssetBrowserEntry* source = azrtti_cast(entry))
- {
- if (AzFramework::StringFunc::Equal(source->GetExtension().c_str(), ".fbx", false))
- {
- return true;
- }
- }
- }
- return false;
- }
}
AzAssetBrowserRequestHandler::AzAssetBrowserRequestHandler()
diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp
index 4008710786..b77c6c4b3a 100644
--- a/Code/Editor/CryEdit.cpp
+++ b/Code/Editor/CryEdit.cpp
@@ -4181,6 +4181,8 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
"\nThis could be because of incorrectly configured components, or missing required gems."
"\nSee other errors for more details.");
+ AzToolsFramework::EditorEventsBus::Broadcast(&AzToolsFramework::EditorEvents::NotifyEditorInitialized);
+
if (didCryEditStart)
{
app->EnableOnIdle();
diff --git a/Code/Editor/Include/IEditorMaterialManager.h b/Code/Editor/Include/IEditorMaterialManager.h
index d76ec32829..6f71c5ddd1 100644
--- a/Code/Editor/Include/IEditorMaterialManager.h
+++ b/Code/Editor/Include/IEditorMaterialManager.h
@@ -9,10 +9,6 @@
#define CRYINCLUDE_EDITOR_MATERIAL_IEDITORMATERIALMANAGER_H
#pragma once
-#define MATERIAL_FILE_EXT ".mtl"
-#define DCC_MATERIAL_FILE_EXT ".dccmtl"
-#define MATERIALS_PATH "materials/"
-
#include
#include
diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/AssetCatalogModel.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/AssetCatalogModel.cpp
index d0091f968e..2073d0dd5a 100644
--- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/AssetCatalogModel.cpp
+++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/AssetCatalogModel.cpp
@@ -18,7 +18,6 @@
#include
#include
-#include
#include
#include
@@ -136,14 +135,6 @@ AssetCatalogModel::AssetCatalogModel(QObject* parent)
}
}
- // Special cases for SimpleAssets. If these get full-fledged AssetData types, these cases can be removed.
- QString textureExtensions = LmbrCentral::TextureAsset::GetFileFilter();
- m_extensionToAssetType.insert(AZStd::make_pair(textureExtensions.replace("*", "").replace(" ", "").toStdString().c_str(), AZStd::vector { AZ::AzTypeInfo::Uuid() }));
- QString materialExtensions = LmbrCentral::MaterialAsset::GetFileFilter();
- m_extensionToAssetType.insert(AZStd::make_pair(materialExtensions.replace("*", "").replace(" ", "").toStdString().c_str(), AZStd::vector { AZ::AzTypeInfo::Uuid() }));
- QString dccMaterialExtensions = LmbrCentral::DccMaterialAsset::GetFileFilter();
- m_extensionToAssetType.insert(AZStd::make_pair(dccMaterialExtensions.replace("*", "").replace(" ", "").toStdString().c_str(), AZStd::vector { AZ::AzTypeInfo::Uuid() }));
-
AZ::SerializeContext* serializeContext = nullptr;
EBUS_EVENT_RESULT(serializeContext, AZ::ComponentApplicationBus, GetSerializeContext);
AZ_Assert(serializeContext, "Failed to acquire application serialize context.");
diff --git a/Code/Editor/StartupLogoDialog.ui b/Code/Editor/StartupLogoDialog.ui
index c0b8115cb0..c2cbfcfd69 100644
--- a/Code/Editor/StartupLogoDialog.ui
+++ b/Code/Editor/StartupLogoDialog.ui
@@ -103,7 +103,7 @@
-
- General Availability
+ Stable 21.11
diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp
index 06bb0b0cac..b03e1affdc 100644
--- a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp
+++ b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp
@@ -1677,9 +1677,13 @@ namespace AZ
// they will trigger a ReleaseAsset call sometime after the AssetManager has begun to shut down, which can lead to
// race conditions.
+ // Make sure the streamer request is removed first before the asset is released
+ // If the asset is released first it could lead to a race condition where another thread starts loading the asset
+ // again and attempts to add a new streamer request with the same ID before the old one has been removed, causing
+ // that load request to fail
+ RemoveActiveStreamerRequest(assetId);
weakAsset = {};
loadingAsset.Reset();
- RemoveActiveStreamerRequest(assetId);
};
auto&& [deadline, priority] = GetEffectiveDeadlineAndPriority(*handler, asset.GetType(), loadParams);
diff --git a/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp b/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp
index 6f5ccc93e4..2307a9372c 100644
--- a/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp
+++ b/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp
@@ -56,11 +56,12 @@ namespace AZ
int numberOfWorkerThreads = m_numberOfWorkerThreads;
if (numberOfWorkerThreads <= 0) // spawn default number of threads
{
+ #if (AZ_TRAIT_THREAD_NUM_JOB_MANAGER_WORKER_THREADS)
+ numberOfWorkerThreads = AZ_TRAIT_THREAD_NUM_JOB_MANAGER_WORKER_THREADS;
+ #else
uint32_t scaledHardwareThreads = Threading::CalcNumWorkerThreads(cl_jobThreadsConcurrencyRatio, cl_jobThreadsMinNumber, cl_jobThreadsNumReserved);
numberOfWorkerThreads = AZ::GetMin(static_cast(desc.m_workerThreads.capacity()), scaledHardwareThreads);
- #if (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS)
- numberOfWorkerThreads = AZ::GetMin(numberOfWorkerThreads, AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS);
- #endif // (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS)
+ #endif // (AZ_TRAIT_THREAD_NUM_JOB_MANAGER_WORKER_THREADS)
}
threadDesc.m_cpuId = AFFINITY_MASK_USERTHREADS;
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp
index da02e70181..0ba44e4e61 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp
@@ -104,6 +104,8 @@ namespace AZ
->HandlesType();
jsonContext->Serializer()
->HandlesType();
+ jsonContext->Serializer()
+ ->HandlesType();
MathReflect(jsonContext);
}
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.cpp
index 2392ff435f..ad1839f974 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.cpp
@@ -15,6 +15,7 @@ namespace AZ
AZ_CLASS_ALLOCATOR_IMPL(JsonAnySerializer, SystemAllocator, 0);
AZ_CLASS_ALLOCATOR_IMPL(JsonVariantSerializer, SystemAllocator, 0);
AZ_CLASS_ALLOCATOR_IMPL(JsonOptionalSerializer, SystemAllocator, 0);
+ AZ_CLASS_ALLOCATOR_IMPL(JsonBitsetSerializer, SystemAllocator, 0);
JsonSerializationResult::Result JsonUnsupportedTypesSerializer::Load(void*, const Uuid&, const rapidjson::Value&,
JsonDeserializerContext& context)
@@ -49,4 +50,10 @@ namespace AZ
return "The Json Serialization doesn't support AZStd::optional by design. No JSON format has yet been found that wasn't deemed too "
"complex or overly verbose.";
}
+
+ AZStd::string_view JsonBitsetSerializer::GetMessage() const
+ {
+ return "The Json Serialization doesn't support AZStd::bitset by design. No JSON format has yet been found that is content creator "
+ "friendly i.e., easy to comprehend the intent.";
+ }
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.h
index d913289d3d..fdcac4c761 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/UnsupportedTypesSerializer.h
@@ -65,4 +65,14 @@ namespace AZ
protected:
AZStd::string_view GetMessage() const override;
};
+
+ class JsonBitsetSerializer : public JsonUnsupportedTypesSerializer
+ {
+ public:
+ AZ_RTTI(JsonBitsetSerializer, "{10CE969D-D69E-4B3F-8593-069736F8F705}", JsonUnsupportedTypesSerializer);
+ AZ_CLASS_ALLOCATOR_DECL;
+
+ protected:
+ AZStd::string_view GetMessage() const override;
+ };
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp
index 56b56e96a1..1cacef7ff3 100644
--- a/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp
+++ b/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp
@@ -30,8 +30,13 @@ namespace AZ
if (Interface::Get() == nullptr)
{
+ #if (AZ_TRAIT_THREAD_NUM_TASK_GRAPH_WORKER_THREADS)
+ const uint32_t numberOfWorkerThreads = AZ_TRAIT_THREAD_NUM_TASK_GRAPH_WORKER_THREADS;
+ #else
+ const uint32_t numberOfWorkerThreads = Threading::CalcNumWorkerThreads(cl_taskGraphThreadsConcurrencyRatio, cl_taskGraphThreadsMinNumber, cl_taskGraphThreadsNumReserved);
+ #endif // (AZ_TRAIT_THREAD_NUM_TASK_GRAPH_WORKER_THREADS)
Interface::Register(this); // small window that another thread can try to use taskgraph between this line and the set instance.
- m_taskExecutor = aznew TaskExecutor(Threading::CalcNumWorkerThreads(cl_taskGraphThreadsConcurrencyRatio, cl_taskGraphThreadsMinNumber, cl_taskGraphThreadsNumReserved));
+ m_taskExecutor = aznew TaskExecutor(numberOfWorkerThreads);
TaskExecutor::SetInstance(m_taskExecutor);
}
}
diff --git a/Code/Framework/AzCore/Platform/Android/AzCore/AzCore_Traits_Android.h b/Code/Framework/AzCore/Platform/Android/AzCore/AzCore_Traits_Android.h
index 495c8d5f2c..e05e000a4e 100644
--- a/Code/Framework/AzCore/Platform/Android/AzCore/AzCore_Traits_Android.h
+++ b/Code/Framework/AzCore/Platform/Android/AzCore/AzCore_Traits_Android.h
@@ -75,7 +75,6 @@
#define AZ_TRAIT_HEAPSCHEMA_COMPILE_MALLINFO 0
#define AZ_TRAIT_IS_ABS_PATH_IF_COLON_FOUND_ANYWHERE 0
#define AZ_TRAIT_JSON_CLANG_IGNORE_UNKNOWN_WARNING 0
-#define AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS 0
#define AZ_TRAIT_PERF_MEMORYBENCHMARK_IS_AVAILABLE 0
#define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING 0
#define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING_INTERVAL_MS 0
diff --git a/Code/Framework/AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h b/Code/Framework/AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h
index 6ba369e86d..2c0d554078 100644
--- a/Code/Framework/AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h
+++ b/Code/Framework/AzCore/Platform/Linux/AzCore/AzCore_Traits_Linux.h
@@ -75,7 +75,6 @@
#define AZ_TRAIT_HEAPSCHEMA_COMPILE_MALLINFO 1
#define AZ_TRAIT_IS_ABS_PATH_IF_COLON_FOUND_ANYWHERE 0
#define AZ_TRAIT_JSON_CLANG_IGNORE_UNKNOWN_WARNING 0
-#define AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS 0
#define AZ_TRAIT_PERF_MEMORYBENCHMARK_IS_AVAILABLE 0
#define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING 0
#define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING_INTERVAL_MS 0
diff --git a/Code/Framework/AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h b/Code/Framework/AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h
index a41b5c6baa..816a28b728 100644
--- a/Code/Framework/AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h
+++ b/Code/Framework/AzCore/Platform/Mac/AzCore/AzCore_Traits_Mac.h
@@ -75,7 +75,6 @@
#define AZ_TRAIT_HEAPSCHEMA_COMPILE_MALLINFO 1
#define AZ_TRAIT_IS_ABS_PATH_IF_COLON_FOUND_ANYWHERE 0
#define AZ_TRAIT_JSON_CLANG_IGNORE_UNKNOWN_WARNING 0
-#define AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS 0
#define AZ_TRAIT_PERF_MEMORYBENCHMARK_IS_AVAILABLE 0
#define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING 0
#define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING_INTERVAL_MS 0
diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/AzCore_Traits_Windows.h b/Code/Framework/AzCore/Platform/Windows/AzCore/AzCore_Traits_Windows.h
index 2f9fcefdbd..83cff9b54f 100644
--- a/Code/Framework/AzCore/Platform/Windows/AzCore/AzCore_Traits_Windows.h
+++ b/Code/Framework/AzCore/Platform/Windows/AzCore/AzCore_Traits_Windows.h
@@ -75,7 +75,6 @@
#define AZ_TRAIT_HEAPSCHEMA_COMPILE_MALLINFO 1
#define AZ_TRAIT_IS_ABS_PATH_IF_COLON_FOUND_ANYWHERE 0
#define AZ_TRAIT_JSON_CLANG_IGNORE_UNKNOWN_WARNING 1
-#define AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS 0
#define AZ_TRAIT_PERF_MEMORYBENCHMARK_IS_AVAILABLE 1
#define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING 0
#define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING_INTERVAL_MS 0
diff --git a/Code/Framework/AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h b/Code/Framework/AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h
index d53f4b057e..b0832c54f6 100644
--- a/Code/Framework/AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h
+++ b/Code/Framework/AzCore/Platform/iOS/AzCore/AzCore_Traits_iOS.h
@@ -76,7 +76,6 @@
#define AZ_TRAIT_HEAPSCHEMA_COMPILE_MALLINFO 1
#define AZ_TRAIT_IS_ABS_PATH_IF_COLON_FOUND_ANYWHERE 0
#define AZ_TRAIT_JSON_CLANG_IGNORE_UNKNOWN_WARNING 0
-#define AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS 0
#define AZ_TRAIT_PERF_MEMORYBENCHMARK_IS_AVAILABLE 0
#define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING 0
#define AZ_TRAIT_PUMP_SYSTEM_EVENTS_WHILE_LOADING_INTERVAL_MS 0
diff --git a/Code/Framework/AzCore/Tests/Asset/AssetManagerLoadingTests.cpp b/Code/Framework/AzCore/Tests/Asset/AssetManagerLoadingTests.cpp
index e33dbce9c1..3f2d9491a7 100644
--- a/Code/Framework/AzCore/Tests/Asset/AssetManagerLoadingTests.cpp
+++ b/Code/Framework/AzCore/Tests/Asset/AssetManagerLoadingTests.cpp
@@ -652,7 +652,7 @@ namespace UnitTest
threads.emplace_back([this, &threadCount, &cv, assetUuid]() {
bool checkLoaded = true;
- for (int i = 0; i < 5000; i++)
+ for (int i = 0; i < 1000; i++)
{
Asset asset1 =
m_testAssetManager->GetAsset(assetUuid, azrtti_typeid(), AZ::Data::AssetLoadBehavior::PreLoad);
@@ -678,7 +678,7 @@ namespace UnitTest
while (threadCount > 0 && !timedOut)
{
AZStd::unique_lock lock(mutex);
- timedOut = (AZStd::cv_status::timeout == cv.wait_until(lock, AZStd::chrono::system_clock::now() + DefaultTimeoutSeconds * 20000));
+ timedOut = (AZStd::cv_status::timeout == cv.wait_until(lock, AZStd::chrono::system_clock::now() + DefaultTimeoutSeconds));
}
ASSERT_EQ(threadCount, 0) << "Thread count is non-zero, a thread has likely deadlocked. Test will not shut down cleanly.";
@@ -1190,7 +1190,7 @@ namespace UnitTest
#if AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
TEST_F(AssetJobsFloodTest, DISABLED_ContainerFilterTest_ContainersWithAndWithoutFiltering_Success)
#else
- TEST_F(AssetJobsFloodTest, DISABLED_ContainerFilterTest_ContainersWithAndWithoutFiltering_Success)
+ TEST_F(AssetJobsFloodTest, ContainerFilterTest_ContainersWithAndWithoutFiltering_Success)
#endif // !AZ_TRAIT_DISABLE_FAILED_ASSET_MANAGER_TESTS
{
m_assetHandlerAndCatalog->AssetCatalogRequestBus::Handler::BusConnect();
diff --git a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp
index c1c5775958..0fede85aa7 100644
--- a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp
@@ -1241,6 +1241,10 @@ namespace AZ::IO
m_arrZips.insert(revItZip.base(), desc);
+ // This lock is for m_arrZips.
+ // Unlock it now because the modification is complete, and events responding to this signal
+ // will attempt to lock the same mutex, causing the application to lock up.
+ lock.unlock();
m_levelOpenEvent.Signal(levelDirs);
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h
index fd4196a296..282898c37d 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h
@@ -927,6 +927,9 @@ namespace AzToolsFramework
/// Notify that the MainWindow has been fully initialized
virtual void NotifyMainWindowInitialized(QMainWindow* /*mainWindow*/) {}
+ /// Notify that the Editor has been fully initialized
+ virtual void NotifyEditorInitialized() {}
+
/// Signal that an asset should be highlighted / selected
virtual void SelectAsset(const QString& /* assetPath */) {}
};
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp
index 3c7495e836..056872edab 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp
@@ -214,12 +214,17 @@ namespace AzToolsFramework
, public AZ::BehaviorEBusHandler
{
AZ_EBUS_BEHAVIOR_BINDER(EditorEventsBusHandler, "{352F80BB-469A-40B6-B322-FE57AB51E4DA}", AZ::SystemAllocator,
- NotifyRegisterViews);
+ NotifyRegisterViews, NotifyEditorInitialized);
void NotifyRegisterViews() override
{
Call(FN_NotifyRegisterViews);
}
+
+ void NotifyEditorInitialized() override
+ {
+ Call(FN_NotifyEditorInitialized);
+ }
};
} // Internal
@@ -443,6 +448,7 @@ namespace AzToolsFramework
->Attribute(AZ::Script::Attributes::Module, "editor")
->Handler()
->Event("NotifyRegisterViews", &EditorEvents::NotifyRegisterViews)
+ ->Event("NotifyEditorInitialized", &EditorEvents::NotifyEditorInitialized)
;
behaviorContext->EBus("ViewPaneCallbackBus")
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserComponent.cpp
index 7da6f794d6..172bd3a29c 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserComponent.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserComponent.cpp
@@ -234,11 +234,6 @@ namespace AzToolsFramework
return SourceFileDetails("Icons/AssetBrowser/Lua_16.svg");
}
- if (AzFramework::StringFunc::Equal(extension.c_str(), ".mtl"))
- {
- return SourceFileDetails("Icons/AssetBrowser/Material_16.svg");
- }
-
if (AzFramework::StringFunc::Equal(extension.c_str(), AzToolsFramework::SliceUtilities::GetSliceFileExtension().c_str()))
{
return SourceFileDetails("Icons/AssetBrowser/Slice_16.svg");
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp
index 4ebeb03a71..eae8ec2a1e 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetPicker/AssetPickerDialog.cpp
@@ -31,7 +31,10 @@ AZ_POP_DISABLE_WARNING
AZ_CVAR(
bool, ed_hideAssetPickerPathColumn, true, nullptr, AZ::ConsoleFunctorFlags::Null,
"Hide AssetPicker path column for a clearer view.");
-AZ_CVAR_EXTERNED(bool, ed_useNewAssetBrowserTableView);
+
+AZ_CVAR(
+ bool, ed_useNewAssetPickerView, false, nullptr, AZ::ConsoleFunctorFlags::Null,
+ "Uses the new Asset Picker View.");
namespace AzToolsFramework
{
@@ -106,7 +109,7 @@ namespace AzToolsFramework
m_persistentState = AZ::UserSettings::CreateFind(AZ::Crc32(("AssetBrowserTreeView_Dialog_" + name).toUtf8().data()), AZ::UserSettings::CT_GLOBAL);
m_ui->m_assetBrowserTableViewWidget->setVisible(false);
- if (ed_useNewAssetBrowserTableView)
+ if (ed_useNewAssetPickerView)
{
m_ui->m_assetBrowserTreeViewWidget->setVisible(false);
m_ui->m_assetBrowserTableViewWidget->setVisible(true);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.cpp
index 2cca3804ea..20a15643c6 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Component/EditorComponentAPIComponent.cpp
@@ -597,11 +597,13 @@ namespace AzToolsFramework
pte.SetVisibleEnforcement(true);
}
+ ScopedUndoBatch undo("Modify Entity Property");
PropertyOutcome result = pte.SetProperty(propertyPath, value);
if (result.IsSuccess())
{
PropertyEditorEntityChangeNotificationBus::Event(componentInstance.GetEntityId(), &PropertyEditorEntityChangeNotifications::OnEntityComponentPropertyChanged, componentInstance.GetComponentId());
}
+ undo.MarkEntityDirty(componentInstance.GetEntityId());
return result;
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp
index 920e99665d..c1fc9138d1 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp
@@ -64,6 +64,9 @@ namespace AzToolsFramework::Prefab
);
m_backButton->setToolTip("Up one level (-)");
+
+ // Currently hide this button until we can correctly disable/enable it based on context.
+ m_backButton->hide();
}
void PrefabViewportFocusPathHandler::OnPrefabFocusChanged()
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp
index 29bc106eed..9ecbdf5ffc 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp
@@ -4705,13 +4705,6 @@ namespace AzToolsFramework
{
if (mimeData->hasFormat(AssetBrowser::AssetBrowserEntry::GetMimeType()))
{
- // extra special case: MTLs from FBX drags are ignored. are we dragging a FBX file?
- bool isDraggingFBXFile = false;
- AssetBrowser::AssetBrowserEntry::ForEachEntryInMimeData(mimeData, [&](const AssetBrowser::SourceAssetBrowserEntry* source)
- {
- isDraggingFBXFile = isDraggingFBXFile || AzFramework::StringFunc::Equal(source->GetExtension().c_str(), ".fbx", false);
- });
-
// the usual case - we only allow asset browser drops of assets that have actually been associated with a kind of component.
AssetBrowser::AssetBrowserEntry::ForEachEntryInMimeData(mimeData, [&](const AssetBrowser::ProductAssetBrowserEntry* product)
{
@@ -4723,17 +4716,7 @@ namespace AzToolsFramework
if (canCreateComponent && !componentTypeId.IsNull())
{
- // we have a component type that handles this asset.
- // but we disallow it if its a MTL file from a FBX and the FBX itself is being dragged. Its still allowed
- // to drag the actual MTL.
- EBusFindAssetTypeByName materialAssetTypeResult("Material");
- AZ::AssetTypeInfoBus::BroadcastResult(materialAssetTypeResult, &AZ::AssetTypeInfo::GetAssetType);
- AZ::Data::AssetType materialAssetType = materialAssetTypeResult.GetAssetType();
-
- if ((!isDraggingFBXFile) || (product->GetAssetType() != materialAssetType))
- {
- callbackFunction(product);
- }
+ callbackFunction(product);
}
});
}
diff --git a/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp b/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp
index a02eef8b75..f9b5d6aef7 100644
--- a/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp
+++ b/Code/Tools/AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.cpp
@@ -690,7 +690,6 @@ namespace AssetBuilderSDK
static const char* textureExtensions = ".dds";
static const char* staticMeshExtensions = ".cgf";
static const char* skinnedMeshExtensions = ".skin";
- static const char* materialExtensions = ".mtl";
// MIPS
static const int c_MaxMipsCount = 11; // 11 is for 8k textures non-compressed. When not compressed it is using one file per mip.
@@ -805,11 +804,6 @@ namespace AssetBuilderSDK
return textureAssetType;
}
- if (AzFramework::StringFunc::Find(materialExtensions, extension.c_str()) != AZStd::string::npos)
- {
- return materialAssetType;
- }
-
if (AzFramework::StringFunc::Find(staticMeshExtensions, extension.c_str()) != AZStd::string::npos)
{
return meshAssetType;
diff --git a/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Traits_Linux.h b/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Traits_Linux.h
index 7c0543361f..d7edcfcf12 100644
--- a/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Traits_Linux.h
+++ b/Code/Tools/ProjectManager/Platform/Linux/ProjectManager_Traits_Linux.h
@@ -9,3 +9,4 @@
#pragma once
#define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR false
+#define AZ_TRAIT_PROJECT_MANAGER_CREATE_DESKTOP_SHORTCUT false
diff --git a/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp b/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp
index dc3ec55dee..a7bd2dae08 100644
--- a/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp
+++ b/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp
@@ -96,5 +96,10 @@ namespace O3DE::ProjectManager
{
return AZ::Utils::GetExecutableDirectory();
}
+
+ AZ::Outcome CreateDesktopShortcut([[maybe_unused]] const QString& filename, [[maybe_unused]] const QString& targetPath, [[maybe_unused]] const QStringList& arguments)
+ {
+ return AZ::Failure(QObject::tr("Creating desktop shortcuts functionality not implemented for this platform yet."));
+ }
} // namespace ProjectUtils
} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Traits_Mac.h b/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Traits_Mac.h
index 7c0543361f..d7edcfcf12 100644
--- a/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Traits_Mac.h
+++ b/Code/Tools/ProjectManager/Platform/Mac/ProjectManager_Traits_Mac.h
@@ -9,3 +9,4 @@
#pragma once
#define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR false
+#define AZ_TRAIT_PROJECT_MANAGER_CREATE_DESKTOP_SHORTCUT false
diff --git a/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp b/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp
index b768200398..62011bf04b 100644
--- a/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp
+++ b/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp
@@ -137,5 +137,10 @@ namespace O3DE::ProjectManager
return editorPath;
}
+
+ AZ::Outcome CreateDesktopShortcut([[maybe_unused]] const QString& filename, [[maybe_unused]] const QString& targetPath, [[maybe_unused]] const QStringList& arguments)
+ {
+ return AZ::Failure(QObject::tr("Creating desktop shortcuts functionality not implemented for this platform yet."));
+ }
} // namespace ProjectUtils
} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Traits_Windows.h b/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Traits_Windows.h
index e6422b5a77..9e4d29b58f 100644
--- a/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Traits_Windows.h
+++ b/Code/Tools/ProjectManager/Platform/Windows/ProjectManager_Traits_Windows.h
@@ -9,3 +9,4 @@
#pragma once
#define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR true
+#define AZ_TRAIT_PROJECT_MANAGER_CREATE_DESKTOP_SHORTCUT true
diff --git a/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp b/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp
index 871f8e9567..d08da1d5e1 100644
--- a/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp
+++ b/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp
@@ -13,6 +13,7 @@
#include
#include
#include
+#include
#include
@@ -146,5 +147,26 @@ namespace O3DE::ProjectManager
{
return AZ::Utils::GetExecutableDirectory();
}
+
+ AZ::Outcome CreateDesktopShortcut(const QString& filename, const QString& targetPath, const QStringList& arguments)
+ {
+ const QString cmd{"powershell.exe"};
+ const QString desktopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
+ const QString shortcutPath = QString("%1/%2.lnk").arg(desktopPath).arg(filename);
+ const QString arg = QString("$s=(New-Object -COM WScript.Shell).CreateShortcut('%1');$s.TargetPath='%2';$s.Arguments='%3';$s.Save();")
+ .arg(shortcutPath)
+ .arg(targetPath)
+ .arg(arguments.join(' '));
+ auto createShortcutResult = ExecuteCommandResult(cmd, QStringList{"-Command", arg}, QProcessEnvironment::systemEnvironment());
+ if (!createShortcutResult.IsSuccess())
+ {
+ return AZ::Failure(QObject::tr("Failed to create desktop shortcut %1
"
+ "Please verify you have permission to create files at the specified location.
%2")
+ .arg(shortcutPath)
+ .arg(createShortcutResult.GetError()));
+ }
+
+ return AZ::Success(QObject::tr("Desktop shortcut created at
%2").arg(desktopPath).arg(shortcutPath));
+ }
} // namespace ProjectUtils
} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp
index 6abbfe16ba..0dacbbb906 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp
@@ -126,7 +126,8 @@ namespace O3DE::ProjectManager
// Select the first entry after everything got correctly sized
QTimer::singleShot(200, [=]{
QModelIndex firstModelIndex = m_gemModel->index(0, 0);
- m_gemModel->GetSelectionModel()->select(firstModelIndex, QItemSelectionModel::ClearAndSelect);
+ QModelIndex proxyIndex = m_proxyModel->mapFromSource(firstModelIndex);
+ m_proxyModel->GetSelectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect);
});
}
@@ -209,7 +210,7 @@ namespace O3DE::ProjectManager
const bool gemFound = gemInfoHash.contains(gemName);
if (!gemFound && !m_gemModel->IsAdded(index) && !m_gemModel->IsAddedDependency(index))
{
- m_gemModel->removeRow(i);
+ m_gemModel->RemoveGem(index);
}
else
{
@@ -239,7 +240,7 @@ namespace O3DE::ProjectManager
m_filterWidget->ResetAllFilters();
// Reselect the same selection to proc UI updates
- m_proxyModel->GetSelectionModel()->select(m_proxyModel->GetSelectionModel()->selection(), QItemSelectionModel::Select);
+ m_proxyModel->GetSelectionModel()->setCurrentIndex(m_proxyModel->GetSelectionModel()->currentIndex(), QItemSelectionModel::Select);
}
void GemCatalogScreen::OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies)
@@ -268,7 +269,7 @@ namespace O3DE::ProjectManager
if (added && GemModel::GetDownloadStatus(modelIndex) == GemInfo::DownloadStatus::NotDownloaded)
{
m_downloadController->AddGemDownload(GemModel::GetName(modelIndex));
- GemModel::SetDownloadStatus(*m_proxyModel, m_proxyModel->mapFromSource(modelIndex), GemInfo::DownloadStatus::Downloading);
+ GemModel::SetDownloadStatus(*m_gemModel, modelIndex, GemInfo::DownloadStatus::Downloading);
}
}
@@ -300,7 +301,7 @@ namespace O3DE::ProjectManager
}
QModelIndex proxyIndex = m_proxyModel->mapFromSource(modelIndex);
- m_proxyModel->GetSelectionModel()->select(proxyIndex, QItemSelectionModel::ClearAndSelect);
+ m_proxyModel->GetSelectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect);
m_gemListView->scrollTo(proxyIndex);
}
@@ -362,6 +363,9 @@ namespace O3DE::ProjectManager
{
const QString selectedGemPath = m_gemModel->GetPath(modelIndex);
+ // Remove gem from gems to be added
+ GemModel::SetIsAdded(*m_gemModel, modelIndex, false);
+
// Unregister the gem
auto unregisterResult = PythonBindingsInterface::Get()->UnregisterGem(selectedGemPath);
if (!unregisterResult)
@@ -370,8 +374,10 @@ namespace O3DE::ProjectManager
}
else
{
+ const QString selectedGemName = m_gemModel->GetName(modelIndex);
+
// Remove gem from model
- m_gemModel->removeRow(modelIndex.row());
+ m_gemModel->RemoveGem(modelIndex);
// Delete uninstalled gem directory
if (!ProjectUtils::DeleteProjectFiles(selectedGemPath, /*force*/true))
@@ -382,6 +388,11 @@ namespace O3DE::ProjectManager
// Show undownloaded remote gem again
Refresh();
+
+ // Select remote gem
+ QModelIndex remoteGemIndex = m_gemModel->FindIndexByNameString(selectedGemName);
+ QModelIndex proxyIndex = m_proxyModel->mapFromSource(remoteGemIndex);
+ m_proxyModel->GetSelectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect);
}
}
}
@@ -564,7 +575,8 @@ namespace O3DE::ProjectManager
if (succeeded)
{
// refresh the information for downloaded gems
- const AZ::Outcome, AZStd::string>& allGemInfosResult = PythonBindingsInterface::Get()->GetAllGemInfos(m_projectPath);
+ const AZ::Outcome, AZStd::string>& allGemInfosResult =
+ PythonBindingsInterface::Get()->GetAllGemInfos(m_projectPath);
if (allGemInfosResult.IsSuccess())
{
// we should find the gem name now in all gem infos
@@ -572,15 +584,33 @@ namespace O3DE::ProjectManager
{
if (gemInfo.m_name == gemName)
{
- QModelIndex index = m_gemModel->FindIndexByNameString(gemName);
- if (index.isValid())
+ QModelIndex oldIndex = m_gemModel->FindIndexByNameString(gemName);
+ if (oldIndex.isValid())
{
- m_proxyModel->setData(m_proxyModel->mapFromSource(index), GemInfo::DownloadSuccessful, GemModel::RoleDownloadStatus);
- m_gemModel->setData(index, gemInfo.m_path, GemModel::RolePath);
- m_gemModel->setData(index, gemInfo.m_path, GemModel::RoleDirectoryLink);
+ // Check if old gem is selected
+ bool oldGemSelected = false;
+ if (m_gemModel->GetSelectionModel()->currentIndex() == oldIndex)
+ {
+ oldGemSelected = true;
+ }
+
+ // Remove old remote gem
+ m_gemModel->RemoveGem(oldIndex);
+
+ // Add new downloaded version of gem
+ QModelIndex newIndex = m_gemModel->AddGem(gemInfo);
+ GemModel::SetDownloadStatus(*m_gemModel, newIndex, GemInfo::DownloadSuccessful);
+ GemModel::SetIsAdded(*m_gemModel, newIndex, true);
+
+ // Select new version of gem if it was previously selected
+ if (oldGemSelected)
+ {
+ QModelIndex proxyIndex = m_proxyModel->mapFromSource(newIndex);
+ m_proxyModel->GetSelectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect);
+ }
}
- return;
+ break;
}
}
}
@@ -590,7 +620,7 @@ namespace O3DE::ProjectManager
QModelIndex index = m_gemModel->FindIndexByNameString(gemName);
if (index.isValid())
{
- m_proxyModel->setData(m_proxyModel->mapFromSource(index), GemInfo::DownloadFailed, GemModel::RoleDownloadStatus);
+ GemModel::SetDownloadStatus(*m_gemModel, index, GemInfo::DownloadFailed);
}
}
}
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp
index 886b9e57c7..95fdc8e1e2 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp
@@ -26,14 +26,14 @@ namespace O3DE::ProjectManager
return m_selectionModel;
}
- void GemModel::AddGem(const GemInfo& gemInfo)
+ QModelIndex GemModel::AddGem(const GemInfo& gemInfo)
{
if (FindIndexByNameString(gemInfo.m_name).isValid())
{
// do not add gems with duplicate names
// this can happen by mistake or when a gem repo has a gem with the same name as a local gem
AZ_TracePrintf("GemModel", "Ignoring duplicate gem: %s", gemInfo.m_name.toUtf8().constData());
- return;
+ return QModelIndex();
}
QStandardItem* item = new QStandardItem();
@@ -67,6 +67,22 @@ namespace O3DE::ProjectManager
const QModelIndex modelIndex = index(rowCount()-1, 0);
m_nameToIndexMap[gemInfo.m_name] = modelIndex;
+
+ return modelIndex;
+ }
+
+ void GemModel::RemoveGem(const QModelIndex& modelIndex)
+ {
+ removeRow(modelIndex.row());
+ }
+
+ void GemModel::RemoveGem(const QString& gemName)
+ {
+ auto nameFind = m_nameToIndexMap.find(gemName);
+ if (nameFind != m_nameToIndexMap.end())
+ {
+ removeRow(nameFind->row());
+ }
}
void GemModel::Clear()
@@ -391,11 +407,11 @@ namespace O3DE::ProjectManager
// Select a valid row if currently selected row was removed
if (selectedRowRemoved)
{
- for (const QModelIndex& index : m_nameToIndexMap)
+ for (const QModelIndex& index : m_nameToIndexMap)
{
if (index.isValid())
{
- GetSelectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
+ GetSelectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
break;
}
}
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h
index 87a718d8c7..bb89d46861 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h
@@ -55,7 +55,9 @@ namespace O3DE::ProjectManager
RoleRepoUri
};
- void AddGem(const GemInfo& gemInfo);
+ QModelIndex AddGem(const GemInfo& gemInfo);
+ void RemoveGem(const QModelIndex& modelIndex);
+ void RemoveGem(const QString& gemName);
void Clear();
void UpdateGemDependencies();
diff --git a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp
index 794635a3e3..91432c2346 100644
--- a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp
+++ b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp
@@ -75,7 +75,7 @@ namespace O3DE::ProjectManager
// Select the first entry after everything got correctly sized
QTimer::singleShot(200, [=]{
QModelIndex firstModelIndex = m_gemRepoListView->model()->index(0,0);
- m_gemRepoListView->selectionModel()->select(firstModelIndex, QItemSelectionModel::ClearAndSelect);
+ m_gemRepoListView->selectionModel()->setCurrentIndex(firstModelIndex, QItemSelectionModel::ClearAndSelect);
});
}
diff --git a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp
index c425c344e1..98916cccf6 100644
--- a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp
@@ -8,7 +8,11 @@
#include
#include
+#include
+#include
#include
+#include
+#include
#include
#include
@@ -23,6 +27,7 @@
#include
#include
#include
+#include
namespace O3DE::ProjectManager
{
@@ -205,6 +210,29 @@ namespace O3DE::ProjectManager
{
AzQtComponents::ShowFileOnDesktop(m_projectInfo.m_path);
});
+
+#if AZ_TRAIT_PROJECT_MANAGER_CREATE_DESKTOP_SHORTCUT
+ menu->addAction(tr("Create Editor desktop shortcut..."), this, [this]()
+ {
+ AZ::IO::FixedMaxPath executableDirectory = ProjectUtils::GetEditorDirectory();
+ AZStd::string executableFilename = "Editor";
+ AZ::IO::FixedMaxPath editorExecutablePath = executableDirectory / (executableFilename + AZ_TRAIT_OS_EXECUTABLE_EXTENSION);
+
+ const QString shortcutName = QString("%1 Editor").arg(m_projectInfo.m_displayName);
+ const QString arg = QString("--regset=\"/Amazon/AzCore/Bootstrap/project_path=%1\"").arg(m_projectInfo.m_path);
+
+ auto result = ProjectUtils::CreateDesktopShortcut(shortcutName, editorExecutablePath.c_str(), { arg });
+ if(result.IsSuccess())
+ {
+ QMessageBox::information(this, tr("Desktop Shortcut Created"), result.GetValue());
+ }
+ else
+ {
+ QMessageBox::critical(this, tr("Failed to create shortcut"), result.GetError());
+ }
+ });
+#endif // AZ_TRAIT_PROJECT_MANAGER_CREATE_DESKTOP_SHORTCUT
+
menu->addSeparator();
menu->addAction(tr("Duplicate"), this, [this]() { emit CopyProject(m_projectInfo); });
menu->addSeparator();
diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp
index bb2bcd070e..4a0e1c153c 100644
--- a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp
+++ b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp
@@ -628,11 +628,11 @@ namespace O3DE::ProjectManager
return AZ::Failure(QObject::tr("Process for command '%1' timed out at %2 seconds").arg(cmd).arg(commandTimeoutSeconds));
}
int resultCode = execProcess.exitCode();
+ QString resultOutput = execProcess.readAllStandardOutput();
if (resultCode != 0)
{
- return AZ::Failure(QObject::tr("Process for command '%1' failed (result code %2").arg(cmd).arg(resultCode));
+ return AZ::Failure(QObject::tr("Process for command '%1' failed (result code %2) %3").arg(cmd).arg(resultCode).arg(resultOutput));
}
- QString resultOutput = execProcess.readAllStandardOutput();
return AZ::Success(resultOutput);
}
diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.h b/Code/Tools/ProjectManager/Source/ProjectUtils.h
index 890d50d2de..ee605b5117 100644
--- a/Code/Tools/ProjectManager/Source/ProjectUtils.h
+++ b/Code/Tools/ProjectManager/Source/ProjectUtils.h
@@ -68,6 +68,15 @@ namespace O3DE::ProjectManager
AZ::Outcome GetProjectBuildPath(const QString& projectPath);
AZ::Outcome OpenCMakeGUI(const QString& projectPath);
AZ::Outcome RunGetPythonScript(const QString& enginePath);
+
+ /**
+ * Create a desktop shortcut.
+ * @param filename the name of the desktop shorcut file
+ * @param target the path to the target to run
+ * @param arguments the argument list to provide to the target
+ * @return AZ::Outcome with the command result on success
+ */
+ AZ::Outcome CreateDesktopShortcut(const QString& filename, const QString& targetPath, const QStringList& arguments);
AZ::IO::FixedMaxPath GetEditorDirectory();
diff --git a/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingConstants.h b/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingConstants.h
index 97eb5b6492..a3d18c1ea1 100644
--- a/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingConstants.h
+++ b/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingConstants.h
@@ -68,7 +68,7 @@ namespace AWSCore
},
"AccountIdString": {
"type": "string",
- "pattern": "^[0-9]{12}$|EMPTY"
+ "pattern": "^[0-9]{12}$|EMPTY|^$"
},
"NonEmptyString": {
"type": "string",
diff --git a/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp b/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp
index fb03dea4c0..a90518006f 100644
--- a/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp
+++ b/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp
@@ -59,6 +59,34 @@ R"({
"Version": "1.0.0"
})";
+static constexpr const char TEST_VALID_EMPTY_ACCOUNTID_RESOURCE_MAPPING_CONFIG_FILE[] =
+ R"({
+ "AWSResourceMappings": {
+ "TestLambda": {
+ "Type": "AWS::Lambda::Function",
+ "Name/ID": "MyTestLambda",
+ "Region": "us-east-1",
+ "AccountId": "012345678912"
+ },
+ "TestS3Bucket": {
+ "Type": "AWS::S3::Bucket",
+ "Name/ID": "MyTestS3Bucket"
+ },
+ "TestService.RESTApiId": {
+ "Type": "AWS::ApiGateway::RestApi",
+ "Name/ID": "1234567890"
+ },
+ "TestService.RESTApiStage": {
+ "Type": "AWS::ApiGateway::Stage",
+ "Name/ID": "prod",
+ "Region": "us-east-1"
+ }
+ },
+ "AccountId": "",
+ "Region": "us-west-2",
+ "Version": "1.0.0"
+})";
+
static constexpr const char TEST_INVALID_RESOURCE_MAPPING_CONFIG_FILE[] =
R"({
"AWSResourceMappings": {},
@@ -237,6 +265,21 @@ TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseValidConfigFile_Confi
EXPECT_TRUE(actualEbusCalls == testThreadNumber);
}
+TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseValidConfigFile_GlobalAccountIdEmpty)
+{
+ CreateTestConfigFile(TEST_VALID_EMPTY_ACCOUNTID_RESOURCE_MAPPING_CONFIG_FILE);
+ m_resourceMappingManager->ActivateManager();
+
+ AZStd::string actualAccountId;
+ AZStd::string actualRegion;
+ AWSResourceMappingRequestBus::BroadcastResult(actualAccountId, &AWSResourceMappingRequests::GetDefaultAccountId);
+ AWSResourceMappingRequestBus::BroadcastResult(actualRegion, &AWSResourceMappingRequests::GetDefaultRegion);
+ EXPECT_EQ(m_reloadConfigurationCounter, 0);
+ EXPECT_TRUE(actualAccountId.empty());
+ EXPECT_FALSE(actualRegion.empty());
+ EXPECT_TRUE(m_resourceMappingManager->GetStatus() == AWSResourceMappingManager::Status::Ready);
+}
+
TEST_F(AWSResourceMappingManagerTest, DeactivateManager_AfterActivatingWithValidConfigFile_ConfigDataGetCleanedUp)
{
CreateTestConfigFile(TEST_VALID_RESOURCE_MAPPING_CONFIG_FILE);
diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp
index e41c04a0be..99b7c814d1 100644
--- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp
+++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp
@@ -82,7 +82,7 @@ namespace AZ
// Register Shader Asset Builder
AssetBuilderSDK::AssetBuilderDesc shaderAssetBuilderDescriptor;
shaderAssetBuilderDescriptor.m_name = "Shader Asset Builder";
- shaderAssetBuilderDescriptor.m_version = 107; // Required .azsl extension in .shader file references
+ shaderAssetBuilderDescriptor.m_version = 108; // The Build Time Stamp of ShaderAsset And ShaderVariantAsset Should Be Based On GetTimeUTCMilliSecond()
// .shader file changes trigger rebuilds
shaderAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern( AZStd::string::format("*.%s", RPI::ShaderSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
shaderAssetBuilderDescriptor.m_busId = azrtti_typeid();
@@ -108,7 +108,7 @@ namespace AZ
shaderVariantAssetBuilderDescriptor.m_name = "Shader Variant Asset Builder";
// Both "Shader Variant Asset Builder" and "Shader Asset Builder" produce ShaderVariantAsset products. If you update
// ShaderVariantAsset you will need to update BOTH version numbers, not just "Shader Variant Asset Builder".
- shaderVariantAssetBuilderDescriptor.m_version = 26; // [AZSL] Changing inlineConstant to rootConstant keyword work.
+ shaderVariantAssetBuilderDescriptor.m_version = 27; // The Build Time Stamp of ShaderAsset And ShaderVariantAsset Should Be Based On GetTimeUTCMilliSecond().
shaderVariantAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string::format("*.%s", RPI::ShaderVariantListSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
shaderVariantAssetBuilderDescriptor.m_busId = azrtti_typeid();
shaderVariantAssetBuilderDescriptor.m_createJobFunction = AZStd::bind(&ShaderVariantAssetBuilder::CreateJobs, &m_shaderVariantAssetBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp
index 89e202a4bc..e431b74282 100644
--- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp
+++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp
@@ -162,7 +162,7 @@ namespace AZ
// has the same value, because later the ShaderVariantTreeAsset job will fetch this value from the local ShaderAsset
// which could cross platforms (i.e. building an android ShaderVariantTreeAsset on PC would fetch the tiemstamp from
// the PC's ShaderAsset).
- AZStd::sys_time_t shaderAssetBuildTimestamp = AZStd::GetTimeNowMicroSecond();
+ AZ::u64 shaderAssetBuildTimestamp = AZStd::GetTimeUTCMilliSecond();
// Need to get the name of the azsl file from the .shader source asset, to be able to declare a dependency to SRG Layout Job.
// and the macro options to preprocess.
@@ -229,8 +229,8 @@ namespace AZ
} // for all request.m_enabledPlatforms
AZ_TracePrintf(
- ShaderAssetBuilderName, "CreateJobs for %s took %llu microseconds", shaderAssetSourceFileFullPath.c_str(),
- AZStd::GetTimeNowMicroSecond() - shaderAssetBuildTimestamp);
+ ShaderAssetBuilderName, "CreateJobs for %s took %llu milliseconds", shaderAssetSourceFileFullPath.c_str(),
+ AZStd::GetTimeUTCMilliSecond() - shaderAssetBuildTimestamp);
response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
}
@@ -355,8 +355,8 @@ namespace AZ
return;
}
- // Get the time stamp string as sys_time_t, and also convert back to string to make sure it was converted correctly.
- AZStd::sys_time_t shaderAssetBuildTimestamp = 0;
+ // Get the time stamp string as u64, and also convert back to string to make sure it was converted correctly.
+ AZ::u64 shaderAssetBuildTimestamp = 0;
auto shaderAssetBuildTimestampIterator = request.m_jobDescription.m_jobParameters.find(ShaderAssetBuildTimestampParam);
if (shaderAssetBuildTimestampIterator != request.m_jobDescription.m_jobParameters.end())
{
diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp
index bb40baca7d..5eaa0d9ddb 100644
--- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp
+++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp
@@ -765,7 +765,7 @@ namespace AZ
return;
}
- const AZStd::sys_time_t shaderVariantAssetBuildTimestamp = AZStd::GetTimeNowMicroSecond();
+ const AZ::u64 shaderVariantAssetBuildTimestamp = AZStd::GetTimeUTCMilliSecond();
auto supervariantList = ShaderBuilderUtility::GetSupervariantListFromShaderSourceData(shaderSourceDescriptor);
diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.h b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.h
index 2eaf1d9d8b..b0457656af 100644
--- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.h
+++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.h
@@ -38,7 +38,7 @@ namespace AZ
const AZStd::string& m_tempDirPath;
//! Used to synchronize versions of the ShaderAsset and ShaderVariantAsset,
//! especially during hot-reload. A (ShaderVariantAsset.timestamp) >= (ShaderAsset.timestamp).
- const AZStd::sys_time_t m_assetBuildTimestamp;
+ const AZ::u64 m_assetBuildTimestamp;
const RPI::ShaderSourceData& m_shaderSourceDataDescriptor;
const RPI::ShaderOptionGroupLayout& m_shaderOptionGroupLayout;
const MapOfStringToStageType& m_shaderEntryPoints;
diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli
index a7122aaf3a..59817af701 100644
--- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli
+++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli
@@ -166,7 +166,7 @@ float DirectionalLightShadow::GetThickness(uint lightIndex, float3 shadowCoords[
bool2 DirectionalLightShadow::IsShadowed(float3 shadowCoord, uint indexOfCascade)
{
static const float PixelMargin = 1.5; // avoiding artifact between cascade levels.
- static const float DepthMargin = 0.01; // avoiding artifact when near depth bounds.
+ static const float DepthMargin = 1e-8; // avoiding artifact when near depth bounds.
// size is the shadowap's width and height.
const uint size = ViewSrg::m_directionalLightShadows[m_lightIndex].m_shadowmapSize;
@@ -210,8 +210,8 @@ float DirectionalLightShadow::GetVisibilityFromLightNoFilter()
float DirectionalLightShadow::GetVisibilityFromLightPcf()
{
- static const float DepthMargin = 0.01; // avoiding artifact when near depth bounds.
static const float PixelMargin = 1.5; // avoiding artifact between cascade levels.
+ static const float DepthMargin = 1e-8; // avoiding artifact when near depth bounds.
const uint size = ViewSrg::m_directionalLightShadows[m_lightIndex].m_shadowmapSize;
const uint cascadeCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_cascadeCount;
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance.azshader
index 31fae5d98b..a9b5567f6b 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_dx12_0.azshadervariant
index 19e9fdfc8d..6d4b6d0fca 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_null_0.azshadervariant
index 43c4a615cf..5d8800a6fe 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_vulkan_0.azshadervariant
index 75f070a03e..930f7898c4 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblenddistance_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance.azshader
index 0025388bc1..268020b431 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_dx12_0.azshadervariant
index 34a9b3659f..d95ec6c1b9 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_null_0.azshadervariant
index 4a2b0e9944..3253ddba37 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_vulkan_0.azshadervariant
index c053a7db19..c38b94c4f1 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridblendirradiance_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn.azshader
index c507b12563..5c46d368ce 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_dx12_0.azshadervariant
index f60c713597..eb6938f8c9 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_null_0.azshadervariant
index 3e810bcfb5..8c83c1e3ff 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_vulkan_0.azshadervariant
index 5918f277b5..2fbb9ffffe 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdatecolumn_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow.azshader
index 120eb70e54..96053f4091 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_dx12_0.azshadervariant
index d38d779696..4bdbdddf33 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_null_0.azshadervariant
index 6d7a604701..77668a2450 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_vulkan_0.azshadervariant
index dee941cfae..fb3dd771ca 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridborderupdaterow_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification.azshader
index e2e0fa90f5..eda8d53376 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_dx12_0.azshadervariant
index 7a92fc2de5..2df610df77 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_null_0.azshadervariant
index 43408b26f3..f2458e692b 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_vulkan_0.azshadervariant
index 877085446d..0e08e84f74 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridclassification_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing.azshader
index 2c403c77f8..1cea4860a1 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_dx12_0.azshadervariant
index 4bcc47ee43..5605a47e9c 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_null_0.azshadervariant
index f173416210..15f3477cb5 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_vulkan_0.azshadervariant
index 0eb04a25b8..c2bcd4ab07 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit.azshader
index 2847d0035a..9958708a64 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_dx12_0.azshadervariant
index 93cfb47819..fbd1d90251 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_null_0.azshadervariant
index 4a16e24211..483be0eceb 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_vulkan_0.azshadervariant
index df52c9c8d2..530eef2f10 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss.azshader
index d95fd5b3b2..eddac4e2bd 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_dx12_0.azshadervariant
index c853de4d14..ad06bbd104 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_null_0.azshadervariant
index 40e18c215c..527b42569a 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_vulkan_0.azshadervariant
index 34761ccf98..426d955938 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader
index c19020dc84..08ed61ab03 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant
index a7d44b5541..d1012a896f 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant
index 82e0065216..cb730be1df 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant
index 20b81aee6c..b58af4c473 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader
index aec2786540..56009d56ab 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant
index de851f187e..e9893c96da 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant
index 5d8207dfdb..d195b08c34 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant
index c819e57c4c..47789d9b9b 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp
index 410c80dbdc..ce5d3cc363 100644
--- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp
@@ -1248,6 +1248,32 @@ namespace AZ
property.m_shadowmapViewNeedsUpdate = true;
}
+ float DirectionalLightFeatureProcessor::GetShadowmapSizeFromCameraView(const LightHandle handle, const RPI::View* cameraView) const
+ {
+ const DirectionalLightShadowData& shadowData = m_shadowData.at(cameraView).GetData(handle.GetIndex());
+ return static_cast(shadowData.m_shadowmapSize);
+ }
+
+ void DirectionalLightFeatureProcessor::SnapAabbToPixelIncrements(const float invShadowmapSize, Vector3& orthoMin, Vector3& orthoMax)
+ {
+ // This function stops the cascaded shadowmap from shimmering as the camera moves.
+ // See CascadedShadowsManager.cpp in the Microsoft CascadedShadowMaps11 sample for details.
+
+ const Vector3 normalizeByBufferSize = Vector3(invShadowmapSize, invShadowmapSize, invShadowmapSize);
+
+ const Vector3 worldUnitsPerTexel = (orthoMax - orthoMin) * normalizeByBufferSize;
+
+ // We snap the camera to 1 pixel increments so that moving the camera does not cause the shadows to jitter.
+ // This is a matter of dividing by the world space size of a texel
+ orthoMin /= worldUnitsPerTexel;
+ orthoMin = orthoMin.GetFloor();
+ orthoMin *= worldUnitsPerTexel;
+
+ orthoMax /= worldUnitsPerTexel;
+ orthoMax = orthoMax.GetFloor();
+ orthoMax *= worldUnitsPerTexel;
+ }
+
void DirectionalLightFeatureProcessor::UpdateShadowmapViews(LightHandle handle)
{
ShadowProperty& property = m_shadowProperties.GetData(handle.GetIndex());
@@ -1259,18 +1285,26 @@ namespace AZ
for (auto& segmentIt : property.m_segments)
{
+ const float invShadowmapSize = 1.0f / GetShadowmapSizeFromCameraView(handle, segmentIt.first);
+
for (uint16_t cascadeIndex = 0; cascadeIndex < segmentIt.second.size(); ++cascadeIndex)
{
- const Aabb viewAabb = CalculateShadowViewAabb(
- handle, segmentIt.first, cascadeIndex, lightTransform);
+ const Aabb viewAabb = CalculateShadowViewAabb(handle, segmentIt.first, cascadeIndex, lightTransform);
if (viewAabb.IsValid() && viewAabb.IsFinite())
{
+ const float cascadeNear = viewAabb.GetMin().GetY();
+ const float cascadeFar = viewAabb.GetMax().GetY();
+
+ Vector3 snappedAabbMin = viewAabb.GetMin();
+ Vector3 snappedAabbMax = viewAabb.GetMax();
+
+ SnapAabbToPixelIncrements(invShadowmapSize, snappedAabbMin, snappedAabbMax);
+
Matrix4x4 viewToClipMatrix = Matrix4x4::CreateIdentity();
- MakeOrthographicMatrixRH(viewToClipMatrix,
- viewAabb.GetMin().GetElement(0), viewAabb.GetMax().GetElement(0),
- viewAabb.GetMin().GetElement(2), viewAabb.GetMax().GetElement(2),
- viewAabb.GetMin().GetElement(1), viewAabb.GetMax().GetElement(1));
+ MakeOrthographicMatrixRH(
+ viewToClipMatrix, snappedAabbMin.GetElement(0), snappedAabbMax.GetElement(0), snappedAabbMin.GetElement(2),
+ snappedAabbMax.GetElement(2), cascadeNear, cascadeFar);
CascadeSegment& segment = segmentIt.second[cascadeIndex];
segment.m_aabb = viewAabb;
diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h
index 8d7a9d76e4..77f2db38d6 100644
--- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h
+++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h
@@ -341,6 +341,9 @@ namespace AZ
//! This draws bounding boxes of cascades.
void DrawCascadeBoundingBoxes(LightHandle handle);
+ float GetShadowmapSizeFromCameraView(const LightHandle handle, const RPI::View* cameraView) const;
+ void SnapAabbToPixelIncrements(const float invShadowmapSize, Vector3& orthoMin, Vector3& orthoMax);
+
IndexedDataVector m_shadowProperties;
// [GFX TODO][ATOM-2012] shadow for multiple directional lights
LightHandle m_shadowingLightHandle;
diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp
index 5f85d3ad03..fc80cc50d6 100644
--- a/Gems/Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp
+++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/AsyncUploadQueue.cpp
@@ -33,12 +33,20 @@ namespace AZ
ID3D12DeviceX* dx12Device = device.GetDevice();
m_copyQueue = CommandQueue::Create();
-
+
+ // The async upload queue should always use the primary copy queue,
+ // but because this change is being made in the stabilization branch
+ // we will put it behind a define out of an abundance of caution, and
+ // change it to always do this once the change gets back to development.
+ #if defined(AZ_DX12_USE_PRIMARY_COPY_QUEUE_FOR_ASYNC_UPLOAD_QUEUE)
+ m_copyQueue = &device.GetCommandQueueContext().GetCommandQueue(RHI::HardwareQueueClass::Copy);
+ #else
// Make a secondary Copy queue, the primary queue is owned by the CommandQueueContext
CommandQueueDescriptor commandQueueDesc;
commandQueueDesc.m_hardwareQueueClass = RHI::HardwareQueueClass::Copy;
commandQueueDesc.m_hardwareQueueSubclass = HardwareQueueSubclass::Secondary;
m_copyQueue->Init(device, commandQueueDesc);
+ #endif // defined(AZ_DX12_ASYNC_UPLOAD_QUEUE_USE_PRIMARY_COPY_QUEUE)
m_uploadFence.Init(dx12Device, RHI::FenceState::Signaled);
for (size_t i = 0; i < descriptor.m_frameCount; ++i)
diff --git a/Gems/Atom/RPI/Code/CMakeLists.txt b/Gems/Atom/RPI/Code/CMakeLists.txt
index 521178be20..f0459a23c2 100644
--- a/Gems/Atom/RPI/Code/CMakeLists.txt
+++ b/Gems/Atom/RPI/Code/CMakeLists.txt
@@ -160,6 +160,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
Gem::Atom_RPI.Public
Gem::Atom_RHI.Public
Gem::Atom_RPI.Edit
+ Gem::Atom_Utils.TestUtils.Static
)
ly_add_googletest(
NAME Gem::Atom_RPI.Tests
diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h
index 3dbedb7a4b..f5336807c7 100644
--- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h
+++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialTypeSourceData.h
@@ -209,10 +209,6 @@ namespace AZ
//! Traversal will stop once all properties have been enumerated or the callback function returns false
void EnumeratePropertiesInDisplayOrder(const EnumeratePropertiesCallback& callback) const;
- //! Convert the property value into the format that will be stored in the source data
- //! This is primarily needed to support conversions of special types like enums and images
- bool ConvertPropertyValueToSourceDataFormat(const AZ::Name& propertyId, const PropertyDefinition& propertyDefinition, MaterialPropertyValue& propertyValue) const;
-
Outcome> CreateMaterialTypeAsset(Data::AssetId assetId, AZStd::string_view materialTypeSourceFilePath = "", bool elevateWarnings = true) const;
//! Possibly renames @propertyId based on the material version update steps.
diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Shader/ShaderVariantAssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Shader/ShaderVariantAssetCreator.h
index fd069f21e0..488bfb09f8 100644
--- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Shader/ShaderVariantAssetCreator.h
+++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Shader/ShaderVariantAssetCreator.h
@@ -40,7 +40,7 @@ namespace AZ
//! Set the timestamp value when the ProcessJob() started.
//! This is needed to synchronize between the ShaderAsset and ShaderVariantAsset when hot-reloading shaders.
//! The idea is that this timestamp must be greater or equal than the ShaderAsset.
- void SetBuildTimestamp(AZStd::sys_time_t buildTimestamp);
+ void SetBuildTimestamp(AZ::u64 buildTimestamp);
//! Assigns a shaderStageFunction, which contains the byte code, to the slot dictated by the shader stage.
void SetShaderFunction(RHI::ShaderStage shaderStage, RHI::Ptr shaderStageFunction);
diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderAsset.h
index c5df9a4b51..5dc990d93a 100644
--- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderAsset.h
+++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderAsset.h
@@ -294,7 +294,7 @@ namespace AZ
Name m_drawListName;
//! Use to synchronize versions of the ShaderAsset and ShaderVariantTreeAsset, especially during hot-reload.
- AZStd::sys_time_t m_shaderAssetBuildTimestamp = 0;
+ AZ::u64 m_shaderAssetBuildTimestamp = 0;
///////////////////////////////////////////////////////////////////
diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h
index 66bbd7b188..5146ae370a 100644
--- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h
+++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h
@@ -61,7 +61,7 @@ namespace AZ
//! Return the timestamp when this asset was built, and it must be >= than the timestamp of the main ShaderAsset.
//! This is used to synchronize versions of the ShaderAsset and ShaderVariantAsset, especially during hot-reload.
- AZStd::sys_time_t GetBuildTimestamp() const;
+ AZ::u64 GetBuildTimestamp() const;
bool IsRootVariant() const { return m_stableId == RPI::RootShaderVariantStableId; }
@@ -80,7 +80,7 @@ namespace AZ
AZStd::array, RHI::ShaderStageCount> m_functionsByStage;
//! Used to synchronize versions of the ShaderAsset and ShaderVariantAsset, especially during hot-reload.
- AZStd::sys_time_t m_buildTimestamp = 0;
+ AZ::u64 m_buildTimestamp = 0;
};
class ShaderVariantAssetHandler final
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp
index 8d439c99ab..c6fa4653c3 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp
@@ -300,48 +300,6 @@ namespace AZ
}
}
- bool MaterialTypeSourceData::ConvertPropertyValueToSourceDataFormat([[maybe_unused]] const AZ::Name& propertyId, const PropertyDefinition& propertyDefinition, MaterialPropertyValue& propertyValue) const
- {
- if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Enum && propertyValue.Is())
- {
- const uint32_t index = propertyValue.GetValue();
- if (index >= propertyDefinition.m_enumValues.size())
- {
- AZ_Error("Material source data", false, "Invalid value for material enum property: '%s'.", propertyId.GetCStr());
- return false;
- }
-
- propertyValue = propertyDefinition.m_enumValues[index];
- return true;
- }
-
- // Image asset references must be converted from asset IDs to a relative source file path
- if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Image && propertyValue.Is>())
- {
- const Data::Asset& imageAsset = propertyValue.GetValue>();
-
- Data::AssetInfo imageAssetInfo;
- if (imageAsset.GetId().IsValid())
- {
- bool result = false;
- AZStd::string rootFilePath;
- const AZStd::string platformName = ""; // Empty for default
- AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetAssetInfoById,
- imageAsset.GetId(), imageAsset.GetType(), platformName, imageAssetInfo, rootFilePath);
- if (!result)
- {
- AZ_Error("Material source data", false, "Image asset could not be found for property: '%s'.", propertyId.GetCStr());
- return false;
- }
- }
-
- propertyValue = imageAssetInfo.m_relativePath;
- return true;
- }
-
- return true;
- }
-
Outcome> MaterialTypeSourceData::CreateMaterialTypeAsset(Data::AssetId assetId, AZStd::string_view materialTypeSourceFilePath, bool elevateWarnings) const
{
MaterialTypeAssetCreator materialTypeAssetCreator;
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderVariantAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderVariantAssetCreator.cpp
index e0e83cfce2..5b32edc0bf 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderVariantAssetCreator.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderVariantAssetCreator.cpp
@@ -92,7 +92,7 @@ namespace AZ
/////////////////////////////////////////////////////////////////////
// Methods for all shader variant types
- void ShaderVariantAssetCreator::SetBuildTimestamp(AZStd::sys_time_t buildTimestamp)
+ void ShaderVariantAssetCreator::SetBuildTimestamp(AZ::u64 buildTimestamp)
{
if (ValidateIsReady())
{
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp
index a2d91fefd6..7dbeac7098 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp
@@ -202,17 +202,17 @@ namespace AZ
return;
}
AZ_Assert(m_asset->m_shaderAssetBuildTimestamp == m_reloadedRootShaderVariantAsset->GetBuildTimestamp(),
- "shaderAsset timeStamp=%lld, but Root ShaderVariantAsset timeStamp=%lld",
+ "shaderAsset '%s' timeStamp=%lld, but Root ShaderVariantAsset timeStamp=%lld", m_asset.GetHint().c_str(),
m_asset->m_shaderAssetBuildTimestamp, m_reloadedRootShaderVariantAsset->GetBuildTimestamp());
m_asset->UpdateRootShaderVariantAsset(m_supervariantIndex, m_reloadedRootShaderVariantAsset);
m_reloadedRootShaderVariantAsset = {}; // Clear the temporary reference.
if (ShaderReloadDebugTracker::IsEnabled())
{
- auto makeTimeString = [](AZStd::sys_time_t timestamp, AZStd::sys_time_t now)
+ auto makeTimeString = [](AZ::u64 timestamp, AZ::u64 now)
{
- AZStd::sys_time_t elapsedMicroseconds = now - timestamp;
- double elapsedSeconds = aznumeric_cast(elapsedMicroseconds / 1'000'000);
+ AZ::u64 elapsedMillis = now - timestamp;
+ double elapsedSeconds = aznumeric_cast(elapsedMillis / 1'000);
AZStd::string timeString = AZStd::string::format("%lld (%f seconds ago)", timestamp, elapsedSeconds);
return timeString;
};
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp
index 442fc6a79f..ec1a65a6d5 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp
@@ -60,7 +60,7 @@ namespace AZ
}
}
- AZStd::sys_time_t ShaderVariantAsset::GetBuildTimestamp() const
+ AZ::u64 ShaderVariantAsset::GetBuildTimestamp() const
{
return m_buildTimestamp;
}
diff --git a/Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h b/Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h
index 48d404d268..0707528d7f 100644
--- a/Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h
+++ b/Gems/Atom/RPI/Code/Tests/Common/RPITestFixture.h
@@ -21,7 +21,7 @@
#include
#include
#include
-#include
+#include
namespace UnitTest
{
diff --git a/Gems/Atom/RPI/Code/atom_rpi_tests_files.cmake b/Gems/Atom/RPI/Code/atom_rpi_tests_files.cmake
index e99e4e456b..5d67948ac8 100644
--- a/Gems/Atom/RPI/Code/atom_rpi_tests_files.cmake
+++ b/Gems/Atom/RPI/Code/atom_rpi_tests_files.cmake
@@ -10,8 +10,6 @@ set(FILES
Tests/Buffer/BufferTests.cpp
Tests/Common/AssetManagerTestFixture.cpp
Tests/Common/AssetManagerTestFixture.h
- Tests/Common/AssetSystemStub.cpp
- Tests/Common/AssetSystemStub.h
Tests/Common/ErrorMessageFinder.cpp
Tests/Common/ErrorMessageFinder.h
Tests/Common/ErrorMessageFinderTests.cpp
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt b/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt
index e64c9b80e7..40c8d7956e 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt
@@ -61,3 +61,31 @@ ly_add_target(
PRIVATE
Gem::AtomToolsFramework.Static
)
+
+################################################################################
+# Tests
+################################################################################
+if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
+
+ ly_add_target(
+ NAME AtomToolsFramework.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
+ NAMESPACE Gem
+ FILES_CMAKE
+ atomtoolsframework_tests_files.cmake
+ INCLUDE_DIRECTORIES
+ PRIVATE
+ .
+ Tests
+ BUILD_DEPENDENCIES
+ PRIVATE
+ AZ::AzTest
+ AZ::AzTestShared
+ Gem::AtomToolsFramework.Static
+ Gem::Atom_Utils.TestUtils.Static
+ )
+
+ ly_add_googletest(
+ NAME Gem::AtomToolsFramework.Tests
+ )
+
+endif()
\ No newline at end of file
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h
index 333796493d..08f59f9e0b 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Util/MaterialPropertyUtil.h
@@ -7,11 +7,12 @@
*/
#pragma once
-#include
-#include
#include
#include
#include
+#include
+#include
+#include
namespace AzToolsFramework
{
@@ -35,12 +36,31 @@ namespace AtomToolsFramework
//! Convert and assign material property meta data fields to editor dynamic property configuration
void ConvertToPropertyConfig(AtomToolsFramework::DynamicPropertyConfig& propertyConfig, const AZ::RPI::MaterialPropertyDynamicMetadata& propertyMetaData);
- //! Convert and assign editor dynamic property configuration fields to material property meta data
+ //! Convert and assign editor dynamic property configuration fields to material property meta data
void ConvertToPropertyMetaData(AZ::RPI::MaterialPropertyDynamicMetadata& propertyMetaData, const AtomToolsFramework::DynamicPropertyConfig& propertyConfig);
//! Compare equality of data types and values of editor property stored in AZStd::any
bool ArePropertyValuesEqual(const AZStd::any& valueA, const AZStd::any& valueB);
+ //! Convert the property value into the format that will be stored in the source data
+ //! This is primarily needed to support conversions of special types like enums and images
+ //! @param exportPath absolute path of the file being saved
+ //! @param propertyDefinition describes type information and other details about propertyValue
+ //! @param propertyValue the value being converted before saving
+ bool ConvertToExportFormat(
+ const AZStd::string& exportPath,
+ const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition,
+ AZ::RPI::MaterialPropertyValue& propertyValue);
+
+ //! Generate a file path from the exported file to the external reference.
+ //! This function returns a relative path from the export file to the reference file.
+ //! If the relative path is too different or distant from the export path then we return the asset folder relative path.
+ //! @param exportPath absolute path of the file being saved
+ //! @param referencePath absolute path of a file that will be treated as an external reference
+ //! @param maxPathDepth the maximum relative depth or number of parent or child folders between the export path and the reference path
+ AZStd::string GetExteralReferencePath(
+ const AZStd::string& exportPath, const AZStd::string& referencePath, const uint32_t maxPathDepth = 2);
+
//! Traverse up the instance data node hierarchy to find the containing dynamic property object
const AtomToolsFramework::DynamicProperty* FindDynamicPropertyForInstanceDataNode(const AzToolsFramework::InstanceDataNode* pNode);
} // namespace AtomToolsFramework
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp
index 3f8a173918..c49cd3fafb 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp
@@ -6,9 +6,10 @@
*
*/
-#include
#include
+#include
+#include
#include
#include
#include
@@ -18,6 +19,7 @@
#include
#include
#include
+#include
#include
namespace AtomToolsFramework
@@ -163,6 +165,88 @@ namespace AtomToolsFramework
return false;
}
+ bool ConvertToExportFormat(
+ const AZStd::string& exportPath,
+ const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition,
+ AZ::RPI::MaterialPropertyValue& propertyValue)
+ {
+ if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Enum && propertyValue.Is())
+ {
+ const uint32_t index = propertyValue.GetValue();
+ if (index >= propertyDefinition.m_enumValues.size())
+ {
+ AZ_Error("AtomToolsFramework", false, "Invalid value for material enum property: '%s'.", propertyDefinition.m_name.c_str());
+ return false;
+ }
+
+ propertyValue = propertyDefinition.m_enumValues[index];
+ return true;
+ }
+
+ // Image asset references must be converted from asset IDs to a relative source file path
+ if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Image)
+ {
+ if (propertyValue.Is>())
+ {
+ const auto& imageAsset = propertyValue.GetValue>();
+ const auto& imagePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(imageAsset.GetId());
+ propertyValue = GetExteralReferencePath(exportPath, imagePath);
+ return true;
+ }
+
+ if (propertyValue.Is>())
+ {
+ const auto& image = propertyValue.GetValue>();
+ const auto& imagePath = image ? AZ::RPI::AssetUtils::GetSourcePathByAssetId(image->GetAssetId()) : "";
+ propertyValue = GetExteralReferencePath(exportPath, imagePath);
+ return true;
+ }
+ }
+
+ return true;
+ }
+
+ AZStd::string GetExteralReferencePath(const AZStd::string& exportPath, const AZStd::string& referencePath, const uint32_t maxPathDepth)
+ {
+ if (referencePath.empty())
+ {
+ return {};
+ }
+
+ AZ::IO::BasicPath exportFolder(exportPath);
+ exportFolder.RemoveFilename();
+
+ const AZStd::string relativePath = AZ::IO::PathView(referencePath).LexicallyRelative(exportFolder).StringAsPosix();
+
+ // Count the difference in depth between the export file path and the referenced file path.
+ uint32_t parentFolderCount = 0;
+ AZStd::string::size_type pos = 0;
+ const AZStd::string parentFolderToken = "..";
+ while ((pos = relativePath.find(parentFolderToken, pos)) != AZStd::string::npos)
+ {
+ parentFolderCount++;
+ pos += parentFolderToken.length();
+ }
+
+ // If the difference in depth is too great then revert to using the asset folder relative path.
+ // We could change this to only use relative paths for references in subfolders.
+ if (parentFolderCount > maxPathDepth)
+ {
+ AZStd::string watchFolder;
+ AZ::Data::AssetInfo assetInfo;
+ bool sourceInfoFound = false;
+ AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
+ sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, referencePath.c_str(),
+ assetInfo, watchFolder);
+ if (sourceInfoFound)
+ {
+ return assetInfo.m_relativePath;
+ }
+ }
+
+ return relativePath;
+ }
+
const AtomToolsFramework::DynamicProperty* FindDynamicPropertyForInstanceDataNode(const AzToolsFramework::InstanceDataNode* pNode)
{
// Traverse up the hierarchy from the input node to search for an instance corresponding to material inspector property
@@ -172,7 +256,8 @@ namespace AtomToolsFramework
const AZ::SerializeContext::ClassData* classData = currentNode->GetClassMetadata();
if (context && classData)
{
- if (context->CanDowncast(classData->m_typeId, azrtti_typeid(), classData->m_azRtti, nullptr))
+ if (context->CanDowncast(
+ classData->m_typeId, azrtti_typeid(), classData->m_azRtti, nullptr))
{
return static_cast(currentNode->FirstInstance());
}
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp
index aeca51230a..f07fd9c536 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Window/AtomToolsMainWindow.cpp
@@ -50,8 +50,9 @@ namespace AtomToolsFramework
void AtomToolsMainWindow::ActivateWindow()
{
- activateWindow();
+ show();
raise();
+ activateWindow();
}
bool AtomToolsMainWindow::AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation)
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp
index aee8e2a775..df16cfbc43 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Tests/AtomToolsFrameworkTest.cpp
@@ -7,25 +7,71 @@
*/
#include
+#include
+#include
-class AtomToolsFrameworkTest
- : public ::testing::Test
+namespace UnitTest
{
-protected:
- void SetUp() override
+ class AtomToolsFrameworkTest : public ::testing::Test
{
+ protected:
+ void SetUp() override
+ {
+ if (!AZ::AllocatorInstance::IsReady())
+ {
+ AZ::AllocatorInstance::Create(AZ::SystemAllocator::Descriptor());
+ }
- }
+ m_assetSystemStub.Activate();
- void TearDown() override
- {
+ RegisterSourceAsset("objects/upgrades/materials/supercondor.material");
+ RegisterSourceAsset("materials/condor.material");
+ RegisterSourceAsset("materials/talisman.material");
+ RegisterSourceAsset("materials/city.material");
+ RegisterSourceAsset("materials/totem.material");
+ RegisterSourceAsset("textures/orange.png");
+ RegisterSourceAsset("textures/red.png");
+ RegisterSourceAsset("textures/gold.png");
+ RegisterSourceAsset("textures/fuzz.png");
+ }
- }
-};
+ void TearDown() override
+ {
+ m_assetSystemStub.Deactivate();
-TEST_F(AtomToolsFrameworkTest, SanityTest)
-{
- ASSERT_TRUE(true);
-}
+ if (AZ::AllocatorInstance::IsReady())
+ {
+ AZ::AllocatorInstance::Destroy();
+ }
+ }
+
+ void RegisterSourceAsset(const AZStd::string& path)
+ {
+ const AZ::IO::BasicPath assetRootPath = AZ::IO::PathView(m_assetRoot).LexicallyNormal();
+ const AZ::IO::BasicPath normalizedPath = AZ::IO::BasicPath(assetRootPath).Append(path).LexicallyNormal();
+
+ AZ::Data::AssetInfo assetInfo = {};
+ assetInfo.m_assetId = AZ::Uuid::CreateRandom();
+ assetInfo.m_relativePath = normalizedPath.LexicallyRelative(assetRootPath).StringAsPosix();
+ m_assetSystemStub.RegisterSourceInfo(normalizedPath.StringAsPosix().c_str(), assetInfo, assetRootPath.StringAsPosix().c_str());
+ }
+
+ static constexpr const char* m_assetRoot = "d:/project/assets/";
+ AssetSystemStub m_assetSystemStub;
+ };
+
+ TEST_F(AtomToolsFrameworkTest, GetExteralReferencePath_Succeeds)
+ {
+ ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("", "", 2), "");
+ ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/materials/condor.material", "", 2), "");
+ ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/materials/talisman.material", "", 2), "");
+ ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/materials/talisman.material", "d:/project/assets/textures/gold.png", 2), "../textures/gold.png");
+ ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/materials/talisman.material", "d:/project/assets/textures/gold.png", 0), "textures/gold.png");
+ ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/objects/upgrades/materials/supercondor.material", "d:/project/assets/materials/condor.material", 3), "../../../materials/condor.material");
+ ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/objects/upgrades/materials/supercondor.material", "d:/project/assets/materials/condor.material", 2), "materials/condor.material");
+ ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/objects/upgrades/materials/supercondor.material", "d:/project/assets/materials/condor.material", 1), "materials/condor.material");
+ ASSERT_EQ(AtomToolsFramework::GetExteralReferencePath("d:/project/assets/objects/upgrades/materials/supercondor.material", "d:/project/assets/materials/condor.material", 0), "materials/condor.material");
+ }
-AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);
+ AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);
+} // namespace UnitTest
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_tests_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_tests_files.cmake
new file mode 100644
index 0000000000..bd9ad9b3d8
--- /dev/null
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_tests_files.cmake
@@ -0,0 +1,11 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+set(FILES
+ Tests/AtomToolsFrameworkTest.cpp
+)
\ No newline at end of file
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp
index 0174871502..4ac0b745fd 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp
@@ -231,18 +231,13 @@ namespace MaterialEditor
// create source data from properties
MaterialSourceData sourceData;
- sourceData.m_materialType = m_materialSourceData.m_materialType;
- sourceData.m_parentMaterial = m_materialSourceData.m_parentMaterial;
-
- AZ_Assert(m_materialAsset && m_materialAsset->GetMaterialTypeAsset(), "When IsOpen() is true, these assets should not be null.");
sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion();
-
- // Force save data to store forward slashes
- AzFramework::StringFunc::Replace(sourceData.m_materialType, "\\", "/");
- AzFramework::StringFunc::Replace(sourceData.m_parentMaterial, "\\", "/");
+ sourceData.m_materialType = AtomToolsFramework::GetExteralReferencePath(m_absolutePath, m_materialSourceData.m_materialType);
+ sourceData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(m_absolutePath, m_materialSourceData.m_parentMaterial);
// populate sourceData with modified or overwritten properties
- const bool savedProperties = SavePropertiesToSourceData(sourceData, [](const AtomToolsFramework::DynamicProperty& property) {
+ const bool savedProperties = SavePropertiesToSourceData(m_absolutePath, sourceData, [](const AtomToolsFramework::DynamicProperty& property)
+ {
return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue);
});
@@ -305,18 +300,13 @@ namespace MaterialEditor
// create source data from properties
MaterialSourceData sourceData;
- sourceData.m_materialType = m_materialSourceData.m_materialType;
- sourceData.m_parentMaterial = m_materialSourceData.m_parentMaterial;
-
- AZ_Assert(m_materialAsset && m_materialAsset->GetMaterialTypeAsset(), "When IsOpen() is true, these assets should not be null.");
sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion();
-
- // Force save data to store forward slashes
- AzFramework::StringFunc::Replace(sourceData.m_materialType, "\\", "/");
- AzFramework::StringFunc::Replace(sourceData.m_parentMaterial, "\\", "/");
+ sourceData.m_materialType = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_materialType);
+ sourceData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_parentMaterial);
// populate sourceData with modified or overwritten properties
- const bool savedProperties = SavePropertiesToSourceData(sourceData, [](const AtomToolsFramework::DynamicProperty& property) {
+ const bool savedProperties = SavePropertiesToSourceData(normalizedSavePath, sourceData, [](const AtomToolsFramework::DynamicProperty& property)
+ {
return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue);
});
@@ -378,23 +368,18 @@ namespace MaterialEditor
// create source data from properties
MaterialSourceData sourceData;
- sourceData.m_materialType = m_materialSourceData.m_materialType;
-
- AZ_Assert(m_materialAsset && m_materialAsset->GetMaterialTypeAsset(), "When IsOpen() is true, these assets should not be null.");
sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion();
+ sourceData.m_materialType = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_materialType);
// Only assign a parent path if the source was a .material
if (AzFramework::StringFunc::Path::IsExtension(m_relativePath.c_str(), MaterialSourceData::Extension))
{
- sourceData.m_parentMaterial = m_relativePath;
+ sourceData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_absolutePath);
}
- // Force save data to store forward slashes
- AzFramework::StringFunc::Replace(sourceData.m_materialType, "\\", "/");
- AzFramework::StringFunc::Replace(sourceData.m_parentMaterial, "\\", "/");
-
// populate sourceData with modified properties
- const bool savedProperties = SavePropertiesToSourceData(sourceData, [](const AtomToolsFramework::DynamicProperty& property) {
+ const bool savedProperties = SavePropertiesToSourceData(normalizedSavePath, sourceData, [](const AtomToolsFramework::DynamicProperty& property)
+ {
return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_originalValue);
});
@@ -591,7 +576,8 @@ namespace MaterialEditor
}
}
- bool MaterialDocument::SavePropertiesToSourceData(AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const
+ bool MaterialDocument::SavePropertiesToSourceData(
+ const AZStd::string& exportPath, AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const
{
using namespace AZ;
using namespace RPI;
@@ -599,7 +585,7 @@ namespace MaterialEditor
bool result = true;
// populate sourceData with properties that meet the filter
- m_materialTypeSourceData.EnumerateProperties([this, &sourceData, &propertyFilter, &result](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition) {
+ m_materialTypeSourceData.EnumerateProperties([&](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition) {
const MaterialPropertyId propertyId(groupName, propertyName);
@@ -609,7 +595,7 @@ namespace MaterialEditor
MaterialPropertyValue propertyValue = AtomToolsFramework::ConvertToRuntimeType(it->second.GetValue());
if (propertyValue.IsValid())
{
- if (!m_materialTypeSourceData.ConvertPropertyValueToSourceDataFormat(propertyId.GetFullName(), propertyDefinition, propertyValue))
+ if (!AtomToolsFramework::ConvertToExportFormat(exportPath, propertyId.GetFullName(), propertyDefinition, propertyValue))
{
AZ_Error("MaterialDocument", false, "Material document property could not be converted: '%s' in '%s'.", propertyId.GetFullName().GetCStr(), m_absolutePath.c_str());
result = false;
@@ -663,8 +649,6 @@ namespace MaterialEditor
return false;
}
- AZStd::string materialTypeSourceFilePath;
-
// The material document and inspector are constructed from source data
if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), MaterialSourceData::Extension))
{
@@ -675,13 +659,24 @@ namespace MaterialEditor
return false;
}
- // We must also always load the material type data for a complete, ordered set of the
- // groups and properties that will be needed for comparison and building the inspector
- materialTypeSourceFilePath = AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_materialType);
- auto materialTypeOutcome = MaterialUtils::LoadMaterialTypeSourceData(materialTypeSourceFilePath);
+ // We always need the absolute path for the material type and parent material to load source data and resolving
+ // relative paths when saving. This will convert and store them as absolute paths for use within the document.
+ if (!m_materialSourceData.m_parentMaterial.empty())
+ {
+ m_materialSourceData.m_parentMaterial =
+ AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_parentMaterial);
+ }
+
+ if (!m_materialSourceData.m_materialType.empty())
+ {
+ m_materialSourceData.m_materialType = AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_materialType);
+ }
+
+ // Load the material type source data which provides the layout and default values of all of the properties
+ auto materialTypeOutcome = MaterialUtils::LoadMaterialTypeSourceData(m_materialSourceData.m_materialType);
if (!materialTypeOutcome.IsSuccess())
{
- AZ_Error("MaterialDocument", false, "Material type source data could not be loaded: '%s'.", materialTypeSourceFilePath.c_str());
+ AZ_Error("MaterialDocument", false, "Material type source data could not be loaded: '%s'.", m_materialSourceData.m_materialType.c_str());
return false;
}
m_materialTypeSourceData = materialTypeOutcome.GetValue();
@@ -694,10 +689,10 @@ namespace MaterialEditor
}
else if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), MaterialTypeSourceData::Extension))
{
- materialTypeSourceFilePath = m_absolutePath;
-
- // Load the material type source data, which will be used for enumerating properties and building material source data
- auto materialTypeOutcome = MaterialUtils::LoadMaterialTypeSourceData(materialTypeSourceFilePath);
+ // A material document can be created or loaded from material or material type source data. If we are attempting to load
+ // material type source data then the material source data object can be created just by referencing the document path as the
+ // material type path.
+ auto materialTypeOutcome = MaterialUtils::LoadMaterialTypeSourceData(m_absolutePath);
if (!materialTypeOutcome.IsSuccess())
{
AZ_Error("MaterialDocument", false, "Material type source data could not be loaded: '%s'.", m_absolutePath.c_str());
@@ -705,9 +700,8 @@ namespace MaterialEditor
}
m_materialTypeSourceData = materialTypeOutcome.GetValue();
- // The document represents a material, not a material type.
- // If the input data is a material type file we have to generate the material source data by referencing it.
- m_materialSourceData.m_materialType = m_relativePath;
+ // We are storing absolute paths in the loaded version of the source data so that the files can be resolved at all times.
+ m_materialSourceData.m_materialType = m_absolutePath;
m_materialSourceData.m_parentMaterial.clear();
}
else
@@ -751,25 +745,24 @@ namespace MaterialEditor
if (!m_materialSourceData.m_parentMaterial.empty())
{
AZ::RPI::MaterialSourceData parentMaterialSourceData;
- const auto parentMaterialFilePath = AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_parentMaterial);
- if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentMaterialFilePath, parentMaterialSourceData))
+ if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_materialSourceData.m_parentMaterial, parentMaterialSourceData))
{
- AZ_Error("MaterialDocument", false, "Material parent source data could not be loaded for: '%s'.", parentMaterialFilePath.c_str());
+ AZ_Error("MaterialDocument", false, "Material parent source data could not be loaded for: '%s'.", m_materialSourceData.m_parentMaterial.c_str());
return false;
}
- const auto parentMaterialAssetIdResult = AssetUtils::MakeAssetId(parentMaterialFilePath, 0);
+ const auto parentMaterialAssetIdResult = AssetUtils::MakeAssetId(m_materialSourceData.m_parentMaterial, 0);
if (!parentMaterialAssetIdResult)
{
- AZ_Error("MaterialDocument", false, "Material parent asset ID could not be created: '%s'.", parentMaterialFilePath.c_str());
+ AZ_Error("MaterialDocument", false, "Material parent asset ID could not be created: '%s'.", m_materialSourceData.m_parentMaterial.c_str());
return false;
}
auto parentMaterialAssetResult = parentMaterialSourceData.CreateMaterialAssetFromSourceData(
- parentMaterialAssetIdResult.GetValue(), parentMaterialFilePath, elevateWarnings, true);
+ parentMaterialAssetIdResult.GetValue(), parentMaterialFilePath, true, true);
if (!parentMaterialAssetResult)
{
- AZ_Error("MaterialDocument", false, "Material parent asset could not be created from source data: '%s'.", parentMaterialFilePath.c_str());
+ AZ_Error("MaterialDocument", false, "Material parent asset could not be created from source data: '%s'.", m_materialSourceData.m_parentMaterial.c_str());
return false;
}
@@ -880,7 +873,8 @@ namespace MaterialEditor
m_properties[propertyConfig.m_id] = AtomToolsFramework::DynamicProperty(propertyConfig);
}
- const MaterialFunctorSourceData::EditorContext editorContext = MaterialFunctorSourceData::EditorContext(materialTypeSourceFilePath, m_materialAsset->GetMaterialPropertiesLayout());
+ const MaterialFunctorSourceData::EditorContext editorContext =
+ MaterialFunctorSourceData::EditorContext(m_materialSourceData.m_materialType, m_materialAsset->GetMaterialPropertiesLayout());
for (Ptr functorData : m_materialTypeSourceData.m_materialFunctorSourceData)
{
MaterialFunctorSourceData::FunctorResult result2 = functorData->CreateFunctor(editorContext);
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h
index 452111f99a..ceb3190f26 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h
@@ -104,7 +104,8 @@ namespace MaterialEditor
void SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid sourceUUID) override;
//////////////////////////////////////////////////////////////////////////
- bool SavePropertiesToSourceData(AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const;
+ bool SavePropertiesToSourceData(
+ const AZStd::string& exportPath, AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const;
bool OpenInternal(AZStd::string_view loadPath);
diff --git a/Gems/Atom/Utils/Code/CMakeLists.txt b/Gems/Atom/Utils/Code/CMakeLists.txt
index 89bc8dd0a5..90d7ce501b 100644
--- a/Gems/Atom/Utils/Code/CMakeLists.txt
+++ b/Gems/Atom/Utils/Code/CMakeLists.txt
@@ -27,6 +27,27 @@ ly_add_target(
3rdParty::libpng
)
+if(PAL_TRAIT_BUILD_HOST_TOOLS)
+
+ ly_add_target(
+ NAME Atom_Utils.TestUtils.Static STATIC
+ NAMESPACE Gem
+ FILES_CMAKE
+ atom_utils_editor_files.cmake
+ INCLUDE_DIRECTORIES
+ PRIVATE
+ Source
+ PUBLIC
+ Include
+ BUILD_DEPENDENCIES
+ PRIVATE
+ AZ::AtomCore
+ AZ::AzCore
+ AZ::AzFramework
+ AZ::AzToolsFramework
+ )
+endif()
+
################################################################################
# Tests
################################################################################
diff --git a/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/TestUtils/AssetSystemStub.h
similarity index 100%
rename from Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.h
rename to Gems/Atom/Utils/Code/Include/Atom/Utils/TestUtils/AssetSystemStub.h
diff --git a/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.cpp b/Gems/Atom/Utils/Code/Source/TestUtils/AssetSystemStub.cpp
similarity index 98%
rename from Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.cpp
rename to Gems/Atom/Utils/Code/Source/TestUtils/AssetSystemStub.cpp
index 31a46e9a6f..d57969ea9c 100644
--- a/Gems/Atom/RPI/Code/Tests/Common/AssetSystemStub.cpp
+++ b/Gems/Atom/Utils/Code/Source/TestUtils/AssetSystemStub.cpp
@@ -6,7 +6,7 @@
*
*/
-#include
+#include
#include
namespace UnitTest
diff --git a/Gems/Atom/Utils/Code/atom_utils_editor_files.cmake b/Gems/Atom/Utils/Code/atom_utils_editor_files.cmake
new file mode 100644
index 0000000000..6c4202fe09
--- /dev/null
+++ b/Gems/Atom/Utils/Code/atom_utils_editor_files.cmake
@@ -0,0 +1,12 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+set(FILES
+ Include/Atom/Utils/TestUtils/AssetSystemStub.h
+ Source/TestUtils/AssetSystemStub.cpp
+)
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp
index 8620ec34f4..d3e125426c 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentUtil.cpp
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -97,51 +98,28 @@ namespace AZ
bool SaveSourceMaterialFromEditData(const AZStd::string& path, const MaterialEditData& editData)
{
- // Construct the material source data object that will be exported
- AZ::RPI::MaterialSourceData exportData;
-
- // Converting absolute material paths to relative paths
- bool result = false;
- AZ::Data::AssetInfo info;
- AZStd::string watchFolder;
- AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
- result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath,
- editData.m_materialTypeSourcePath.c_str(), info, watchFolder);
- if (!result)
+ if (path.empty() || !editData.m_materialAsset.IsReady() || !editData.m_materialTypeAsset.IsReady() ||
+ editData.m_materialTypeSourcePath.empty())
{
- AZ_Error(
- "AZ::Render::EditorMaterialComponentUtil", false,
- "Failed to get material type source file info while attempting to export: %s", path.c_str());
+ AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Can not export: %s", path.c_str());
return false;
}
- exportData.m_materialType = info.m_relativePath;
-
- if (!editData.m_materialParentSourcePath.empty())
- {
- result = false;
- AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
- result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath,
- editData.m_materialParentSourcePath.c_str(), info, watchFolder);
- if (!result)
- {
- AZ_Error(
- "AZ::Render::EditorMaterialComponentUtil", false,
- "Failed to get parent material source file info while attempting to export: %s", path.c_str());
- return false;
- }
-
- exportData.m_parentMaterial = info.m_relativePath;
- }
+ // Construct the material source data object that will be exported
+ AZ::RPI::MaterialSourceData exportData;
+ exportData.m_materialTypeVersion = editData.m_materialTypeAsset->GetVersion();
+ exportData.m_materialType = AtomToolsFramework::GetExteralReferencePath(path, editData.m_materialTypeSourcePath);
+ exportData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(path, editData.m_materialParentSourcePath);
// Copy all of the properties from the material asset to the source data that will be exported
- result = true;
- editData.m_materialTypeSourceData.EnumerateProperties([&](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition) {
+ bool result = true;
+ editData.m_materialTypeSourceData.EnumerateProperties([&](const AZStd::string& groupName, const AZStd::string& propertyName, const auto& propertyDefinition){
const AZ::RPI::MaterialPropertyId propertyId(groupName, propertyName);
const AZ::RPI::MaterialPropertyIndex propertyIndex =
editData.m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyId.GetFullName());
- AZ::RPI::MaterialPropertyValue propertyValue = editData.m_materialAsset->GetPropertyValues()[propertyIndex.GetIndex()];
+ AZ::RPI::MaterialPropertyValue propertyValue =
+ editData.m_materialAsset->GetPropertyValues()[propertyIndex.GetIndex()];
AZ::RPI::MaterialPropertyValue propertyValueDefault = propertyDefinition.m_value;
if (editData.m_materialParentAsset.IsReady())
@@ -151,12 +129,12 @@ namespace AZ
// Check for and apply any property overrides before saving property values
auto propertyOverrideItr = editData.m_materialPropertyOverrideMap.find(propertyId.GetFullName());
- if(propertyOverrideItr != editData.m_materialPropertyOverrideMap.end())
+ if (propertyOverrideItr != editData.m_materialPropertyOverrideMap.end())
{
propertyValue = AZ::RPI::MaterialPropertyValue::FromAny(propertyOverrideItr->second);
}
- if (!editData.m_materialTypeSourceData.ConvertPropertyValueToSourceDataFormat(propertyId.GetFullName(), propertyDefinition, propertyValue))
+ if (!AtomToolsFramework::ConvertToExportFormat(path, propertyId.GetFullName(), propertyDefinition, propertyValue))
{
AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Failed to export: %s", path.c_str());
result = false;
diff --git a/Gems/AtomTressFX/Code/Builders/HairBuilderComponent.cpp b/Gems/AtomTressFX/Code/Builders/HairBuilderComponent.cpp
index f80261f4b5..7f99e4c55f 100644
--- a/Gems/AtomTressFX/Code/Builders/HairBuilderComponent.cpp
+++ b/Gems/AtomTressFX/Code/Builders/HairBuilderComponent.cpp
@@ -46,14 +46,6 @@ namespace AZ
{
m_hairAssetBuilder.RegisterBuilder();
m_hairAssetHandler.Register();
-
- // Add asset types and extensions to AssetCatalog.
- auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler();
- if (assetCatalog)
- {
- assetCatalog->EnableCatalogForAsset(azrtti_typeid());
- assetCatalog->AddExtension(AMD::TFXCombinedFileExtension);
- }
}
void HairBuilderComponent::Deactivate()
diff --git a/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp b/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp
deleted file mode 100644
index 48973b2779..0000000000
--- a/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#include "MaterialBuilderComponent.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-namespace MaterialBuilder
-{
- [[maybe_unused]] const char s_materialBuilder[] = "MaterialBuilder";
-
- namespace Internal
- {
- const char g_nodeNameMaterial[] = "Material";
- const char g_nodeNameSubmaterial[] = "SubMaterials";
- const char g_nodeNameTexture[] = "Texture";
- const char g_nodeNameTextures[] = "Textures";
- const char g_attributeFileName[] = "File";
-
- const int g_numSourceImageFormats = 9;
- const char* g_sourceImageFormats[g_numSourceImageFormats] = { ".tif", ".tiff", ".bmp", ".gif", ".jpg", ".jpeg", ".tga", ".png", ".dds" };
- bool IsSupportedImageExtension(const AZStd::string& extension)
- {
- for (const char* format : g_sourceImageFormats)
- {
- if (extension == format)
- {
- return true;
- }
- }
- return false;
- }
-
- // Cleans up legacy pathing from older materials
- const char* CleanLegacyPathingFromTexturePath(const char* texturePath)
- {
- // Copied from MaterialHelpers::SetTexturesFromXml, line 459
- // legacy. Some textures used to be referenced using "engine\\" or "engine/" - this is no longer valid
- if (
- (strlen(texturePath) > 7) &&
- (azstrnicmp(texturePath, "engine", 6) == 0) &&
- ((texturePath[6] == '\\') || (texturePath[6] == '/'))
- )
- {
- texturePath = texturePath + 7;
- }
-
- // legacy: Files were saved into a mtl with many leading forward or back slashes, we eat them all here. We want it to start with a relative path.
- const char* actualFileName = texturePath;
- while ((actualFileName[0]) && ((actualFileName[0] == '\\') || (actualFileName[0] == '/')))
- {
- ++actualFileName;
- }
- return actualFileName;
- }
-
- // Parses the material XML for all texture paths
- AZ::Outcome GetTexturePathsFromMaterial(AZ::rapidxml::xml_node* materialNode, AZStd::vector& paths)
- {
- AZ::Outcome resultOutcome = AZ::Failure(AZStd::string(""));
- AZStd::string success_with_warning_message;
-
- // check if this material has a set of textures defined, and if so, grab all the paths from the textures
- AZ::rapidxml::xml_node* texturesNode = materialNode->first_node(g_nodeNameTextures);
- if (texturesNode)
- {
- AZ::rapidxml::xml_node* textureNode = texturesNode->first_node(g_nodeNameTexture);
- // it is possible for an empty node to exist for things like collision materials, so check
- // to make sure that there is at least one child node before starting to iterate.
- if (textureNode)
- {
- do
- {
- AZ::rapidxml::xml_attribute* fileAttribute = textureNode->first_attribute(g_attributeFileName);
- if (!fileAttribute)
- {
- success_with_warning_message = "Texture node exists but does not have a file attribute defined";
- }
- else
- {
- const char* rawTexturePath = fileAttribute->value();
- // do an initial clean-up of the path taken from the file, similar to MaterialHelpers::SetTexturesFromXml
- AZStd::string texturePath = CleanLegacyPathingFromTexturePath(rawTexturePath);
- paths.emplace_back(AZStd::move(texturePath));
- }
-
- textureNode = textureNode->next_sibling(g_nodeNameTexture);
- } while (textureNode);
- }
- }
-
- // check to see if this material has sub materials defined. If so, recurse into this function for each sub material
- AZ::rapidxml::xml_node* subMaterialsNode = materialNode->first_node(g_nodeNameSubmaterial);
- if (subMaterialsNode)
- {
- AZ::rapidxml::xml_node* subMaterialNode = subMaterialsNode->first_node(g_nodeNameMaterial);
- if (subMaterialNode == nullptr)
- {
- // this is a malformed material as there is no material node child in the SubMaterials node, so error out
- return AZ::Failure(AZStd::string("SubMaterials node exists but does not have any child Material nodes."));
- }
-
- do
- {
- // grab the texture paths from the submaterial, or error out if necessary
- AZ::Outcome subMaterialTexturePathsResult = GetTexturePathsFromMaterial(subMaterialNode, paths);
- if (!subMaterialTexturePathsResult.IsSuccess())
- {
- return subMaterialTexturePathsResult;
- }
- else if (!subMaterialTexturePathsResult.GetValue().empty())
- {
- success_with_warning_message = subMaterialTexturePathsResult.GetValue();
- }
-
- subMaterialNode = subMaterialNode->next_sibling(g_nodeNameMaterial);
- } while (subMaterialNode);
- }
-
- if (texturesNode == nullptr && subMaterialsNode == nullptr)
- {
- return AZ::Failure(AZStd::string("Failed to find a Textures node or SubMaterials node in this material. At least one of these must exist to be able to gather texture dependencies."));
- }
-
- if (!success_with_warning_message.empty())
- {
- return AZ::Success(success_with_warning_message);
- }
- return AZ::Success(AZStd::string());
- }
-
- // find a sequence of digits with a string starting from lastDigitIndex, and try to parse that sequence to and int
- // and store it in outAnimIndex.
- bool ParseFilePathForCompleteNumber(const AZStd::string& filePath, int& lastDigitIndex, int& outAnimIndex)
- {
- int firstAnimIndexDigit = lastDigitIndex;
- while (isdigit(static_cast(filePath[lastDigitIndex])))
- {
- ++lastDigitIndex;
- }
- if (!AzFramework::StringFunc::LooksLikeInt(filePath.substr(firstAnimIndexDigit, lastDigitIndex - firstAnimIndexDigit).c_str(), &outAnimIndex))
- {
- return false;
- }
- return true;
- }
-
- // Parse the texture path for a texture animation to determine the actual names of the textures to resolve that
- // make up the entire sequence.
- AZ::Outcome GetAllTexturesInTextureSequence(const AZStd::string& path, AZStd::vector& texturesInSequence)
- {
- // Taken from CShaderMan::mfReadTexSequence
- // All comments next to variable declarations in this function are the original variable names in
- // CShaderMan::mfReadTexSequence, to help keep track of how these variables relate to the original function
- AZStd::string prefix;
- AZStd::string postfix;
-
- AZStd::string filePath = path; // name
- AZStd::string extension; // ext
- AzFramework::StringFunc::Path::GetExtension(filePath.c_str(), extension);
- AzFramework::StringFunc::Path::StripExtension(filePath);
-
- // unsure if it is actually possible to enter here or the original version with '$' as the indicator
- // for texture sequences, but they check for both just in case, so this will match the behavior.
- char separator = '#'; // chSep
- int firstSeparatorIndex = static_cast(filePath.find(separator));
- if (firstSeparatorIndex == AZStd::string::npos)
- {
- firstSeparatorIndex = static_cast(filePath.find('$'));
- if (firstSeparatorIndex == AZStd::string::npos)
- {
- return AZ::Failure(AZStd::string("Failed to find separator '#' or '$' in texture path."));
- }
- separator = '$';
- }
-
- // we don't actually care about getting the speed of the animation, so just remove everything from the
- // end of the string starting with the last open parenthesis
- size_t speedStartIndex = filePath.find_last_of('(');
- if (speedStartIndex != AZStd::string::npos)
- {
- AzFramework::StringFunc::LKeep(filePath, speedStartIndex);
- AzFramework::StringFunc::Append(filePath, '\0');
- }
-
- // try to find where the digits start after the separator (there can be any number of separators
- // between the texture name prefix and where the digit range starts)
- int firstAnimIndexDigit = -1; // m
- int numSeparators = 0; // j
- for (int stringIndex = firstSeparatorIndex; stringIndex < filePath.length(); ++stringIndex)
- {
- if (filePath[stringIndex] == separator)
- {
- ++numSeparators;
- if (firstSeparatorIndex == -1)
- {
- firstSeparatorIndex = stringIndex;
- }
- }
- else if (firstSeparatorIndex > 0 && firstAnimIndexDigit < 0)
- {
- firstAnimIndexDigit = stringIndex;
- break;
- }
- }
- if (numSeparators == 0)
- {
- return AZ::Failure(AZStd::string("Failed to find separator '#' or '$' in texture path."));
- }
-
- // store off everything before the separator
- prefix = AZStd::move(filePath.substr(0, firstSeparatorIndex));
-
- int startAnimIndex = 0; // startn
- int endAnimIndex = 0; // endn
- // we only found the separator, but no indexes, so just assume its 0 - 999
- if (firstAnimIndexDigit < 0)
- {
- startAnimIndex = 0;
- endAnimIndex = 999;
- }
- else
- {
- // find the length of the first index, then parse that to an int
- int lastDigitIndex = firstAnimIndexDigit;
- if (!ParseFilePathForCompleteNumber(filePath, lastDigitIndex, startAnimIndex))
- {
- return AZ::Failure(AZStd::string("Failed to determine first index of the sequence after the separators in texture path."));
- }
-
- // reset to the start of the next index
- ++lastDigitIndex;
-
- // find the length of the end index, then parse that to an int
- if (!ParseFilePathForCompleteNumber(filePath, lastDigitIndex, endAnimIndex))
- {
- return AZ::Failure(AZStd::string("Failed to determine last index of the sequence after the first index of the sequence in texture path."));
- }
-
- // save off the rest of the string
- postfix = AZStd::move(filePath.substr(lastDigitIndex));
- }
-
- int numTextures = endAnimIndex - startAnimIndex + 1;
- const char* textureNameFormat = "%s%.*d%s%s"; // prefix, num separators (number of digits), sequence index, postfix, extension)
- for (int sequenceIndex = 0; sequenceIndex < numTextures; ++sequenceIndex)
- {
- texturesInSequence.emplace_back(AZStd::move(AZStd::string::format(textureNameFormat, prefix.c_str(), numSeparators, startAnimIndex + sequenceIndex, postfix.c_str(), extension.c_str())));
- }
-
- return AZ::Success();
- }
-
- // Determine which product path to use based on the path stored in the texture, and make it relative to
- // the cache.
- bool ResolveMaterialTexturePath(const AZStd::string& path, AZStd::string& outPath)
- {
- AZStd::string aliasedPath = path;
-
- //if its a source image format try to load the dds
- AZStd::string extension;
- bool hasExtension = AzFramework::StringFunc::Path::GetExtension(path.c_str(), extension);
-
- // Replace all supported extensions with DDS if it has an extension. If the extension exists but is not supported, fail out.
- if (hasExtension && IsSupportedImageExtension(extension))
- {
- AzFramework::StringFunc::Path::ReplaceExtension(aliasedPath, ".dds");
- }
- else if (hasExtension)
- {
- AZ_Warning(s_materialBuilder, false, "Failed to resolve texture path %s as the path is not to a supported texture format. Please make sure that textures in materials are formats supported by Open 3D Engine.", aliasedPath.c_str());
- return false;
- }
-
- AZStd::to_lower(aliasedPath.begin(), aliasedPath.end());
- AzFramework::StringFunc::Path::Normalize(aliasedPath);
-
- AZStd::string currentFolderSpecifier = AZStd::string::format(".%c", AZ_CORRECT_FILESYSTEM_SEPARATOR);
- if (AzFramework::StringFunc::StartsWith(aliasedPath, currentFolderSpecifier))
- {
- AzFramework::StringFunc::Strip(aliasedPath, currentFolderSpecifier.c_str(), false, true);
- }
-
- AZStd::string resolvedPath;
- char fullPathBuffer[AZ_MAX_PATH_LEN] = {};
- // if there is an alias already at the front of the path, resolve it, and try to make it relative to the
- // cache (@products@). If it can't, then error out.
- // This case handles the possibility of aliases existing in texture paths in materials that is still supported
- // by the legacy loading code, however it is not currently used, so the else path is always taken.
- if (aliasedPath[0] == '@')
- {
- if (!AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(aliasedPath.c_str(), fullPathBuffer, AZ_MAX_PATH_LEN))
- {
- AZ_Warning(s_materialBuilder, false, "Failed to resolve the alias in texture path %s. Please make sure all aliases are registered with the engine.", aliasedPath.c_str());
- return false;
- }
- resolvedPath = fullPathBuffer;
- AzFramework::StringFunc::Path::Normalize(resolvedPath);
- if (!AzFramework::StringFunc::Replace(resolvedPath, AZ::IO::FileIOBase::GetDirectInstance()->GetAlias("@products@"), ""))
- {
- AZ_Warning(s_materialBuilder, false, "Failed to resolve aliased texture path %s to be relative to the asset cache. Please make sure this alias resolves to a path within the asset cache.", aliasedPath.c_str());
- return false;
- }
- }
- else
- {
- resolvedPath = AZStd::move(aliasedPath);
- }
-
- // AP deferred path resolution requires UNIX separators and no leading separators, so clean up and convert here
- if (AzFramework::StringFunc::StartsWith(resolvedPath, AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING))
- {
- AzFramework::StringFunc::Strip(resolvedPath, AZ_CORRECT_FILESYSTEM_SEPARATOR, false, true);
- }
- AzFramework::StringFunc::Replace(resolvedPath, AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING, "/");
-
- outPath = AZStd::move(resolvedPath);
- return true;
- }
-
- }
-
- BuilderPluginComponent::BuilderPluginComponent()
- {
- }
-
- BuilderPluginComponent::~BuilderPluginComponent()
- {
- }
-
- void BuilderPluginComponent::Init()
- {
- }
-
- void BuilderPluginComponent::Activate()
- {
- // Register material builder
- AssetBuilderSDK::AssetBuilderDesc builderDescriptor;
- builderDescriptor.m_name = "MaterialBuilderWorker";
- builderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.mtl", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
- builderDescriptor.m_busId = MaterialBuilderWorker::GetUUID();
- builderDescriptor.m_version = 5;
- builderDescriptor.m_createJobFunction = AZStd::bind(&MaterialBuilderWorker::CreateJobs, &m_materialBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
- builderDescriptor.m_processJobFunction = AZStd::bind(&MaterialBuilderWorker::ProcessJob, &m_materialBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
-
- // (optimization) this builder does not emit source dependencies:
- builderDescriptor.m_flags |= AssetBuilderSDK::AssetBuilderDesc::BF_EmitsNoDependencies;
-
- m_materialBuilder.BusConnect(builderDescriptor.m_busId);
-
- EBUS_EVENT(AssetBuilderSDK::AssetBuilderBus, RegisterBuilderInformation, builderDescriptor);
- }
-
- void BuilderPluginComponent::Deactivate()
- {
- m_materialBuilder.BusDisconnect();
- }
-
- void BuilderPluginComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context)
- {
- if (AZ::SerializeContext* serializeContext = azrtti_cast(context))
- {
- serializeContext->Class()
- ->Version(1)
- ->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector({ AssetBuilderSDK::ComponentTags::AssetBuilder }));
- }
- }
-
- MaterialBuilderWorker::MaterialBuilderWorker()
- {
- }
- MaterialBuilderWorker::~MaterialBuilderWorker()
- {
- }
-
- void MaterialBuilderWorker::ShutDown()
- {
- // This will be called on a different thread than the process job thread
- m_isShuttingDown = true;
- }
-
- // This happens early on in the file scanning pass.
- // This function should always create the same jobs and not do any checking whether the job is up to date.
- void MaterialBuilderWorker::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response)
- {
- if (m_isShuttingDown)
- {
- response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown;
- return;
- }
-
- for (const AssetBuilderSDK::PlatformInfo& info : request.m_enabledPlatforms)
- {
- AssetBuilderSDK::JobDescriptor descriptor;
- descriptor.m_jobKey = "Material Builder Job";
- descriptor.SetPlatformIdentifier(info.m_identifier.c_str());
- descriptor.m_priority = 8; // meshes are more important (at 10) but mats are still pretty important.
- response.m_createJobOutputs.push_back(descriptor);
- }
-
- response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
- }
-
- // The request will contain the CreateJobResponse you constructed earlier, including any keys and
- // values you placed into the hash table
- void MaterialBuilderWorker::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response)
- {
- AZ_TracePrintf(AssetBuilderSDK::InfoWindow, "Starting Job.\n");
- AZStd::string fileName;
- AzFramework::StringFunc::Path::GetFullFileName(request.m_fullPath.c_str(), fileName);
- AZStd::string destPath;
-
- // Do all work inside the tempDirPath.
- AzFramework::StringFunc::Path::ConstructFull(request.m_tempDirPath.c_str(), fileName.c_str(), destPath, true);
-
- AZ::IO::LocalFileIO fileIO;
- if (!m_isShuttingDown && fileIO.Copy(request.m_fullPath.c_str(), destPath.c_str()) == AZ::IO::ResultCode::Success)
- {
- // Push assets back into the response's product list
- // Assets you created in your temp path can be specified using paths relative to the temp path
- // since that is assumed where you're writing stuff.
- AZStd::string relPath = destPath;
- AssetBuilderSDK::ProductPathDependencySet dependencyPaths;
- response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
- AssetBuilderSDK::JobProduct jobProduct(fileName);
-
- bool dependencyResult = GatherProductDependencies(request.m_fullPath, dependencyPaths);
- if (dependencyResult)
- {
- jobProduct.m_pathDependencies = AZStd::move(dependencyPaths);
- jobProduct.m_dependenciesHandled = true; // We've output the dependencies immediately above so it's OK to tell the AP we've handled dependencies
- }
- else
- {
- AZ_Error(s_materialBuilder, false, "Dependency gathering for %s failed.", request.m_fullPath.c_str());
- }
- response.m_outputProducts.push_back(jobProduct);
- }
- else
- {
- if (m_isShuttingDown)
- {
- AZ_TracePrintf(AssetBuilderSDK::ErrorWindow, "Cancelled job %s because shutdown was requested.\n", request.m_fullPath.c_str());
- response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Cancelled;
- }
- else
- {
- AZ_TracePrintf(AssetBuilderSDK::ErrorWindow, "Error during processing job %s.\n", request.m_fullPath.c_str());
- response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
- }
- }
- }
-
- bool MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial(const AZStd::string& path, AZStd::vector& resolvedPaths)
- {
- if (!AZ::IO::SystemFile::Exists(path.c_str()))
- {
- AZ_Error(s_materialBuilder, false, "Failed to find material at path %s. Please make sure this material exists on disk.", path.c_str());
- return false;
- }
-
- uint64_t fileSize = AZ::IO::SystemFile::Length(path.c_str());
- if (fileSize == 0)
- {
- AZ_Error(s_materialBuilder, false, "Material at path %s is an empty file. Please make sure this material was properly saved to disk.", path.c_str());
- return false;
- }
-
- AZStd::vector buffer(fileSize + 1);
- buffer[fileSize] = 0;
- if (!AZ::IO::SystemFile::Read(path.c_str(), buffer.data()))
- {
- AZ_Error(s_materialBuilder, false, "Failed to read material at path %s. Please make sure the file is not open or being edited by another program.", path.c_str());
- return false;
- }
-
- AZ::rapidxml::xml_document* xmlDoc = azcreate(AZ::rapidxml::xml_document, (), AZ::SystemAllocator, "Mtl builder temp XML Reader");
- if (!xmlDoc->parse(buffer.data()))
- {
- azdestroy(xmlDoc, AZ::SystemAllocator, AZ::rapidxml::xml_document);
- AZ_Error(s_materialBuilder, false, "Failed to parse material at path %s into XML. Please make sure that the material was properly saved to disk.", path.c_str());
- return false;
- }
-
- // if the first node in this file isn't a material, this must not actually be a material so it can't have deps
- AZ::rapidxml::xml_node* rootNode = xmlDoc->first_node(Internal::g_nodeNameMaterial);
- if (!rootNode)
- {
- azdestroy(xmlDoc, AZ::SystemAllocator, AZ::rapidxml::xml_document);
- AZ_Error(s_materialBuilder, false, "Failed to find root material node for material at path %s. Please make sure that the material was properly saved to disk.", path.c_str());
- return false;
- }
-
- AZStd::vector texturePaths;
- // gather all textures in the material file
- AZ::Outcome texturePathsResult = Internal::GetTexturePathsFromMaterial(rootNode, texturePaths);
- if (!texturePathsResult.IsSuccess())
- {
- azdestroy(xmlDoc, AZ::SystemAllocator, AZ::rapidxml::xml_document);
- AZ_Error(s_materialBuilder, false, "Failed to gather dependencies for %s as the material file is malformed. %s", path.c_str(), texturePathsResult.GetError().c_str());
- return false;
- }
- else if (!texturePathsResult.GetValue().empty())
- {
- AZ_Warning(s_materialBuilder, false, "Some nodes in material %s could not be read as the material is malformed. %s. Some dependencies might not be reported correctly. Please make sure that the material was properly saved to disk.", path.c_str(), texturePathsResult.GetValue().c_str());
- }
- azdestroy(xmlDoc, AZ::SystemAllocator, AZ::rapidxml::xml_document);
-
- // fail this if there are absolute paths.
- for (const AZStd::string& texPath : texturePaths)
- {
- if (AZ::IO::PathView(texPath).IsAbsolute())
- {
- AZ_Warning(s_materialBuilder, false, "Skipping resolving of texture path %s in material %s as the texture path is an absolute path. Please update the texture path to be relative to the asset cache.", texPath.c_str(), path.c_str());
- texturePaths.erase(AZStd::find(texturePaths.begin(), texturePaths.end(), texPath));
- }
- }
-
- // for each path in the array, split any texture animation entry up into the individual files and add each to the list.
- for (const AZStd::string& texPath : texturePaths)
- {
- if (texPath.find('#') != AZStd::string::npos)
- {
- AZStd::vector actualTexturePaths;
- AZ::Outcome parseTextureSequenceResult = Internal::GetAllTexturesInTextureSequence(texPath, actualTexturePaths);
- if (parseTextureSequenceResult.IsSuccess())
- {
- texturePaths.erase(AZStd::find(texturePaths.begin(), texturePaths.end(), texPath));
- texturePaths.insert(texturePaths.end(), actualTexturePaths.begin(), actualTexturePaths.end());
- }
- else
- {
- texturePaths.erase(AZStd::find(texturePaths.begin(), texturePaths.end(), texPath));
- AZ_Warning(s_materialBuilder, false, "Failed to parse texture sequence %s when trying to gather dependencies for %s. %s Please make sure the texture sequence path is formatted correctly. Registering dependencies for the texture sequence will be skipped.", texPath.c_str(), path.c_str(), parseTextureSequenceResult.GetError().c_str());
- }
- }
- }
-
- // for each texture in the file
- for (const AZStd::string& texPath : texturePaths)
- {
- // if the texture path starts with a '$' then it is a special runtime defined texture, so it it doesn't have
- // an actual asset on disk to depend on. If the texture path doesn't have an extension, then it is a texture
- // that is determined at runtime (such as 'nearest_cubemap'), so also ignore those, as other things pull in
- // those dependencies.
- if (AzFramework::StringFunc::StartsWith(texPath, "$") || !AzFramework::StringFunc::Path::HasExtension(texPath.c_str()))
- {
- continue;
- }
-
- // resolve the path in the file.
- AZStd::string resolvedPath;
- if (!Internal::ResolveMaterialTexturePath(texPath, resolvedPath))
- {
- AZ_Warning(s_materialBuilder, false, "Failed to resolve texture path %s to a product path when gathering dependencies for %s. Registering dependencies on this texture path will be skipped.", texPath.c_str(), path.c_str());
- continue;
- }
-
- resolvedPaths.emplace_back(AZStd::move(resolvedPath));
- }
-
- return true;
- }
-
- bool MaterialBuilderWorker::PopulateProductDependencyList(AZStd::vector& resolvedPaths, AssetBuilderSDK::ProductPathDependencySet& dependencies)
- {
- for (const AZStd::string& texturePath : resolvedPaths)
- {
- if (texturePath.empty())
- {
- AZ_Warning(s_materialBuilder, false, "Resolved path is empty.\n");
- return false;
- }
-
- dependencies.emplace(texturePath, AssetBuilderSDK::ProductPathDependencyType::ProductFile);
- }
- return true;
- }
-
- bool MaterialBuilderWorker::GatherProductDependencies(const AZStd::string& path, AssetBuilderSDK::ProductPathDependencySet& dependencies)
- {
- AZStd::vector resolvedTexturePaths;
- if (!GetResolvedTexturePathsFromMaterial(path, resolvedTexturePaths))
- {
- return false;
- }
-
- if (!PopulateProductDependencyList(resolvedTexturePaths, dependencies))
- {
- AZ_Warning(s_materialBuilder, false, "Failed to populate dependency list for material %s with possible variants for textures.", path.c_str());
- }
-
- return true;
- }
-
- AZ::Uuid MaterialBuilderWorker::GetUUID()
- {
- return AZ::Uuid::CreateString("{258D34AC-12F8-4196-B535-3206D8E7287B}");
- }
-}
diff --git a/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.h b/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.h
deleted file mode 100644
index a7813cf0bd..0000000000
--- a/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#pragma once
-
-#include
-#include
-#include
-
-namespace MaterialBuilder
-{
- //! Material builder is responsible for building material files
- class MaterialBuilderWorker
- : public AssetBuilderSDK::AssetBuilderCommandBus::Handler
- {
- public:
- MaterialBuilderWorker();
- ~MaterialBuilderWorker();
-
- //! Asset Builder Callback Functions
- void CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response);
- void ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response);
-
- //!AssetBuilderSDK::AssetBuilderCommandBus interface
- void ShutDown() override;
-
- //! Returns the UUID for this builder
- static AZ::Uuid GetUUID();
-
- bool GetResolvedTexturePathsFromMaterial(const AZStd::string& path, AZStd::vector& resolvedPaths);
- bool PopulateProductDependencyList(AZStd::vector& resolvedPaths, AssetBuilderSDK::ProductPathDependencySet& dependencies);
-
- private:
- bool GatherProductDependencies(const AZStd::string& path, AssetBuilderSDK::ProductPathDependencySet& dependencies);
-
- bool m_isShuttingDown = false;
- };
-
- class BuilderPluginComponent
- : public AZ::Component
- {
- public:
- AZ_COMPONENT(BuilderPluginComponent, "{4D1A4B0C-54CE-4397-B8AE-ADD08898C2CD}")
- static void Reflect(AZ::ReflectContext* context);
-
- BuilderPluginComponent();
-
- //////////////////////////////////////////////////////////////////////////
- // AZ::Component
- virtual void Init(); // create objects, allocate memory and initialize yourself without reaching out to the outside world
- virtual void Activate(); // reach out to the outside world and connect up to what you need to, register things, etc.
- virtual void Deactivate(); // unregister things, disconnect from the outside world
- //////////////////////////////////////////////////////////////////////////
-
- virtual ~BuilderPluginComponent(); // free memory an uninitialize yourself.
-
- private:
- MaterialBuilderWorker m_materialBuilder;
- };
-}
diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp
index 027d19fdef..ad90c16f43 100644
--- a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp
+++ b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp
@@ -38,9 +38,6 @@
#include "Geometry/GeometrySystemComponent.h"
#include
-// Unhandled asset types
-// Material
-#include "Unhandled/Material/MaterialAssetTypeInfo.h"
// Other
#include "Unhandled/Other/AudioAssetTypeInfo.h"
#include "Unhandled/Other/CharacterPhysicsAssetTypeInfo.h"
@@ -353,8 +350,6 @@ namespace LmbrCentral
// Add asset types and extensions to AssetCatalog. Uses "AssetCatalogService".
if (auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler(); assetCatalog)
{
- assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid());
- assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid());
assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid());
assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid());
@@ -364,24 +359,12 @@ namespace LmbrCentral
assetCatalog->AddExtension("dds");
assetCatalog->AddExtension("caf");
assetCatalog->AddExtension("xml");
- assetCatalog->AddExtension("mtl");
- assetCatalog->AddExtension("dccmtl");
assetCatalog->AddExtension("sprite");
assetCatalog->AddExtension("cax");
}
AZ::Data::AssetManagerNotificationBus::Handler::BusConnect();
-
- // Register unhandled asset type info
- // Material
- auto materialAssetTypeInfo = aznew MaterialAssetTypeInfo();
- materialAssetTypeInfo->Register();
- m_unhandledAssetInfo.emplace_back(materialAssetTypeInfo);
- // DCC Material
- auto dccMaterialAssetTypeInfo = aznew DccMaterialAssetTypeInfo();
- dccMaterialAssetTypeInfo->Register();
- m_unhandledAssetInfo.emplace_back(dccMaterialAssetTypeInfo);
// Other
auto audioAssetTypeInfo = aznew AudioAssetTypeInfo();
audioAssetTypeInfo->Register();
diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp
index 511bf98582..61b8c8f73d 100644
--- a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp
+++ b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp
@@ -43,7 +43,6 @@
#include
#include
#include
-#include
#include
#include
#include "Builders/CopyDependencyBuilder/CopyDependencyBuilderComponent.h"
@@ -84,7 +83,6 @@ namespace LmbrCentral
CopyDependencyBuilder::CopyDependencyBuilderComponent::CreateDescriptor(),
DependencyBuilder::DependencyBuilderComponent::CreateDescriptor(),
LevelBuilder::LevelBuilderComponent::CreateDescriptor(),
- MaterialBuilder::BuilderPluginComponent::CreateDescriptor(),
SliceBuilder::BuilderPluginComponent::CreateDescriptor(),
TranslationBuilder::BuilderPluginComponent::CreateDescriptor(),
LuaBuilder::BuilderPluginComponent::CreateDescriptor(),
diff --git a/Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.cpp b/Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.cpp
deleted file mode 100644
index 24bc43740d..0000000000
--- a/Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#include "MaterialAssetTypeInfo.h"
-
-#include
-
-namespace LmbrCentral
-{
- // MaterialAssetTypeInfo
-
- MaterialAssetTypeInfo::~MaterialAssetTypeInfo()
- {
- Unregister();
- }
-
- void MaterialAssetTypeInfo::Register()
- {
- AZ::AssetTypeInfoBus::Handler::BusConnect(AZ::AzTypeInfo::Uuid());
- }
-
- void MaterialAssetTypeInfo::Unregister()
- {
- AZ::AssetTypeInfoBus::Handler::BusDisconnect(AZ::AzTypeInfo::Uuid());
- }
-
- AZ::Data::AssetType MaterialAssetTypeInfo::GetAssetType() const
- {
- return AZ::AzTypeInfo::Uuid();
- }
-
- const char* MaterialAssetTypeInfo::GetAssetTypeDisplayName() const
- {
- return "Material";
- }
-
- const char* MaterialAssetTypeInfo::GetGroup() const
- {
- return "Material";
- }
-
- const char* MaterialAssetTypeInfo::GetBrowserIcon() const
- {
- return "Icons/Components/Decal.svg";
- }
-
- // DccMaterialAssetTypeInfo
-
- DccMaterialAssetTypeInfo::~DccMaterialAssetTypeInfo()
- {
- Unregister();
- }
-
- void DccMaterialAssetTypeInfo::Register()
- {
- AZ::AssetTypeInfoBus::Handler::BusConnect(AZ::AzTypeInfo::Uuid());
- }
-
- void DccMaterialAssetTypeInfo::Unregister()
- {
- AZ::AssetTypeInfoBus::Handler::BusDisconnect(AZ::AzTypeInfo::Uuid());
- }
-
- AZ::Data::AssetType DccMaterialAssetTypeInfo::GetAssetType() const
- {
- return AZ::AzTypeInfo::Uuid();
- }
-
- const char* DccMaterialAssetTypeInfo::GetAssetTypeDisplayName() const
- {
- return "DccMaterial";
- }
-
- const char* DccMaterialAssetTypeInfo::GetGroup() const
- {
- return "DccMaterial";
- }
-
- const char* DccMaterialAssetTypeInfo::GetBrowserIcon() const
- {
- return "Icons/Components/Decal.svg";
- }
-} // namespace LmbrCentral
diff --git a/Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.h b/Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.h
deleted file mode 100644
index 2eafa31b41..0000000000
--- a/Gems/LmbrCentral/Code/Source/Unhandled/Material/MaterialAssetTypeInfo.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include
-
-namespace LmbrCentral
-{
- class MaterialAssetTypeInfo
- : public AZ::AssetTypeInfoBus::Handler
- {
- public:
-
- AZ_CLASS_ALLOCATOR(MaterialAssetTypeInfo, AZ::SystemAllocator, 0);
-
- ~MaterialAssetTypeInfo() override;
-
- //////////////////////////////////////////////////////////////////////////////////////////////
- // AZ::AssetTypeInfoBus::Handler
- AZ::Data::AssetType GetAssetType() const override;
- const char* GetAssetTypeDisplayName() const override;
- const char* GetGroup() const override;
- const char* GetBrowserIcon() const override;
- //////////////////////////////////////////////////////////////////////////////////////////////
-
- void Register();
- void Unregister();
- };
-
- class DccMaterialAssetTypeInfo
- : public AZ::AssetTypeInfoBus::Handler
- {
- public:
-
- AZ_CLASS_ALLOCATOR(DccMaterialAssetTypeInfo, AZ::SystemAllocator, 0);
-
- ~DccMaterialAssetTypeInfo() override;
-
- //////////////////////////////////////////////////////////////////////////////////////////////
- // AZ::AssetTypeInfoBus::Handler
- AZ::Data::AssetType GetAssetType() const override;
- const char* GetAssetTypeDisplayName() const override;
- const char* GetGroup() const override;
- const char* GetBrowserIcon() const override;
- //////////////////////////////////////////////////////////////////////////////////////////////
-
- void Register();
- void Unregister();
- };
-} // namespace LmbrCentral
diff --git a/Gems/LmbrCentral/Code/Tests/Builders/MaterialBuilderTests.cpp b/Gems/LmbrCentral/Code/Tests/Builders/MaterialBuilderTests.cpp
deleted file mode 100644
index 3786ef7565..0000000000
--- a/Gems/LmbrCentral/Code/Tests/Builders/MaterialBuilderTests.cpp
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-namespace UnitTest
-{
- using namespace MaterialBuilder;
- using namespace AZ;
-
- class MaterialBuilderTests
- : public UnitTest::AllocatorsTestFixture
- , public UnitTest::TraceBusRedirector
- {
- protected:
- void SetUp() override
- {
- UnitTest::AllocatorsTestFixture::SetUp();
-
- m_app.reset(aznew AzToolsFramework::ToolsApplication);
- m_app->Start(AZ::ComponentApplication::Descriptor());
- // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
- // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
- // in the unit tests.
- AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
- AZ::Debug::TraceMessageBus::Handler::BusConnect();
-
- const AZStd::string engineRoot = AZ::Test::GetEngineRootPath();
- AZ::IO::FileIOBase::GetInstance()->SetAlias("@engroot@", engineRoot.c_str());
-
- AZ::IO::Path assetRoot(AZ::Utils::GetProjectPath());
- assetRoot /= "Cache";
- AZ::IO::FileIOBase::GetInstance()->SetAlias("@products@", assetRoot.c_str());
- }
-
- void TearDown() override
- {
- AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
- m_app->Stop();
- m_app.reset();
-
- UnitTest::AllocatorsTestFixture::TearDown();
- }
-
- AZStd::string GetTestFileAliasedPath(AZStd::string_view fileName)
- {
- constexpr char testFileFolder[] = "@engroot@/Gems/LmbrCentral/Code/Tests/Materials/";
- return AZStd::string::format("%s%.*s", testFileFolder, aznumeric_cast(fileName.size()), fileName.data());
- }
-
- AZStd::string GetTestFileFullPath(AZStd::string_view fileName)
- {
- AZStd::string aliasedPath = GetTestFileAliasedPath(fileName);
- char resolvedPath[AZ_MAX_PATH_LEN];
- AZ::IO::FileIOBase::GetInstance()->ResolvePath(aliasedPath.c_str(), resolvedPath, AZ_MAX_PATH_LEN);
- return AZStd::string(resolvedPath);
- }
-
- void TestFailureCase(AZStd::string_view fileName, [[maybe_unused]] int expectedErrorCount)
- {
- MaterialBuilderWorker worker;
- AZStd::vector resolvedPaths;
-
- AZStd::string absoluteMatPath = GetTestFileFullPath(fileName);
-
- AZ_TEST_START_ASSERTTEST;
- ASSERT_FALSE(worker.GetResolvedTexturePathsFromMaterial(absoluteMatPath, resolvedPaths));
- AZ_TEST_STOP_ASSERTTEST(expectedErrorCount * 2); // The assert tests double count AZ errors, so just multiply expected count by 2
- ASSERT_EQ(resolvedPaths.size(), 0);
- }
-
- void TestSuccessCase(AZStd::string_view fileName, AZStd::vector& expectedTextures)
- {
- MaterialBuilderWorker worker;
- AZStd::vector resolvedPaths;
- size_t texturesInMaterialFile = expectedTextures.size();
-
- AZStd::string absoluteMatPath = GetTestFileFullPath(fileName);
- ASSERT_TRUE(worker.GetResolvedTexturePathsFromMaterial(absoluteMatPath, resolvedPaths));
- ASSERT_EQ(resolvedPaths.size(), texturesInMaterialFile);
- if (texturesInMaterialFile > 0)
- {
- ASSERT_THAT(resolvedPaths, testing::ElementsAreArray(expectedTextures));
-
- AssetBuilderSDK::ProductPathDependencySet dependencies;
- ASSERT_TRUE(worker.PopulateProductDependencyList(resolvedPaths, dependencies));
- ASSERT_EQ(dependencies.size(), texturesInMaterialFile);
- }
- }
-
- void TestSuccessCase(AZStd::string_view fileName, const char* expectedTexture)
- {
- AZStd::vector expectedTextures;
- expectedTextures.push_back(expectedTexture);
- TestSuccessCase(fileName, expectedTextures);
- }
-
- void TestSuccessCaseNoDependencies(AZStd::string_view fileName)
- {
- AZStd::vector expectedTextures;
- TestSuccessCase(fileName, expectedTextures);
- }
-
- AZStd::unique_ptr m_app;
- };
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_EmptyFile_ExpectFailure)
- {
- // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial, when checking for the size of the file.
- TestFailureCase("test_mat1.mtl", 1);
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_NoChildren_ExpectFailure)
- {
- // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial after calling
- // Internal::GetTexturePathsFromMaterial, which should return an AZ::Failure when both a Textures node and a
- // SubMaterials node are not found. No other AZ_Errors should be generated.
- TestFailureCase("test_mat2.mtl", 1);
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyTexturesNode_NoDependencies)
- {
- TestSuccessCaseNoDependencies("test_mat3.mtl");
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptySubMaterialNode_ExpectFailure)
- {
- // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial after calling
- // Internal::GetTexturePathsFromMaterial, which should return an AZ::Failure when a SubMaterials node is present,
- // but has no children Material node. No other AZ_Errors should be generated.
- TestFailureCase("test_mat4.mtl", 1);
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyTextureNode_NoDependencies)
- {
- TestSuccessCaseNoDependencies("test_mat5.mtl");
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyMaterialInSubMaterial_ExpectFailure)
- {
- // Should fail in MaterialBuilderWorker::GetResolvedTexturePathsFromMaterial after calling
- // Internal::GetTexturePathsFromMaterial, which should return an AZ::Failure when a SubMaterials node is present,
- // but a child Material node has no child Textures node and no child SubMaterials node. No other AZ_Errors should
- // be generated.
- TestFailureCase("test_mat6.mtl", 1);
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_EmptyTextureNodeInSubMaterial_NoDependencies)
- {
- TestSuccessCaseNoDependencies("test_mat7.mtl");
- }
-
-#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS // The following test file 'test_mat8.mtl' has a windows-specific absolute path, so this test is only valid on windows
- TEST_F(MaterialBuilderTests, MaterialBuilder_TextureAbsolutePath_NoDependencies)
- {
- TestSuccessCaseNoDependencies("test_mat8.mtl");
- }
-#endif
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_TextureRuntimeAlias_NoDependencies)
- {
- TestSuccessCaseNoDependencies("test_mat9.mtl");
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_TextureRuntimeTexture_NoDependencies)
- {
- TestSuccessCaseNoDependencies("test_mat10.mtl");
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialSingleTexture_ValidSourceFormat)
- {
- // texture referenced is textures/natural/terrain/am_floor_tile_ddn.png
- const char* expectedPath = "textures/natural/terrain/am_floor_tile_ddn.dds";
- TestSuccessCase("test_mat11.mtl", expectedPath);
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialSingleTexture_ValidProductFormat)
- {
- // texture referenced is textures/natural/terrain/am_floor_tile_ddn.dds
- const char* expectedPath = "textures/natural/terrain/am_floor_tile_ddn.dds";
- TestSuccessCase("test_mat12.mtl", expectedPath);
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialSingleTexture_InvalidSourceFormat_NoDependenices)
- {
- // texture referenced is textures/natural/terrain/am_floor_tile_ddn.txt
- TestSuccessCaseNoDependencies("test_mat13.mtl");
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_TextureAnimSequence)
- {
- AZStd::vector expectedPaths = {
- "path/to/my/textures/test_anim_sequence_01_texture000.dds",
- "path/to/my/textures/test_anim_sequence_01_texture001.dds",
- "path/to/my/textures/test_anim_sequence_01_texture002.dds",
- "path/to/my/textures/test_anim_sequence_01_texture003.dds",
- "path/to/my/textures/test_anim_sequence_01_texture004.dds",
- "path/to/my/textures/test_anim_sequence_01_texture005.dds"
- };
- TestSuccessCase("test_mat14.mtl", expectedPaths);
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialMultipleTexture)
- {
- AZStd::vector expectedPaths = {
- "engineassets/textures/hex.dds",
- "engineassets/textures/hex_ddn.dds"
- };
- TestSuccessCase("test_mat15.mtl", expectedPaths);
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_MalformedMaterial_MultipleTextures_OneEmptyTexture)
- {
- TestSuccessCase("test_mat16.mtl", "engineassets/textures/hex_ddn.dds");
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_SingleMaterialMultipleTexture_ResolveLeadingSeparatorsAndAliases)
- {
- AZStd::vector expectedPaths = {
- "engineassets/textures/hex.dds", // resolved from "/engineassets/textures/hex.dds"
- "engineassets/textures/hex_ddn.dds", // resolved from "./engineassets/textures/hex_ddn.dds"
- "engineassets/textures/hex_spec.dds" // resolved from "@products@/engineassets/textures/hex_spec.dds"
- };
- TestSuccessCase("test_mat17.mtl", expectedPaths);
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_SubMaterialSingleTexture)
- {
- AZStd::vector expectedPaths = {
- "engineassets/textures/scratch.dds",
- "engineassets/textures/perlinnoise2d.dds"
- };
- TestSuccessCase("test_mat18.mtl", expectedPaths);
- }
-
- TEST_F(MaterialBuilderTests, MaterialBuilder_SubMaterialMultipleTexture)
- {
- AZStd::vector expectedPaths = {
- "engineassets/textures/scratch.dds",
- "engineassets/textures/scratch_ddn.dds",
- "engineassets/textures/perlinnoise2d.dds",
- "engineassets/textures/perlinnoisenormal_ddn.dds"
- };
- TestSuccessCase("test_mat19.mtl", expectedPaths);
- }
-}
diff --git a/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake
index 5c77888922..aea2f493c7 100644
--- a/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake
+++ b/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake
@@ -116,8 +116,6 @@ set(FILES
Source/Builders/LevelBuilder/LevelBuilderComponent.h
Source/Builders/LevelBuilder/LevelBuilderWorker.cpp
Source/Builders/LevelBuilder/LevelBuilderWorker.h
- Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp
- Source/Builders/MaterialBuilder/MaterialBuilderComponent.h
Source/Builders/SliceBuilder/SliceBuilderComponent.cpp
Source/Builders/SliceBuilder/SliceBuilderComponent.h
Source/Builders/SliceBuilder/SliceBuilderWorker.cpp
diff --git a/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake
index 0f0cf484d1..afba79e566 100644
--- a/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake
+++ b/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake
@@ -21,7 +21,6 @@ set(FILES
Tests/Builders/CopyDependencyBuilderTest.cpp
Tests/Builders/SliceBuilderTests.cpp
Tests/Builders/LevelBuilderTest.cpp
- Tests/Builders/MaterialBuilderTests.cpp
Tests/Builders/LuaBuilderTests.cpp
Tests/Builders/SeedBuilderTests.cpp
Source/LmbrCentral.cpp
diff --git a/Gems/LmbrCentral/Code/lmbrcentral_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_files.cmake
index 18412e2a38..20a366b5f7 100644
--- a/Gems/LmbrCentral/Code/lmbrcentral_files.cmake
+++ b/Gems/LmbrCentral/Code/lmbrcentral_files.cmake
@@ -145,8 +145,6 @@ set(FILES
Source/Shape/ShapeComponentConverters.inl
Source/Shape/ShapeGeometryUtil.h
Source/Shape/ShapeGeometryUtil.cpp
- Source/Unhandled/Material/MaterialAssetTypeInfo.cpp
- Source/Unhandled/Material/MaterialAssetTypeInfo.h
Source/Unhandled/Other/AudioAssetTypeInfo.cpp
Source/Unhandled/Other/AudioAssetTypeInfo.h
Source/Unhandled/Other/CharacterPhysicsAssetTypeInfo.cpp
diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja
index e9bc21875b..d0b77159f8 100644
--- a/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja
+++ b/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja
@@ -308,13 +308,21 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Prop
{% endmacro %}
{#
+#}
+{% macro PrintRpcParameters(printPrefix, paramDefines) %}
+{% if paramDefines|count > 0 %}
+{{ printPrefix }}{{ ', '.join(paramDefines) }}
+{% endif %}
+{% endmacro %}
+{#
+
#}
{% macro DefineRpcInvocation(Component, ClassName, Property, InvokeFrom, HandleOn) %}
{% set paramNames = [] %}
{% set paramTypes = [] %}
{% set paramDefines = [] %}
{{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }}
-void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramDefines) }})
+void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ PrintRpcParameters('', paramDefines) }})
{
constexpr Multiplayer::RpcIndex rpcId = static_cast({{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ UpperFirst(Property.attrib['Name']) }});
{% if Property.attrib['IsReliable']|booleanTrue %}
@@ -358,7 +366,7 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(par
{% set paramTypes = [] %}
{% set paramDefines = [] %}
{{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }}
- ->Method("{{ UpperFirst(Property.attrib['Name']) }}", []({{ ClassName }}* self, {{ ', '.join(paramDefines) }}) {
+ ->Method("{{ UpperFirst(Property.attrib['Name']) }}", []({{ ClassName }}* self{{ PrintRpcParameters(', ', paramDefines) }}) {
{% if (InvokeFrom == 'Server') %}
self->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }});
{% elif (InvokeFrom == 'Authority') or (InvokeFrom == 'Autonomous') %}
@@ -372,7 +380,7 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(par
}
{% endif %}
})
- ->Method("{{ UpperFirst(Property.attrib['Name']) }}ByEntityId", [](AZ::EntityId id, {{ ', '.join(paramDefines) }}) {
+ ->Method("{{ UpperFirst(Property.attrib['Name']) }}ByEntityId", [](AZ::EntityId id{{ PrintRpcParameters(', ', paramDefines) }}) {
AZ::Entity* entity = AZ::Interface::Get()->FindEntity(id);
if (!entity)
@@ -497,9 +505,9 @@ case {{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ Upp
if (m_controller)
{
AZ_Assert(GetNetBindComponent()->GetNetEntityRole() == Multiplayer::NetEntityRole::Authority, "Entity proxy does not have authority");
- m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection, {{ ', '.join(rpcParamList) }});
+ m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection{{ PrintRpcParameters(', ', rpcParamList) }});
{% if (Property.attrib['GenerateEventBindings']|booleanTrue == true) %}
- m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event().Signal({{ ', '.join(rpcParamList) }});
+ m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event().Signal({{ PrintRpcParameters('', rpcParamList) }});
{% endif %}
}
else // Note that this rpc is marked reliable, trigger the appropriate rpc event so it can be forwarded
@@ -513,15 +521,15 @@ case {{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ Upp
if (m_controller)
{
AZ_Assert(GetNetBindComponent()->GetNetEntityRole() == Multiplayer::NetEntityRole::Autonomous, "Entity proxy does not have autonomy");
- m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection, {{ ', '.join(rpcParamList) }});
+ m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection{{ PrintRpcParameters(', ', rpcParamList) }});
{% if Property.attrib['GenerateEventBindings']|booleanTrue == true %}
- m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event().Signal({{ ', '.join(rpcParamList) }});
+ m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event().Signal({{ PrintRpcParameters('', rpcParamList) }});
{% endif %}
}
{% elif HandleOn == 'Client' %}
- Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection, {{ ', '.join(rpcParamList) }});
+ Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection{{ PrintRpcParameters(', ', rpcParamList) }});
{% if Property.attrib['GenerateEventBindings']|booleanTrue == true %}
- m_{{ UpperFirst(Property.attrib['Name']) }}Event.Signal({{ ', '.join(rpcParamList) }});
+ m_{{ UpperFirst(Property.attrib['Name']) }}Event.Signal({{ PrintRpcParameters('', rpcParamList) }});
{% endif %}
{% endif %}
}
diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp
index ce95e27db3..08e31a89f0 100644
--- a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp
+++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp
@@ -307,7 +307,16 @@ namespace PhysX
AZStd::vector JointsComponentMode::PopulateViewportUiImpl()
{
- return AZStd::vector(m_modeSelectionClusterIds.begin(), m_modeSelectionClusterIds.end());
+ AZStd::vector ids;
+ ids.reserve(m_modeSelectionClusterIds.size());
+ for (auto clusterid : m_modeSelectionClusterIds)
+ {
+ if (clusterid != AzToolsFramework::ViewportUi::InvalidClusterId)
+ {
+ ids.emplace_back(clusterid);
+ }
+ }
+ return ids;
}
void JointsComponentMode::SetCurrentMode(JointsComponentModeCommon::SubComponentModes::ModeType newMode, ButtonData& buttonData)
@@ -353,31 +362,64 @@ namespace PhysX
void JointsComponentMode::SetupSubModes(const AZ::EntityComponentIdPair& entityComponentIdPair)
{
- //create the 3 cluster groups
- for (auto& clusterId : m_modeSelectionClusterIds)
- {
- AzToolsFramework::ViewportUi::ViewportUiRequestBus::EventResult(
- clusterId, AzToolsFramework::ViewportUi::DefaultViewportId,
- &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateCluster,
- AzToolsFramework::ViewportUi::Alignment::TopLeft);
- }
-
//retrieve the enabled sub components from the entity
AZStd::vector subModesState;
EditorJointRequestBus::EventResult(subModesState, entityComponentIdPair, &EditorJointRequests::GetSubComponentModesState);
+ //group 1 is always available so create it
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::EventResult(
+ m_modeSelectionClusterIds[static_cast(ClusterGroups::Group1)], AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateCluster, AzToolsFramework::ViewportUi::Alignment::TopLeft);
+
+ //check if groups 2 and/or 3 need to be created
+ for (auto [modeType, _] : subModesState)
+ {
+ const AzToolsFramework::ViewportUi::ClusterId group2Id = GetClusterId(ClusterGroups::Group2);
+ const AzToolsFramework::ViewportUi::ClusterId group3Id = GetClusterId(ClusterGroups::Group3);
+ switch (modeType)
+ {
+ case JointsComponentModeCommon::SubComponentModes::ModeType::Damping:
+ case JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness:
+ case JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits:
+ case JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits:
+ {
+ if (group2Id == AzToolsFramework::ViewportUi::InvalidClusterId)
+ {
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::EventResult(
+ m_modeSelectionClusterIds[static_cast(ClusterGroups::Group2)],
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateCluster,
+ AzToolsFramework::ViewportUi::Alignment::TopLeft);
+ }
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce:
+ case JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque:
+ {
+ if (group3Id == AzToolsFramework::ViewportUi::InvalidClusterId)
+ {
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::EventResult(
+ m_modeSelectionClusterIds[static_cast(ClusterGroups::Group3)],
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateCluster,
+ AzToolsFramework::ViewportUi::Alignment::TopLeft);
+ }
+ }
+ break;
+ default:
+ AZ_Error("Joints", false, "Joints component mode cluster UI setup found unknown sub mode.");
+ break;
+ }
+ //if both are created - break;
+ if (group2Id != AzToolsFramework::ViewportUi::InvalidClusterId && group3Id != AzToolsFramework::ViewportUi::InvalidClusterId)
+ {
+ break;
+ }
+ }
+
const AzToolsFramework::ViewportUi::ClusterId group1ClusterId = GetClusterId(ClusterGroups::Group1);
const AzToolsFramework::ViewportUi::ClusterId group2ClusterId = GetClusterId(ClusterGroups::Group2);
- //hide cluster 2, if something is added to it. it will make is visible
- AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
- AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible,
- group2ClusterId, false);
-
const AzToolsFramework::ViewportUi::ClusterId group3ClusterId = GetClusterId(ClusterGroups::Group3);
- // hide cluster 3, if something is added to it. it will make is visible
- AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
- AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible,
- group3ClusterId, false);
//translation and rotation are enabled for all joints in group 1
m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::Translation] =
@@ -408,10 +450,6 @@ namespace PhysX
Internal::RegisterClusterButton(group3ClusterId, "joints/MaxForce", SubModeData::MaxForceToolTip);
m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce] =
ButtonData{ group3ClusterId, buttonId };
-
- AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
- AzToolsFramework::ViewportUi::DefaultViewportId,
- &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group3ClusterId, true);
}
break;
case JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque:
@@ -424,10 +462,6 @@ namespace PhysX
Internal::RegisterClusterButton(group3ClusterId, "joints/MaxTorque", SubModeData::MaxTorqueToolTip);
m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque] =
ButtonData{ group3ClusterId, buttonId };
-
- AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
- AzToolsFramework::ViewportUi::DefaultViewportId,
- &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group3ClusterId, true);
}
break;
case JointsComponentModeCommon::SubComponentModes::ModeType::Damping:
@@ -439,10 +473,6 @@ namespace PhysX
const AzToolsFramework::ViewportUi::ButtonId buttonId =
Internal::RegisterClusterButton(group2ClusterId, "joints/Damping", SubModeData::DampingToolTip);
m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Damping] = ButtonData{ group2ClusterId, buttonId };
-
- AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
- AzToolsFramework::ViewportUi::DefaultViewportId,
- &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true);
}
break;
case JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness:
@@ -455,10 +485,6 @@ namespace PhysX
Internal::RegisterClusterButton(group2ClusterId, "joints/Stiffness", SubModeData::StiffnessToolTip);
m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness] =
ButtonData{ group2ClusterId, buttonId };
-
- AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
- AzToolsFramework::ViewportUi::DefaultViewportId,
- &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true);
}
break;
case JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits:
@@ -473,10 +499,6 @@ namespace PhysX
Internal::RegisterClusterButton(group2ClusterId, "joints/TwistLimits", SubModeData::TwistLimitsToolTip);
m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits] =
ButtonData{ group2ClusterId, buttonId };
-
- AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
- AzToolsFramework::ViewportUi::DefaultViewportId,
- &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true);
}
break;
case JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits:
@@ -489,10 +511,6 @@ namespace PhysX
Internal::RegisterClusterButton(group2ClusterId, "joints/SwingLimits", SubModeData::SwingLimitsToolTip);
m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits] =
ButtonData{ group2ClusterId, buttonId };
-
- AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
- AzToolsFramework::ViewportUi::DefaultViewportId,
- &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true);
}
break;
case JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition:
@@ -517,6 +535,9 @@ namespace PhysX
ButtonData{ group1ClusterId, buttonId };
}
break;
+ default:
+ AZ_Error("Joints", false, "Joints component mode cluster button setup found unknown sub mode.");
+ break;
}
}
@@ -560,10 +581,13 @@ namespace PhysX
for (int i = 0; i < static_cast(ClusterGroups::GroupCount); i++)
{
- AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
- AzToolsFramework::ViewportUi::DefaultViewportId,
- &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RegisterClusterEventHandler, m_modeSelectionClusterIds[i],
- m_modeSelectionHandlers[i]);
+ if (m_modeSelectionClusterIds[i] != AzToolsFramework::ViewportUi::InvalidClusterId)
+ {
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RegisterClusterEventHandler,
+ m_modeSelectionClusterIds[i], m_modeSelectionHandlers[i]);
+ }
}
// set the translate as enabled by default.
@@ -588,10 +612,14 @@ namespace PhysX
{
for (auto clusterid : m_modeSelectionClusterIds)
{
- AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
- AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RemoveCluster,
- clusterid);
+ if (clusterid != AzToolsFramework::ViewportUi::InvalidClusterId)
+ {
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RemoveCluster, clusterid);
+ }
}
+ m_modeSelectionClusterIds.assign(static_cast(ClusterGroups::GroupCount), AzToolsFramework::ViewportUi::InvalidClusterId);
}
AzToolsFramework::ViewportUi::ClusterId JointsComponentMode::GetClusterId(ClusterGroups group)
diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/CanvasWidget.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/CanvasWidget.cpp
index e448f3ea40..dfa39b0047 100644
--- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/CanvasWidget.cpp
+++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/CanvasWidget.cpp
@@ -84,9 +84,10 @@ namespace ScriptCanvasEditor
{
m_assetId = assetId;
- EditorGraphRequests* editorGraphRequests = EditorGraphRequestBus::FindFirstHandler(m_scriptCanvasId);
-
- editorGraphRequests->SetAssetId(m_assetId);
+ if (EditorGraphRequests* editorGraphRequests = EditorGraphRequestBus::FindFirstHandler(m_scriptCanvasId))
+ {
+ editorGraphRequests->SetAssetId(m_assetId);
+ }
}
const GraphCanvas::ViewId& CanvasWidget::GetViewId() const
diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.cpp
index 0dcd8ebbbd..d55fcf7838 100644
--- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.cpp
+++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.cpp
@@ -59,6 +59,7 @@ namespace ScriptCanvas
m_script = AZStd::move(other.m_script);
m_requiredAssets = AZStd::move(other.m_requiredAssets);
m_requiredScriptEvents = AZStd::move(other.m_requiredScriptEvents);
+ m_areStaticsInitialized = AZStd::move(other.m_areStaticsInitialized);
}
return *this;
diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h
index 24c83b20a1..8c5da5ac07 100644
--- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h
+++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAsset.h
@@ -76,6 +76,9 @@ namespace ScriptCanvas
AZStd::vector m_activationInputStorage;
Execution::ActivationInputRange m_activationInputRange;
+ // used to initialize statics only once, and not necessarily on the loading thread
+ bool m_areStaticsInitialized = false;
+
bool RequiresStaticInitialization() const;
bool RequiresDependencyConstructionParameters() const;
diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAssetHandler.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAssetHandler.cpp
index df7b07d37b..05b6f4397b 100644
--- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAssetHandler.cpp
+++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAssetHandler.cpp
@@ -94,7 +94,6 @@ namespace ScriptCanvas
RuntimeAsset* runtimeAsset = asset.GetAs();
AZ_Assert(runtimeAsset, "RuntimeAssetHandler::InitAsset This should be a Script Canvas runtime asset, as this is the only type this handler processes!");
Execution::Context::InitializeActivationData(runtimeAsset->GetData());
- Execution::InitializeInterpretedStatics(runtimeAsset->GetData());
}
}
@@ -157,4 +156,5 @@ namespace ScriptCanvas
}
}
}
+
}
diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/ExecutionState.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/ExecutionState.h
index 8c2f0a67c4..89ddf178f3 100644
--- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/ExecutionState.h
+++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/ExecutionState.h
@@ -19,6 +19,10 @@
#include
#include
+#if !defined(_RELEASE)
+#define SCRIPT_CANVAS_RUNTIME_ASSET_CHECK
+#endif
+
namespace AZ
{
class ReflectContext;
diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp
index 4d7c8a2cda..bba56847ce 100644
--- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp
+++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp
@@ -506,6 +506,8 @@ namespace ScriptCanvas
#if defined(AZ_PROFILE_BUILD) || defined(AZ_DEBUG_BUILD)
Execution::InitializeFromLuaStackFunctions(const_cast(runtimeData.m_debugMap));
#endif
+ AZ_WarningOnce("ScriptCanvas", !runtimeData.m_areStaticsInitialized, "ScriptCanvas runtime data already initalized");
+
if (runtimeData.RequiresStaticInitialization())
{
AZ::ScriptLoadResult result{};
diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionStateInterpreted.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionStateInterpreted.cpp
index 9224d4f9a4..a92c13ac63 100644
--- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionStateInterpreted.cpp
+++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionStateInterpreted.cpp
@@ -6,14 +6,13 @@
*
*/
-#include "ExecutionStateInterpreted.h"
-
#include
#include
#include
-
-#include "Execution/Interpreted/ExecutionStateInterpretedUtility.h"
-#include "Execution/RuntimeComponent.h"
+#include
+#include
+#include
+#include
namespace ExecutionStateInterpretedCpp
{
@@ -33,7 +32,29 @@ namespace ScriptCanvas
ExecutionStateInterpreted::ExecutionStateInterpreted(const ExecutionStateConfig& config)
: ExecutionState(config)
, m_interpretedAsset(config.runtimeData.m_script)
- {}
+ {
+ RuntimeAsset* runtimeAsset = config.asset.Get();
+
+#if defined(SCRIPT_CANVAS_RUNTIME_ASSET_CHECK)
+ if (!runtimeAsset)
+ {
+ AZ_Error("ScriptCanvas", false
+ , "ExecutionStateInterpreted created with ExecutionStateConfig that contained bad runtime asset data. %s"
+ , config.asset.GetId().ToString().data());
+ return;
+ }
+#else
+ AZ_Assert(false
+ , "ExecutionStateInterpreted created with ExecutionStateConfig that contained bad runtime asset data. %s"
+ , config.asset.GetId().ToString().data());
+#endif
+
+ if (!runtimeAsset->GetData().m_areStaticsInitialized)
+ {
+ runtimeAsset->GetData().m_areStaticsInitialized = true;
+ Execution::InitializeInterpretedStatics(runtimeAsset->GetData());
+ }
+ }
void ExecutionStateInterpreted::ClearLuaRegistryIndex()
{
diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp
index 5fe5c32a48..930b84abe4 100644
--- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp
+++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp
@@ -19,9 +19,8 @@
#include
#include
-#if !defined(_RELEASE)
-#define SCRIPT_CANVAS_RUNTIME_ASSET_CHECK
-#endif
+#include
+#include
AZ_DECLARE_BUDGET(ScriptCanvas);
@@ -112,11 +111,13 @@ namespace ScriptCanvas
#if defined(SCRIPT_CANVAS_RUNTIME_ASSET_CHECK)
if (!m_runtimeOverrides.m_runtimeAsset.Get())
{
- AZ_Error("ScriptCanvas", false, "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data());
+ AZ_Error("ScriptCanvas", false, "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run"
+ , m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data());
return;
}
#else
- AZ_Assert(m_runtimeOverrides.m_runtimeAsset.Get(), "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data());
+ AZ_Assert(m_runtimeOverrides.m_runtimeAsset.Get(), "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run"
+ , m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data());
#endif
AZ_PROFILE_SCOPE(ScriptCanvas, "RuntimeComponent::InitializeExecution (%s)", m_runtimeOverrides.m_runtimeAsset.GetId().ToString().c_str());
@@ -126,11 +127,13 @@ namespace ScriptCanvas
#if defined(SCRIPT_CANVAS_RUNTIME_ASSET_CHECK)
if (!m_executionState)
{
- AZ_Error("ScriptCanvas", false, "RuntimeComponent::m_runtimeAsset AssetId: %s failed to create an execution state, possibly due to missing dependent asset, script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString