diff --git a/.clang-format b/.clang-format
index 565f28130e..04e0284f97 100644
--- a/.clang-format
+++ b/.clang-format
@@ -46,7 +46,7 @@ SortIncludes: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
-SpaceBeforeCpp11BracedList: true
+SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
diff --git a/Assets/Engine/SeedAssetList.seed b/Assets/Engine/SeedAssetList.seed
index 45a02f7682..77ec509721 100644
--- a/Assets/Engine/SeedAssetList.seed
+++ b/Assets/Engine/SeedAssetList.seed
@@ -67,106 +67,98 @@
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -264,109 +256,101 @@
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -387,498 +371,474 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -896,14 +856,6 @@
-
-
-
-
-
-
-
-
@@ -928,29 +880,13 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
@@ -1451,146 +1387,146 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -1699,42 +1635,42 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
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 7a85cb1813..34af4d9115 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
@@ -162,7 +162,7 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
else:
cmd.append(f"--{key}")
if append_defaults:
- cmd.append(f"--project={workspace.project}")
+ cmd.append(f"--project-path={workspace.project}")
return cmd
# ******
@@ -300,9 +300,9 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
workspace.paths.engine_root(),
"Code",
"Framework",
- "AzFramework",
- "AzFramework",
- "Platform",
+ "AzCore",
+ "AzCore",
+ "PlatformId",
"PlatformDefaults.h",
)
@@ -318,7 +318,7 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
if start_gathering:
result = get_platform.match(line) # Try the regex
if result:
- platform_values[result.group(1).lower()] = counter
+ platform_values[result.group(1).replace("_ID", "").lower()] = counter
counter = counter << 1
elif "(Invalid, -1)" in line: # The line right before the first platform
start_gathering = True
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 8738e8acdf..1043bbaefa 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
@@ -302,7 +302,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
that generating debug information does not affect asset list creation
"""
helper = bundler_batch_helper
- seed_list = os.path.join(workspace.paths.engine_root(), "Engine", "SeedAssetList.seed") # Engine seed list
+ seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed") # Engine seed list
asset = r"levels\testdependencieslevel\level.pak"
# Create Asset list
@@ -377,7 +377,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
subcommands.
"""
helper = bundler_batch_helper
- seed_list = os.path.join(workspace.paths.engine_root(), "Engine", "SeedAssetList.seed") # Engine seed list
+ seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed") # Engine seed list
asset = r"levels\testdependencieslevel\level.pak"
# Useful bundle locations / names (2 for comparing contents)
@@ -465,7 +465,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
"Please rerun with commandline option: '--bundle_platforms=pc,mac'"
# fmt:on
- seed_list = os.path.join(workspace.paths.engine_root(), "Engine", "SeedAssetList.seed") # Engine seed list
+ seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed") # Engine seed list
# Useful bundle / asset list locations
bundle_dir = os.path.dirname(helper["bundle_file"])
@@ -502,13 +502,13 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
for bundle_file in bundle_files.values():
assert os.path.isfile(bundle_file)
- # This asset is created on mac platform but not on windows
- file_to_check = b"engineassets/shading/defaultprobe_cm.dds.5" # [use byte str because file is in binary]
+ # This asset is created both on mac and windows platform
+ file_to_check = b"engineassets/shading/defaultprobe_cm_ibldiffuse.tif.streamingimage" # [use byte str because file is in binary]
# Extract the delta catalog file from pc archive. {file_to_check} SHOULD NOT be present for PC
file_contents = helper.extract_file_content(bundle_files["pc"], "DeltaCatalog.xml")
# fmt:off
- assert file_to_check not in file_contents, \
+ assert file_to_check in file_contents, \
f"{file_to_check} was found in DeltaCatalog.xml in pc bundle file {bundle_files['pc']}"
# fmt:on
@@ -619,7 +619,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
# Validate both mac and pc are activated for seed
# fmt:off
check_seed_platform(helper["seed_list_file"], test_asset,
- helper["platform_values"]["pc"] + helper["platform_values"]["osx"])
+ helper["platform_values"]["pc"] + helper["platform_values"]["mac"])
# fmt:on
# Remove MAC platform
@@ -651,7 +651,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
# Validate Mac platform was added back on. Save file contents
# fmt:off
all_lines = check_seed_platform(helper["seed_list_file"], test_asset,
- helper["platform_values"]["pc"] + helper["platform_values"]["osx"])
+ helper["platform_values"]["pc"] + helper["platform_values"]["mac"])
# fmt:on
# Try to remove platform without specifying a platform to remove (should fail)
@@ -1046,7 +1046,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
"--addDefaultSeedListFiles",
"--platform=pc",
"--print",
- f"--project={workspace.project}"
+ f"--project-path={workspace.project}"
],
universal_newlines=True,
)
@@ -1115,7 +1115,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
bundle_result_path = os.path.join(bundles_folder,
helper.platform_file_name("bundle.pak", workspace.asset_processor_platform))
- bundle_cache_path = os.path.join(workspace.paths.platform_cache(), workspace.project,
+ bundle_cache_path = os.path.join(workspace.paths.platform_cache(),
"Bundles",
helper.platform_file_name("bundle.pak", workspace.asset_processor_platform))
@@ -1156,13 +1156,15 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
# fmt:off
def test_WindowsAndMac_FilesMarkedSkip_FilesAreSkipped(self, workspace, bundler_batch_helper):
expected_assets = [
- "libs/particles/milestone2particles.xml",
- "textures/milestone2/particles/fx_sparkstreak_01.dds"
+ "ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas",
+ "ui/textures/prefab/button_normal.sprite"
]
bundler_batch_helper.call_assetLists(
assetListFile=bundler_batch_helper['asset_info_file_request'],
- addSeed="libs/particles/milestone2particles.xml",
- skip="textures/milestone2/particles/fx_launchermuzzlering_01.dds,textures/milestone2/particles/fx_launchermuzzlefront_01.dds"
+ 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"
)
assert os.path.isfile(bundler_batch_helper["asset_info_file_result"])
assets_in_list = []
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_BasicSurfaceTagCreation.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_BasicSurfaceTagCreation.py
index 4f58a23a19..730a557a9e 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_BasicSurfaceTagCreation.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_BasicSurfaceTagCreation.py
@@ -23,6 +23,25 @@ class TestSurfaceMaskFilter_BasicSurfaceTagCreation(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="TestSurfaceMaskFilter_BasicSurfaceTagCreation", args=["level"])
def run_test(self):
+ """
+ Summary:
+ Verifies basic surface tag value equality
+
+ Expected Behavior:
+ Surface tags of the same name are equal, and different names aren't.
+
+ Test Steps:
+ 1) Open level
+ 2) Create 2 new surface tags of identical names and verify they resolve as equal.
+ 3) Create another new tag of a different name and verify they resolve as different.
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
self.log("SurfaceTag test started")
# Create a level
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/VegetationInstances_DespawnWhenOutOfRange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/VegetationInstances_DespawnWhenOutOfRange.py
index c25761d655..46c5483988 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/VegetationInstances_DespawnWhenOutOfRange.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/VegetationInstances_DespawnWhenOutOfRange.py
@@ -33,6 +33,25 @@ class TestVegetationInstances_DespawnWhenOutOfRange(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix='VegetationInstances_DespawnWhenOutOfRange', args=['level'])
def run_test(self):
+ """
+ Summary:
+ Verifies that vegetation instances properly spawn/despawn based on camera range.
+
+ Expected Behavior:
+ Vegetation instances despawn when out of camera range.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Create a simple vegetation area, and set the view position near the spawner. Verify instances plant.
+ 3) Move the view position away from the spawner. Verify instances despawn.
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
# Create a new level
self.test_success = self.create_level(
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py
index cc9a15bba0..c37bc9780f 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py
@@ -28,8 +28,21 @@ class TestGradientGeneratorIncompatibilities(EditorTestHelper):
def run_test(self):
"""
Summary:
- Verify that Entities are not active when a Gradient Generator and incompatible component are both present
- on the same Entity.
+ This test verifies that components are disabled when conflicting components are present on the same entity.
+
+ Expected Behavior:
+ Gradient Generator components are incompatible with Vegetation area components.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Create a new entity in the level
+ 3) Add each Gradient Generator component to an entity, and add a Vegetation Area component to the same entity
+ 4) Verify that components are only enabled when entity is free of a conflicting component
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py
index b7d12d074a..f2edc2924e 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py
@@ -28,8 +28,21 @@ class TestGradientModifiersIncompatibilities(EditorTestHelper):
def run_test(self):
"""
Summary:
- Verify that Entities are not active when a Gradient Modifier and incompatible component are both present
- on the same Entity.
+ This test verifies that components are disabled when conflicting components are present on the same entity.
+
+ Expected Behavior:
+ Gradient Modifier components are incompatible with Vegetation area components.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Create a new entity in the level
+ 3) Add each Gradient Modifier component to an entity, and add a Vegetation Area component to the same entity
+ 4) Verify that components are only enabled when entity is free of a conflicting component
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py
index c37ee36265..45da74d6cd 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py
@@ -9,19 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
-"""
-The below cases are combined in this script
-C2676829
-C3961326
-C3980659
-C3980664
-C3980669
-C3416548
-C2676823
-C3961321
-C2676826
-"""
-
import os
import sys
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py
index 5a758b9d89..b8f4114d30 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py
@@ -44,7 +44,21 @@ class TestGradientPreviewSettings(EditorTestHelper):
def run_test(self):
"""
Summary:
- Verify if the current entity is set to the pin preview to shape entity by default for several components.
+ This test verifies default values for the pinned entity for Gradient Preview settings.
+
+ Expected Behavior:
+ Pinned entity is self for all gradient generator/modifiers.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Create a new entity in the level
+ 3) Add each Gradient Generator component to an entity, and verify the Pin Preview to Shape property is set to
+ self
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py
index a16e37e0fc..8e2d0611af 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py
@@ -31,11 +31,21 @@ class TestGradientSurfaceTagEmitterDependencies(EditorTestHelper):
def run_test(self):
"""
Summary:
- Component has a dependency on a Gradient component
+ This test verifies that the Gradient Surface Tag Emitter component is dependent on a gradient component.
Expected Result:
- Component is disabled until a Gradient Generator, Modifier or Gradient Reference component
- (and any sub-dependencies) is added to the entity.
+ Gradient Surface Tag Emitter component is disabled until a Gradient Generator, Modifier or Gradient Reference
+ component (and any sub-dependencies) is added to the entity.
+
+ Test Steps:
+ 1) Open level
+ 2) Create a new entity with a Gradient Surface Tag Emitter component
+ 3) Verify the component is disabled until a dependent component is also added to the entity
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py
index e1e901f2f7..2311363db9 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py
@@ -28,8 +28,20 @@ class TestGradientTransformRequiresShape(EditorTestHelper):
def run_test(self):
"""
Summary:
- Verify that Gradient Transform Modifier component requires a
- Shape component before the Entity can become active.
+ This test verifies that the Gradient Transform Modifier component is dependent on a shape component.
+
+ Expected Result:
+ Gradient Transform Modifier component is disabled until a shape component is added to the entity.
+
+ Test Steps:
+ 1) Open level
+ 2) Create a new entity with a Gradient Transform Modifier component
+ 3) Verify the component is disabled until a shape component is also added to the entity
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py
index dab8e6928a..a5d9632fd6 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py
@@ -28,8 +28,20 @@ class TestImageGradientRequiresShape(EditorTestHelper):
def run_test(self):
"""
Summary:
- Verify that Image Gradient component requires a
- Shape component before the Entity can become active.
+ This test verifies that the Image Gradient component is dependent on a shape component.
+
+ Expected Result:
+ Gradient Transform Modifier component is disabled until a shape component is added to the entity.
+
+ Test Steps:
+ 1) Open level
+ 2) Create a new entity with a Image Gradient component
+ 3) Verify the component is disabled until a shape component is also added to the entity
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py
index d1e0b68ef4..c41d153cfa 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py
@@ -33,6 +33,26 @@ class TestAreaNodeComponentDependency(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="AreaNodeComponentDependency", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities with
+ proper dependent components.
+
+ Expected Behavior:
+ All expected component dependencies are met when adding an area node to a graph.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the area nodes to the graph area, and ensure the proper dependent components are added
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global newEntityId
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py
index 4e429a192b..fb977b4987 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py
@@ -33,7 +33,25 @@ class TestGradientNodeEntityCreate(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="AreaNodeEntityCreate", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
+ Expected Behavior:
+ New entities are created when dragging area nodes to graph area.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the area nodes to the graph area, and ensure a new entity is created
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global newEntityId
newEntityId = parameters[0]
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityRemovedOnNodeDelete.py
index 38f8641b4c..57ba8fc006 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityRemovedOnNodeDelete.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityRemovedOnNodeDelete.py
@@ -34,7 +34,26 @@ class TestAreaNodeEntityDelete(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="AreaNodeEntityDelete", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
+ Expected Behavior:
+ Entities are removed when area nodes are deleted from a graph.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the area nodes to the graph area, and ensure a new entity is created
+ 4) Delete the nodes, and ensure the newly created entities are removed
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global createdEntityId
createdEntityId = parameters[0]
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py
index 26062c01f8..60527b64d2 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py
@@ -9,24 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
-
-"""
-C22602072 - Graph is updated when underlying components are added/removed
-
-1. Open Level.
-2. Find LandscapeCanvas named entity.
-3. Ensure Vegetation Distribution Component is present on the BushSpawner entity.
-4. Open graph and ensure Distribution Filter wrapped node is present.
-5. Delete the Vegetation Distribution Filter component from the BushSpawner entity via Entity Inspector.
-6. Ensure the Vegetation Distribution Filter component was deleted from the BushSpawner entity and node is no longer
-present in the graph.
-7. Add Vegetation Altitude Filter to the BushSpawner entity through Entity Inspector.
-8. Ensure Altitude Filter was added to the BushSpawner node in the open graph.
-9. Add a new entity with unique name as a child of the Landscape Canvas entity.
-10. Add a Box Shape component to the new child entity.
-11. Ensure Box Shape node is present on the open graph.
-"""
-
import os
import sys
@@ -50,6 +32,36 @@ class TestComponentUpdatesUpdateGraph(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="ComponentUpdatesUpdateGraph", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that the Landscape Canvas graphs update properly when components are added/removed outside of
+ Landscape Canvas.
+
+ Expected Behavior:
+ Graphs properly reflect component changes made to entities outside of Landscape Canvas.
+
+ Test Steps:
+ 1. Open Level
+ 2. Find LandscapeCanvas named entity
+ 3. Ensure Vegetation Distribution Component is present on the BushSpawner entity
+ 4. Open graph and ensure Distribution Filter wrapped node is present
+ 5. Delete the Vegetation Distribution Filter component from the BushSpawner entity via Entity Inspector
+ 6. Ensure the Vegetation Distribution Filter component was deleted from the BushSpawner entity and node is
+ no longer present in the graph
+ 7. Add Vegetation Altitude Filter to the BushSpawner entity through Entity Inspector
+ 8. Ensure Altitude Filter was added to the BushSpawner node in the open graph
+ 9. Add a new entity with unique name as a child of the Landscape Canvas entity
+ 10. Add a Box Shape component to the new child entity
+ 11. Ensure Box Shape node is present on the open graph
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
+
# Create a new empty level and instantiate LC_BushFlowerBlender.slice
self.test_success = self.create_level(
self.args["level"],
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py
index 5fed13985d..4b5e03abbc 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py
@@ -37,6 +37,25 @@ class TestCreateNewGraph(EditorTestHelper):
print("New root entity created")
def run_test(self):
+ """
+ Summary:
+ This test verifies that new graphs can be created in Landscape Canvas.
+
+ Expected Behavior:
+ New graphs can be created, and proper entity is created to hold graph data with a Landscape Canvas component.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Ensures the root entity created contains a Landscape Canvas component
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
self.test_success = self.create_level(
self.args["level"],
heightmap_resolution=128,
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py
index 7fd3f075e0..81e24b20e1 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py
@@ -33,7 +33,25 @@ class TestDisabledNodeDuplication(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="DisabledNodeDuplication", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies Editor stability after duplicating disabled Landscape Canvas nodes.
+ Expected Behavior:
+ Editor remains stable and free of crashes.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Create several new nodes, disable the nodes via disabling/deleting components, and duplicate the nodes
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global newEntityId
newEntityId = parameters[0]
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py
index 27ab6fded3..61c4cf9ac2 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py
@@ -9,17 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
-
-"""
-C30813586 - Editor remains stable after Undoing deletion of a node on a slice entity
-
-1. Open level with instantiated slice.
-2. Open the graph.
-3. Find the BushSpawner's Vegetation Layer Spawner node.
-4. Delete the node.
-5. Undo to restore the node.
-"""
-
import os
import sys
@@ -44,7 +33,26 @@ class TestUndoNodeDeleteSlice(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="UndoNodeDeleteSlice", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies Editor stability after undoing the deletion of nodes on a slice entity.
+ Expected Behavior:
+ Editor remains stable and free of crashes.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Instantiate a slice with a Landscape Canvas setup
+ 3) Find a specific node on the graph, and delete it
+ 4) Restore the node with Undo
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
# Create a new empty level and instantiate LC_BushFlowerBlender.slice
self.test_success = self.create_level(
self.args["level"],
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py
index ca3bc04f47..124baf9d2e 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py
@@ -34,6 +34,27 @@ class TestGradientMixerNodeConstruction(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GradientMixerNodeConstruction", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies a Gradient Mixer vegetation setup can be constructed through Landscape Canvas.
+
+ Expected Behavior:
+ Entities contain all required components and component references after creating nodes and setting connections
+ on a Landscape Canvas graph.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Add all necessary nodes to the graph and set connections to form a Gradient Mixer setup
+ 4) Verify all components and component references were properly set during graph construction
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global newEntityId
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py
index d40b19e7db..aa98eb3dc3 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py
@@ -33,6 +33,25 @@ class TestGradientModifierNodeEntityCreate(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GradientModifierNodeEntityCreate", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
+
+ Expected Behavior:
+ New entities are created when dragging Gradient Modifier nodes to graph area.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the Gradient Modifier nodes to the graph area, and ensure a new entity is created
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global newEntityId
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py
index dc263924d1..6a82b05039 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py
@@ -34,7 +34,26 @@ class TestGradientModifierNodeEntityDelete(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GradientModifierNodeEntityDelete", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
+ Expected Behavior:
+ Entities are removed when Gradient Modifier nodes are deleted from a graph.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the Gradient Modifier nodes to the graph area, and ensure a new entity is created
+ 4) Delete the nodes, and ensure the newly created entities are removed
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global createdEntityId
createdEntityId = parameters[0]
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py
index 5e203e1892..f9360fe356 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py
@@ -33,6 +33,27 @@ class TestGradientNodeComponentDependency(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GradientNodeComponentDependency", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities with
+ proper dependent components.
+
+ Expected Behavior:
+ All expected component dependencies are met when adding a Gradient Modifier node to a graph.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the Gradient Modifier nodes to the graph area, and ensure the proper dependent components are
+ added
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global newEntityId
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py
index 6d4a2f58a7..8aaad9b81d 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py
@@ -32,6 +32,25 @@ class TestGradientNodeEntityCreate(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GradientNodeEntityCreate", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
+
+ Expected Behavior:
+ New entities are created when dragging Gradient nodes to graph area.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the Gradient nodes to the graph area, and ensure a new entity is created
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global newEntityId
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py
index 2b49e3a911..d74b86d0bf 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py
@@ -34,6 +34,26 @@ class TestGradientNodeEntityDelete(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GradientNodeEntityDelete", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
+
+ Expected Behavior:
+ Entities are removed when Gradient nodes are deleted from a graph.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the Gradient nodes to the graph area, and ensure a new entity is created
+ 4) Delete the nodes, and ensure the newly created entities are removed
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global createdEntityId
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py
index d3ad5c1c1e..6aa539b554 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py
@@ -31,6 +31,26 @@ class TestGraphClosedOnEntityDelete(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GraphClosedOnEntityDelete", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that Landscape Canvas graphs are auto-closed when the corresponding entity is deleted.
+
+ Expected Behavior:
+ When a Landscape Canvas root entity is deleted, the corresponding graph automatically closes.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Delete the automatically created entity
+ 4) Verify the open graph is closed
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global newRootEntityId
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py
index b7b0008eb2..ebc75ab621 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py
@@ -29,7 +29,26 @@ class TestGraphClosedOnLevelChange(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GraphClosedOnLevelChange", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that Landscape Canvas graphs are auto-closed when the currently open level changes.
+ Expected Behavior:
+ When a new level is loaded in the Editor, open Landscape Canvas graphs are automatically closed.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Open a different level
+ 4) Verify the open graph is closed
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
# Create a new empty level
self.test_success = self.create_level(
self.args["level"],
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py
index efd1cc5a55..4b018aeb45 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py
@@ -29,6 +29,26 @@ class TestGraphClosedTabbedGraph(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GraphClosedTabbedGraph", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that Landscape Canvas tabbed graphs can be independently closed.
+
+ Expected Behavior:
+ Closing a tabbed graph only closes the appropriate graph.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create several new graphs
+ 3) Close one of the open graphs
+ 4) Ensure the graph properly closed, and other open graphs remain open
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
# Create a new empty level
self.test_success = self.create_level(
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py
index f350d37178..f94a6c2e3a 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py
@@ -9,21 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
-
-"""
-C22715182 - Components are updated when nodes are added/removed/updated
-
-1. Open Level.
-2. Open the graph on LC_BushFlowerBlender.slice
-3. Find the Rotation Modifier node on the BushSpawner entity
-4. Delete the Rotation Modifier node
-5. Ensure the Vegetation Rotation Modifier component is removed from the BushSpawner entity
-6. Delete the Vegetation Layer Spawner node from the graph
-7. Ensure BushSpawner entity is deleted
-8. Change connection from second Rotation Modifier node to a different Gradient
-9. Ensure Gradient reference on component is updated
-"""
-
import os
import sys
@@ -50,6 +35,31 @@ class TestGraphUpdatesUpdateComponents(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GraphUpdatesUpdateComponents", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that components are properly updated as nodes are added/removed/updated.
+
+ Expected Behavior:
+ Landscape Canvas node CRUD properly updates component entities.
+
+ Test Steps:
+ 1. Open Level.
+ 2. Open the graph on LC_BushFlowerBlender.slice
+ 3. Find the Rotation Modifier node on the BushSpawner entity
+ 4. Delete the Rotation Modifier node
+ 5. Ensure the Vegetation Rotation Modifier component is removed from the BushSpawner entity
+ 6. Delete the Vegetation Layer Spawner node from the graph
+ 7. Ensure BushSpawner entity is deleted
+ 8. Change connection from second Rotation Modifier node to a different Gradient
+ 9. Ensure Gradient reference on component is updated
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
# Create a new empty level and instantiate LC_BushFlowerBlender.slice
self.test_success = self.create_level(
self.args["level"],
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py
index 176429885f..c3857e1393 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py
@@ -30,6 +30,26 @@ class TestLandscapeCanvasComponentAddedRemoved(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="LandscapeCanvasComponentAddedRemoved", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that the Landscape Canvas component can be added to/removed from an entity.
+
+ Expected Behavior:
+ Closing a tabbed graph only closes the appropriate graph.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Create a new entity
+ 3) Add a Landscape Canvas component to the entity
+ 4) Remove the Landscape Canvas component from the entity
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
# Create a new empty level
self.test_success = self.create_level(
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py
index e0f13adaa9..f174a52610 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py
@@ -30,12 +30,21 @@ class TestLandscapeCanvasSliceCreateInstantiate(EditorTestHelper):
def run_test(self):
"""
Summary:
- C22602016 A slice containing the LandscapeCanvas component can be created/instantiated.
+ A slice containing the LandscapeCanvas component can be created/instantiated.
Expected Result:
- Slice is created and processed successfully and free of errors/warnings.
- Another copy of the slice is instantiated.
+ Slice is created/processed/instantiated successfully and free of errors/warnings.
+ Test Steps:
+ 1) Create a new level
+ 2) Create a new entity with a Landscape Canvas component
+ 3) Create a slice of the new entity
+ 4) Instantiate a new copy of the slice
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py
index ecc529b9b4..82a2abf5ea 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py
@@ -34,6 +34,27 @@ class TestLayerBlenderNodeConstruction(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="LayerBlenderNodeConstruction", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies a Layer Blender vegetation setup can be constructed through Landscape Canvas.
+
+ Expected Behavior:
+ Entities contain all required components and component references after creating nodes and setting connections
+ on a Landscape Canvas graph.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Add all necessary nodes to the graph and set connections to form a Layer Blender setup
+ 4) Verify all components and component references were properly set during graph construction
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global newEntityId
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py
index 00fcb5170c..df3c549fff 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py
@@ -34,6 +34,25 @@ class TestLayerExtenderNodeComponentEntitySync(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="LayerExtenderNodeComponentEntitySync", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that all wrapped nodes can be successfully added to/removed from parent nodes.
+
+ Expected Behavior:
+ All wrapped extender nodes can be added to/removed from appropriate parent nodes.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Add Area Blender and Layer Spawner nodes to the graph, and add/remove each extender node to/from each
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global newEntityId
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py
index bd10e5f4c6..cd4915ea24 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py
@@ -33,6 +33,25 @@ class TestShapeNodeEntityCreate(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="ShapeNodeEntityCreate", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
+
+ Expected Behavior:
+ New entities are created when dragging shape nodes to graph area.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the shape nodes to the graph area, and ensure a new entity is created
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
def onEntityCreated(parameters):
global newEntityId
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py
index f71f5ae906..fcfbe03576 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py
@@ -34,7 +34,27 @@ class TestShapeNodeEntityDelete(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="ShapeNodeEntityDelete", args=["level"])
def run_test(self):
-
+ """
+ Summary:
+ This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
+
+ Expected Behavior:
+ Entities are removed when shape nodes are deleted from a graph.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Drag each of the shape nodes to the graph area, and ensure a new entity is created
+ 4) Delete the nodes, and ensure the newly created entities are removed
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
+
def onEntityCreated(parameters):
global createdEntityId
createdEntityId = parameters[0]
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py
index 968f39c64d..183c3f7ccb 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py
@@ -33,6 +33,27 @@ class TestSlotConnectionsUpdateComponents(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="SlotConnectionsUpdateComponents", args=["level"])
def run_test(self):
+ """
+ Summary:
+ This test verifies that the Landscape Canvas slot connections properly update component references.
+
+ Expected Behavior:
+ A reference created through slot connections in Landscape Canvas is reflected in the Entity Inspector.
+
+ Test Steps:
+ 1) Create a new level
+ 2) Open Landscape Canvas and create a new graph
+ 3) Several nodes are added to a graph, and connections are set between the nodes
+ 4) Component references are verified via Entity Inspector
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
+
# Retrieve the proper component TypeIds per component name
componentNames = [
'Random Noise Gradient',
diff --git a/AutomatedTesting/Gem/PythonTests/scripting/ScriptEvents_AllParamDatatypes_CreationSuccess.py b/AutomatedTesting/Gem/PythonTests/scripting/ScriptEvents_AllParamDatatypes_CreationSuccess.py
new file mode 100644
index 0000000000..4beedec7cf
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/scripting/ScriptEvents_AllParamDatatypes_CreationSuccess.py
@@ -0,0 +1,210 @@
+"""
+All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+its licensors.
+
+For complete copyright and license terms please see the LICENSE at the root of this
+distribution (the "License"). All use of this software is governed by the License,
+or, if provided, by the license below or the license accompanying this file. Do not
+remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+"""
+
+
+# fmt: off
+class Tests():
+ new_event_created = ("New Script Event created", "New Script Event not created")
+ child_event_created = ("Child Event created", "Child Event not created")
+ params_added = ("New parameters added", "New parameters are not added")
+ file_saved = ("Script event file saved", "Script event file did not save")
+ node_found = ("Node found in Script Canvas", "Node not found in Script Canvas")
+# fmt: on
+
+
+def ScriptEvents_AllParamDatatypes_CreationSuccess():
+ """
+ Summary:
+ Parameters of all types can be created.
+
+ Expected Behavior:
+ The Method handles the large number of Parameters gracefully.
+ Parameters of all data types can be successfully created.
+ Updated ScriptEvent toast appears in Script Canvas.
+
+ Test Steps:
+ 1) Open Asset Editor
+ 2) Initially create new Script Event file with one method
+ 3) Add new method and set name to it
+ 4) Add new parameters of each type
+ 5) Verify if parameters are added
+ 6) Expand the parameter rows
+ 7) Set different names and datatypes for each parameter
+ 8) Save file and verify node in SC Node Palette
+ 9) Close Asset Editor
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
+ import os
+ from utils import TestHelper as helper
+ import pyside_utils
+
+ # Open 3D Engine imports
+ import azlmbr.legacy.general as general
+ import azlmbr.editor as editor
+ import azlmbr.bus as bus
+
+ # Pyside imports
+ from PySide2 import QtWidgets, QtTest, QtCore
+
+ GENERAL_WAIT = 1.0 # seconds
+
+ FILE_PATH = os.path.join("AutomatedTesting", "TestAssets", "test_file.scriptevents")
+ N_VAR_TYPES = 10 # Top 10 variable types
+ TEST_METHOD_NAME = "test_method_name"
+
+ editor_window = pyside_utils.get_editor_main_window()
+ asset_editor = asset_editor_widget = container = menu_bar = None
+ sc = node_palette = tree = search_frame = search_box = None
+
+ def initialize_asset_editor_qt_objects():
+ nonlocal asset_editor, asset_editor_widget, container, menu_bar
+ asset_editor = editor_window.findChild(QtWidgets.QDockWidget, "Asset Editor")
+ asset_editor_widget = asset_editor.findChild(QtWidgets.QWidget, "AssetEditorWindowClass")
+ container = asset_editor_widget.findChild(QtWidgets.QWidget, "ContainerForRows")
+ menu_bar = asset_editor_widget.findChild(QtWidgets.QMenuBar)
+
+ def initialize_sc_qt_objects():
+ nonlocal sc, node_palette, tree, search_frame, search_box
+ sc = editor_window.findChild(QtWidgets.QDockWidget, "Script Canvas")
+ if sc.findChild(QtWidgets.QDockWidget, "NodePalette") is None:
+ action = pyside_utils.find_child_by_pattern(sc, {"text": "Node Palette", "type": QtWidgets.QAction})
+ action.trigger()
+ node_palette = sc.findChild(QtWidgets.QDockWidget, "NodePalette")
+ tree = node_palette.findChild(QtWidgets.QTreeView, "treeView")
+ search_frame = node_palette.findChild(QtWidgets.QFrame, "searchFrame")
+ search_box = search_frame.findChild(QtWidgets.QLineEdit, "searchFilter")
+
+ def save_file():
+ editor.AssetEditorWidgetRequestsBus(bus.Broadcast, "SaveAssetAs", FILE_PATH)
+ action = pyside_utils.find_child_by_pattern(menu_bar, {"type": QtWidgets.QAction, "iconText": "Save"})
+ action.trigger()
+ # wait till file is saved, to validate that check the text of QLabel at the bottom of the AssetEditor,
+ # if there are no unsaved changes we will not have any * in the text
+ label = asset_editor.findChild(QtWidgets.QLabel, "textEdit")
+ return helper.wait_for_condition(lambda: "*" not in label.text(), 3.0)
+
+ def expand_container_rows(object_name):
+ children = container.findChildren(QtWidgets.QFrame, object_name)
+ for child in children:
+ check_box = child.findChild(QtWidgets.QCheckBox)
+ if check_box and not check_box.isChecked():
+ QtTest.QTest.mouseClick(check_box, QtCore.Qt.LeftButton, QtCore.Qt.NoModifier)
+
+ def node_palette_search(node_name):
+ search_box.setText(node_name)
+ helper.wait_for_condition(lambda: search_box.text() == node_name, 1.0)
+ # Try clicking ENTER in search box multiple times
+ for _ in range(20):
+ QtTest.QTest.keyClick(search_box, QtCore.Qt.Key_Enter, QtCore.Qt.NoModifier)
+ if pyside_utils.find_child_by_pattern(tree, {"text": node_name}) is not None:
+ break
+
+ def verify_added_params():
+ for index in range(N_VAR_TYPES):
+ if container.findChild(QtWidgets.QFrame, f"[{index}]") is None:
+ return False
+ return True
+
+ # 1) Open Asset Editor
+ general.idle_enable(True)
+ # Initially close the Asset Editor and then reopen to ensure we don't have any existing assets open
+ general.close_pane("Asset Editor")
+ general.open_pane("Asset Editor")
+ helper.wait_for_condition(lambda: general.is_pane_visible("Asset Editor"), 5.0)
+
+ # 2) Initially create new Script Event file with one method
+ initialize_asset_editor_qt_objects()
+ action = pyside_utils.find_child_by_pattern(menu_bar, {"type": QtWidgets.QAction, "text": "Script Events"})
+ action.trigger()
+ result = helper.wait_for_condition(
+ lambda: container.findChild(QtWidgets.QFrame, "Events") is not None
+ and container.findChild(QtWidgets.QFrame, "Events").findChild(QtWidgets.QToolButton, "") is not None,
+ 3 * GENERAL_WAIT,
+ )
+ Report.result(Tests.new_event_created, result)
+
+ # 3) Add new method and set name to it
+ add_event = container.findChild(QtWidgets.QFrame, "Events").findChild(QtWidgets.QToolButton, "")
+ add_event.click()
+ result = helper.wait_for_condition(
+ lambda: asset_editor_widget.findChild(QtWidgets.QFrame, "EventName") is not None, GENERAL_WAIT
+ )
+ Report.result(Tests.child_event_created, result)
+ expand_container_rows("EventName")
+ expand_container_rows("Name")
+ initialize_asset_editor_qt_objects()
+ children = container.findChildren(QtWidgets.QFrame, "Name")
+ for child in children:
+ line_edit = child.findChild(QtWidgets.QLineEdit)
+ if line_edit is not None and line_edit.text() == "MethodName":
+ line_edit.setText(TEST_METHOD_NAME)
+
+ # 4) Add new parameters of each type
+ helper.wait_for_condition(lambda: container.findChild(QtWidgets.QFrame, "Parameters") is not None, 2.0)
+ parameters = container.findChild(QtWidgets.QFrame, "Parameters")
+ add_param = parameters.findChild(QtWidgets.QToolButton, "")
+ for _ in range(N_VAR_TYPES):
+ add_param.click()
+
+ # 5) Verify if parameters are added
+ result = helper.wait_for_condition(verify_added_params, 3.0)
+ Report.result(Tests.params_added, result)
+
+ # 6) Expand the parameter rows (to render QFrame 'Type' for each param)
+ for index in range(N_VAR_TYPES):
+ expand_container_rows(f"[{index}]")
+
+ # 7) Set different names and datatypes for each parameter
+ expand_container_rows("Name")
+ children = container.findChildren(QtWidgets.QFrame, "Name")
+ index = 0
+ for child in children:
+ line_edit = child.findChild(QtWidgets.QLineEdit)
+ if line_edit is not None and line_edit.text() == "ParameterName":
+ line_edit.setText(f"param_{index}")
+ index += 1
+
+ children = container.findChildren(QtWidgets.QFrame, "Type")
+ index = 0
+ for child in children:
+ combo_box = child.findChild(QtWidgets.QComboBox)
+ if combo_box is not None and index < N_VAR_TYPES:
+ combo_box.setCurrentIndex(index)
+ index += 1
+
+ # 8) Save file and verify node in SC Node Palette
+ Report.result(Tests.file_saved, save_file())
+ general.open_pane("Script Canvas")
+ helper.wait_for_condition(lambda: general.is_pane_visible("Script Canvas"), 5.0)
+ initialize_sc_qt_objects()
+ node_palette_search(TEST_METHOD_NAME)
+ get_node_index = lambda: pyside_utils.find_child_by_pattern(tree, {"text": TEST_METHOD_NAME}) is not None
+ result = helper.wait_for_condition(get_node_index, 2.0)
+ Report.result(Tests.node_found, result)
+
+ # 9) Close Asset Editor
+ general.close_pane("Asset Editor")
+ general.close_pane("Script Canvas")
+
+
+if __name__ == "__main__":
+ import ImportPathHelper as imports
+
+ imports.init()
+ from utils import Report
+
+ Report.start_test(ScriptEvents_AllParamDatatypes_CreationSuccess)
diff --git a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py
index 85d0b4523f..91d6b3e53e 100755
--- a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py
+++ b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py
@@ -113,10 +113,6 @@ class TestAutomation(TestAutomationBase):
from . import Debugger_HappyPath_TargetMultipleGraphs as test_module
self._run_test(request, workspace, editor, test_module)
- def test_Debugging_TargetMultipleGraphs(self, request, workspace, editor, launcher_platform, project):
- from . import Debugging_TargetMultipleGraphs as test_module
- self._run_test(request, workspace, editor, test_module)
-
@pytest.mark.parametrize("level", ["tmp_level"])
def test_Debugger_HappyPath_TargetMultipleEntities(self, request, workspace, editor, launcher_platform, project, level):
def teardown():
@@ -317,4 +313,30 @@ class TestScriptCanvasTests(object):
auto_test_mode=False,
timeout=60,
)
+
+ def test_ScriptEvents_AllParamDatatypes_CreationSuccess(self, request, workspace, editor, launcher_platform):
+ def teardown():
+ file_system.delete(
+ [os.path.join(workspace.paths.project(), "TestAssets", "test_file.scriptevents")], True, True
+ )
+ request.addfinalizer(teardown)
+ file_system.delete(
+ [os.path.join(workspace.paths.project(), "TestAssets", "test_file.scriptevents")], True, True
+ )
+ expected_lines = [
+ "Success: New Script Event created",
+ "Success: Child Event created",
+ "Success: New parameters added",
+ "Success: Script event file saved",
+ "Success: Node found in Script Canvas",
+ ]
+ hydra.launch_and_validate_results(
+ request,
+ TEST_DIRECTORY,
+ editor,
+ "ScriptEvents_AllParamDatatypes_CreationSuccess.py",
+ expected_lines,
+ auto_test_mode=False,
+ timeout=60,
+ )
\ No newline at end of file
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSimulatedBody.h b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSimulatedBody.h
index ed8a68dc24..9d45a17edc 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSimulatedBody.h
+++ b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSimulatedBody.h
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -68,6 +69,22 @@ namespace AzPhysics
return m_customUserData;
}
+ //! Helper functions for setting frame ID.
+ //! @param frameId Optionally set frame ID for the systems moving the actors back in time.
+ void SetFrameId(uint32_t frameId)
+ {
+ m_frameId = frameId;
+ }
+
+ //! Helper functions for getting the set frame ID.
+ //! @return Will return the frame ID.
+ uint32_t GetFrameId() const
+ {
+ return m_frameId;
+ }
+
+ static constexpr uint32_t UndefinedFrameId = AZStd::numeric_limits::max();
+
//! Perform a ray cast on this Simulated Body.
//! @param request The request to make.
//! @return Returns the closest hit, if any, against this simulated body.
@@ -126,6 +143,7 @@ namespace AzPhysics
SimulatedBodyEvents::OnTriggerExit m_triggerExitEvent;
void* m_customUserData = nullptr;
+ uint32_t m_frameId = UndefinedFrameId;
// helpers for reflecting to behavior context
SimulatedBodyEvents::OnCollisionBegin* GetOnCollisionBeginEvent();
diff --git a/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h b/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h
index ba1d2d1e06..749f457286 100644
--- a/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h
+++ b/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h
@@ -12,6 +12,7 @@
#pragma once
#include
+#include
#include
namespace AzFramework
@@ -35,12 +36,12 @@ namespace AzFramework
AzFramework::EntityContextId m_contextId;
};
- //! Interface for intersection requests, implement this interface for making your component
- //! render geometry intersectable.
+ //! Interface for intersection requests.
+ //! Implement this interface to make your component 'intersectable'.
class IntersectionRequests
: public AZ::EBusTraits
{
- //! Policy for notifying the Intersector bus of entities connected/disconnected to this ebus
+ //! Policy for notifying the Intersector bus of entities connected/disconnected to this EBus
//! so it updates the internal data of the entities
template
struct IntersectionRequestsConnectionPolicy
diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp
index e4833ccb3c..d5f02c957c 100644
--- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp
@@ -144,7 +144,7 @@ namespace AzFramework
z = AZStd::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1));
}
- return {x, y, z};
+ return { x, y, z };
}
void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform)
@@ -179,7 +179,7 @@ namespace AzFramework
{
const auto nextCamera = m_cameras.StepCamera(targetCamera, m_motionDelta, m_scrollDelta, deltaTime);
- m_motionDelta = ScreenVector{0, 0};
+ m_motionDelta = ScreenVector{ 0, 0 };
m_scrollDelta = 0.0f;
return nextCamera;
@@ -213,7 +213,10 @@ namespace AzFramework
auto& cameraInput = m_idleCameraInputs[i];
const bool canBegin = cameraInput->Beginning() &&
AZStd::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(),
- [](const auto& input) { return !input->Exclusive(); }) &&
+ [](const auto& input)
+ {
+ return !input->Exclusive();
+ }) &&
(!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty()));
if (canBegin)
@@ -231,7 +234,8 @@ namespace AzFramework
const Camera nextCamera = AZStd::accumulate(
AZStd::begin(m_activeCameraInputs), AZStd::end(m_activeCameraInputs), targetCamera,
- [cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera) {
+ [cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera)
+ {
acc = camera->StepCamera(acc, cursorDelta, scrollDelta, deltaTime);
return acc;
});
@@ -284,7 +288,8 @@ namespace AzFramework
bool RotateCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
{
- const ClickDetector::ClickEvent clickEvent = [&event, this] {
+ const ClickDetector::ClickEvent clickEvent = [&event, this]
+ {
if (const auto& input = AZStd::get_if(&event))
{
if (input->m_channelId == m_rotateChannelId)
@@ -330,7 +335,10 @@ namespace AzFramework
nextCamera.m_pitch -= float(cursorDelta.m_y) * ed_cameraSystemRotateSpeed;
nextCamera.m_yaw -= float(cursorDelta.m_x) * ed_cameraSystemRotateSpeed;
- const auto clampRotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
+ const auto clampRotation = [](const float angle)
+ {
+ return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi);
+ };
nextCamera.m_yaw = clampRotation(nextCamera.m_yaw);
// clamp pitch to be +-90 degrees
@@ -377,9 +385,10 @@ namespace AzFramework
const auto deltaPanX = float(cursorDelta.m_x) * panAxes.m_horizontalAxis * ed_cameraSystemPanSpeed;
const auto deltaPanY = float(cursorDelta.m_y) * panAxes.m_verticalAxis * ed_cameraSystemPanSpeed;
- const auto inv = [](const bool invert) {
- constexpr float Dir[] = {1.0f, -1.0f};
- return Dir[static_cast(invert)];
+ const auto inv = [](const bool invert)
+ {
+ constexpr float Dir[] = { 1.0f, -1.0f };
+ return Dir[aznumeric_cast(invert)];
};
nextCamera.m_lookAt += deltaPanX * inv(ed_cameraSystemPanInvertX);
@@ -475,7 +484,8 @@ namespace AzFramework
const auto axisY = translationBasis.GetBasisY();
const auto axisZ = translationBasis.GetBasisZ();
- const float speed = [boost = m_boost]() {
+ const float speed = [boost = m_boost]()
+ {
return ed_cameraSystemTranslateSpeed * (boost ? ed_cameraSystemBoostMultiplier : 1.0f);
}();
@@ -555,10 +565,12 @@ namespace AzFramework
if (Beginning())
{
- const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn] {
+ const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn]
+ {
if (lookAtFn)
{
- if (const auto lookAt = lookAtFn())
+ // pass through the camera's position and look vector for use in the lookAt function
+ if (const auto lookAt = lookAtFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY()))
{
auto transform = AZ::Transform::CreateLookAt(targetCamera.m_lookAt, *lookAt);
nextCamera.m_lookDist = -lookAt->GetDistance(targetCamera.m_lookAt);
@@ -692,14 +704,20 @@ namespace AzFramework
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const float deltaTime)
{
- const auto clamp_rotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
+ const auto clamp_rotation = [](const float angle)
+ {
+ return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi);
+ };
// keep yaw in 0 - 360 range
float targetYaw = clamp_rotation(targetCamera.m_yaw);
const float currentYaw = clamp_rotation(currentCamera.m_yaw);
// return the sign of the float input (-1, 0, 1)
- const auto sign = [](const float value) { return aznumeric_cast((0.0f < value) - (value < 0.0f)); };
+ const auto sign = [](const float value)
+ {
+ return aznumeric_cast((0.0f < value) - (value < 0.0f));
+ };
// ensure smooth transition when moving across 0 - 360 boundary
const float yawDelta = targetYaw - currentYaw;
@@ -727,26 +745,28 @@ namespace AzFramework
const auto& inputChannelId = inputChannel.GetInputChannelId();
const auto& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId();
- const bool wasMouseButton =
- AZStd::any_of(InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(), [inputChannelId](const auto& button) {
+ const bool wasMouseButton = AZStd::any_of(
+ InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(),
+ [inputChannelId](const auto& button)
+ {
return button == inputChannelId;
});
if (inputChannelId == InputDeviceMouse::Movement::X)
{
- return HorizontalMotionEvent{(int)inputChannel.GetValue()};
+ return HorizontalMotionEvent{ aznumeric_cast(inputChannel.GetValue()) };
}
else if (inputChannelId == InputDeviceMouse::Movement::Y)
{
- return VerticalMotionEvent{(int)inputChannel.GetValue()};
+ return VerticalMotionEvent{ aznumeric_cast(inputChannel.GetValue()) };
}
else if (inputChannelId == InputDeviceMouse::Movement::Z)
{
- return ScrollEvent{inputChannel.GetValue()};
+ return ScrollEvent{ inputChannel.GetValue() };
}
else if (wasMouseButton || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId))
{
- return DiscreteInputEvent{inputChannelId, inputChannel.GetState()};
+ return DiscreteInputEvent{ inputChannelId, inputChannel.GetState() };
}
return AZStd::monostate{};
diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h
index ec70fc00de..a02f796899 100644
--- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h
+++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h
@@ -34,9 +34,9 @@ namespace AzFramework
AZ::Vector3 m_lookAt = AZ::Vector3::CreateZero(); //!< Position of camera when m_lookDist is zero,
//!< or position of m_lookAt when m_lookDist is greater
//!< than zero.
- float m_yaw{0.0};
- float m_pitch{0.0};
- float m_lookDist{0.0}; //!< Zero gives first person free look, otherwise orbit about m_lookAt
+ float m_yaw{ 0.0 };
+ float m_pitch{ 0.0 };
+ float m_lookDist{ 0.0 }; //!< Zero gives first person free look, otherwise orbit about m_lookAt
//! View camera transform (v in MVP).
AZ::Transform View() const;
@@ -195,7 +195,11 @@ namespace AzFramework
inline bool Cameras::Exclusive() const
{
return AZStd::any_of(
- m_activeCameraInputs.begin(), m_activeCameraInputs.end(), [](const auto& cameraInput) { return cameraInput->Exclusive(); });
+ m_activeCameraInputs.begin(), m_activeCameraInputs.end(),
+ [](const auto& cameraInput)
+ {
+ return cameraInput->Exclusive();
+ });
}
//! Responsible for updating a series of cameras given various inputs.
@@ -209,7 +213,7 @@ namespace AzFramework
private:
ScreenVector m_motionDelta; //!< The delta used for look/orbit/pan (rotation + translation) - two dimensional.
- float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional.
+ float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional.
};
class RotateCameraInput : public CameraInput
@@ -237,7 +241,7 @@ namespace AzFramework
inline PanAxes LookPan(const Camera& camera)
{
const AZ::Matrix3x3 orientation = camera.Rotation();
- return {orientation.GetBasisX(), orientation.GetBasisZ()};
+ return { orientation.GetBasisX(), orientation.GetBasisZ() };
}
inline PanAxes OrbitPan(const Camera& camera)
@@ -245,12 +249,13 @@ namespace AzFramework
const AZ::Matrix3x3 orientation = camera.Rotation();
const auto basisX = orientation.GetBasisX();
- const auto basisY = [&orientation] {
+ const auto basisY = [&orientation]
+ {
const auto forward = orientation.GetBasisY();
return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized();
}();
- return {basisX, basisY};
+ return { basisX, basisY };
}
class PanCameraInput : public CameraInput
@@ -285,7 +290,8 @@ namespace AzFramework
const AZ::Matrix3x3 orientation = camera.Rotation();
const auto basisX = orientation.GetBasisX();
- const auto basisY = [&orientation] {
+ const auto basisY = [&orientation]
+ {
const auto forward = orientation.GetBasisY();
return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized();
}();
@@ -398,7 +404,7 @@ namespace AzFramework
class OrbitCameraInput : public CameraInput
{
public:
- using LookAtFn = AZStd::function()>;
+ using LookAtFn = AZStd::function(const AZ::Vector3& position, const AZ::Vector3& direction)>;
// CameraInput overrides ...
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h
index 884562d7e8..28971dc779 100644
--- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h
+++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h
@@ -41,6 +41,7 @@ namespace AzManipulatorTestFramework
AZStd::optional ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) override;
AZStd::optional ViewportScreenToWorldRay(
const AzFramework::ScreenPoint& screenPosition) override;
+ float DeviceScalingFactor() override;
private:
// ViewportInteractionRequestBus ...
bool GridSnappingEnabled();
diff --git a/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp b/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp
index ebef9dea30..7d32187a74 100644
--- a/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp
+++ b/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp
@@ -127,4 +127,9 @@ namespace AzManipulatorTestFramework
{
return {};
}
-} // namespace AzManipulatorTestFramework
+
+ float ViewportInteraction::DeviceScalingFactor()
+ {
+ return 1.0f;
+ }
+}// namespace AzManipulatorTestFramework
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Menu.qss b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Menu.qss
index af9c675f23..7f48637cc8 100644
--- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Menu.qss
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Menu.qss
@@ -49,7 +49,7 @@ QMenu::right-arrow
QMenu::icon
{
- right: 8px;
+ right: 20px;
}
QMenu::indicator:checked
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/link.svg b/Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/link.svg
new file mode 100644
index 0000000000..dfd21d157f
--- /dev/null
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/link.svg
@@ -0,0 +1,4 @@
+
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc b/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc
index dbbf0e78e2..7b0c6530ab 100644
--- a/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc
@@ -13,5 +13,6 @@
Notifications/checkmark.svg
Notifications/download.svg
+ Notifications/link.svg
diff --git a/Code/Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h b/Code/Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h
index 0090ce066b..855b4fe416 100644
--- a/Code/Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h
+++ b/Code/Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h
@@ -39,4 +39,3 @@
#define AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_EDITOR_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_METRICS_TESTS true
-#define AZ_TRAIT_DISABLE_ASSET_JOB_PARALLEL_TESTS true
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp
index 439789f11b..7fd11ff9bf 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp
@@ -57,7 +57,6 @@ namespace AzToolsFramework
"Couldn't get prefab loader interface, it's a requirement for PrefabEntityOwnership system to work");
m_rootInstance = AZStd::unique_ptr(m_prefabSystemComponent->CreatePrefab({}, {}, "NewLevel.prefab"));
-
m_sliceOwnershipService.BusConnect(m_entityContextId);
m_sliceOwnershipService.m_shouldAssertForLegacySlicesUsage = m_shouldAssertForLegacySlicesUsage;
m_editorSliceOwnershipService.BusConnect();
@@ -91,14 +90,17 @@ namespace AzToolsFramework
void PrefabEditorEntityOwnershipService::Reset()
{
- Prefab::TemplateId templateId = m_rootInstance->GetTemplateId();
- if (templateId != Prefab::InvalidTemplateId)
+ if (m_rootInstance)
{
- m_rootInstance->SetTemplateId(Prefab::InvalidTemplateId);
- m_prefabSystemComponent->RemoveTemplate(templateId);
+ Prefab::TemplateId templateId = m_rootInstance->GetTemplateId();
+ if (templateId != Prefab::InvalidTemplateId)
+ {
+ m_rootInstance->SetTemplateId(Prefab::InvalidTemplateId);
+ m_prefabSystemComponent->RemoveTemplate(templateId);
+ }
+ m_rootInstance->Reset();
+ m_rootInstance->SetContainerEntityName("Level");
}
- m_rootInstance->Reset();
- m_rootInstance->SetContainerEntityName("Level");
AzFramework::EntityOwnershipServiceNotificationBus::Event(
m_entityContextId, &AzFramework::EntityOwnershipServiceNotificationBus::Events::OnEntityOwnershipServiceReset);
@@ -202,7 +204,7 @@ namespace AzToolsFramework
}
m_rootInstance->SetTemplateId(templateId);
- m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GetRelativePathToProject(filename));
+ m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GenerateRelativePath(filename));
m_rootInstance->SetContainerEntityName("Level");
m_prefabSystemComponent->PropagateTemplateChanges(templateId);
@@ -220,7 +222,7 @@ namespace AzToolsFramework
bool PrefabEditorEntityOwnershipService::SaveToStream(AZ::IO::GenericStream& stream, AZStd::string_view filename)
{
- AZ::IO::Path relativePath = m_loaderInterface->GetRelativePathToProject(filename);
+ AZ::IO::Path relativePath = m_loaderInterface->GenerateRelativePath(filename);
AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath);
m_rootInstance->SetTemplateSourcePath(relativePath);
@@ -267,7 +269,7 @@ namespace AzToolsFramework
void PrefabEditorEntityOwnershipService::CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename)
{
- AZ::IO::Path relativePath = m_loaderInterface->GetRelativePathToProject(filename);
+ AZ::IO::Path relativePath = m_loaderInterface->GenerateRelativePath(filename);
AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath);
m_rootInstance->SetTemplateSourcePath(relativePath);
@@ -378,7 +380,12 @@ namespace AzToolsFramework
Prefab::InstanceOptionalReference PrefabEditorEntityOwnershipService::GetRootPrefabInstance()
{
AZ_Assert(m_rootInstance, "A valid root prefab instance couldn't be found in PrefabEditorEntityOwnershipService.");
- return *m_rootInstance;
+ if (m_rootInstance)
+ {
+ return *m_rootInstance;
+ }
+
+ return AZStd::nullopt;
}
const AZStd::vector>& PrefabEditorEntityOwnershipService::GetPlayInEditorAssetData()
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp
index 836140eb74..39351df486 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp
@@ -124,7 +124,7 @@ namespace AzToolsFramework
"PrefabLoaderInterface could not be found. It is required to load Prefab Instances");
// Make sure we have a relative path
- instance->m_templateSourcePath = loaderInterface->GetRelativePathToProject(instance->m_templateSourcePath);
+ instance->m_templateSourcePath = loaderInterface->GenerateRelativePath(instance->m_templateSourcePath);
TemplateId templateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(instance->GetTemplateSourcePath());
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp
index 2965148172..e4507227b5 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp
@@ -18,7 +18,9 @@
#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -112,7 +114,7 @@ namespace AzToolsFramework
return InvalidTemplateId;
}
- AZ::IO::Path relativePath = GetRelativePathToProject(originPath);
+ AZ::IO::Path relativePath = GenerateRelativePath(originPath);
// Cyclical dependency detected if the prefab file is already part of the progressed
// file path set.
@@ -385,21 +387,100 @@ namespace AzToolsFramework
AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path).MakePreferred();
if (pathWithOSSeparator.IsAbsolute())
{
+ // If an absolute path was passed in, just return it as-is.
return path;
}
- return AZ::IO::Path(m_projectPathWithOsSeparator).Append(pathWithOSSeparator);
+ // A relative path was passed in, so try to turn it back into an absolute path.
+
+ AZ::IO::Path fullPath;
+
+ bool pathFound = false;
+ AZ::Data::AssetInfo assetInfo;
+ AZStd::string rootFolder;
+ AZStd::string inputPath(path.Native());
+
+ // Given an input path that's expected to exist, try to look it up.
+ AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
+ pathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath,
+ inputPath.c_str(), assetInfo, rootFolder);
+
+ if (pathFound)
+ {
+ // The asset system provided us with a valid root folder and relative path, so return it.
+ fullPath = AZ::IO::Path(rootFolder) / assetInfo.m_relativePath;
+ }
+ else
+ {
+ // If for some reason the Asset system couldn't provide a relative path, provide some fallback logic.
+
+ // Check to see if the AssetProcessor is ready. If it *is* and we didn't get a path, print an error then follow
+ // the fallback logic. If it's *not* ready, we're probably either extremely early in a tool startup flow or inside
+ // a unit test, so just execute the fallback logic without an error.
+ [[maybe_unused]] bool assetProcessorReady = false;
+ AzFramework::AssetSystemRequestBus::BroadcastResult(
+ assetProcessorReady, &AzFramework::AssetSystemRequestBus::Events::AssetProcessorIsReady);
+
+ AZ_Error(
+ "Prefab", !assetProcessorReady, "Full source path for '%.*s' could not be determined. Using fallback logic.",
+ AZ_STRING_ARG(path.Native()));
+
+ // If a relative path was passed in, make it relative to the project root.
+ fullPath = AZ::IO::Path(m_projectPathWithOsSeparator).Append(pathWithOSSeparator);
+ }
+
+ return fullPath;
}
- AZ::IO::Path PrefabLoader::GetRelativePathToProject(AZ::IO::PathView path)
+ AZ::IO::Path PrefabLoader::GenerateRelativePath(AZ::IO::PathView path)
{
- AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path.Native()).MakePreferred();
- if (!pathWithOSSeparator.IsAbsolute())
+ bool pathFound = false;
+
+ AZStd::string relativePath;
+ AZStd::string rootFolder;
+ AZ::IO::Path finalPath;
+
+ // The asset system allows for paths to be relative to multiple root folders, using a priority system.
+ // This request will make the input path relative to the most appropriate, highest-priority root folder.
+ AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
+ pathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GenerateRelativeSourcePath, path.Native(),
+ relativePath, rootFolder);
+
+ if (pathFound && !relativePath.empty())
{
- return path;
+ // A relative path was generated successfully, so return it.
+ finalPath = relativePath;
+ }
+ else
+ {
+ // If for some reason the Asset system couldn't provide a relative path, provide some fallback logic.
+
+ // Check to see if the AssetProcessor is ready. If it *is* and we didn't get a path, print an error then follow
+ // the fallback logic. If it's *not* ready, we're probably either extremely early in a tool startup flow or inside
+ // a unit test, so just execute the fallback logic without an error.
+ [[maybe_unused]] bool assetProcessorReady = false;
+ AzFramework::AssetSystemRequestBus::BroadcastResult(
+ assetProcessorReady, &AzFramework::AssetSystemRequestBus::Events::AssetProcessorIsReady);
+
+ AZ_Error("Prefab", !assetProcessorReady,
+ "Relative source path for '%.*s' could not be determined. Using project path as relative root.",
+ AZ_STRING_ARG(path.Native()));
+
+ AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path.Native()).MakePreferred();
+
+ if (pathWithOSSeparator.IsAbsolute())
+ {
+ // If an absolute path was passed in, make it relative to the project path.
+ finalPath = AZ::IO::Path(path.Native(), '/').MakePreferred().LexicallyRelative(m_projectPathWithSlashSeparator);
+ }
+ else
+ {
+ // If a relative path was passed in, just return it.
+ finalPath = path;
+ }
}
- return AZ::IO::Path(path.Native(), '/').MakePreferred().LexicallyRelative(m_projectPathWithSlashSeparator);
+ return finalPath;
}
AZ::IO::Path PrefabLoaderInterface::GeneratePath()
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h
index d11cb62ca3..aed24e153e 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h
@@ -91,9 +91,11 @@ namespace AzToolsFramework
//! The path will always have the correct separator for the current OS
AZ::IO::Path GetFullPath(AZ::IO::PathView path) override;
- //! Converts path into a relative path to the project, this will be the paths in .prefab file.
- //! The path will always have '/' separator.
- AZ::IO::Path GetRelativePathToProject(AZ::IO::PathView path) override;
+ //! Converts path into a path that's relative to the highest-priority containing folder of all the folders registered
+ //! with the engine.
+ //! This path will be the path that appears in the .prefab file.
+ //! The path will always use the '/' separator.
+ AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) override;
//! Returns if the path is a valid path for a prefab
static bool IsValidPrefabPath(AZ::IO::PathView path);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
index a4055fb15a..d71fbff80f 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
@@ -74,9 +74,11 @@ namespace AzToolsFramework
//! The path will always have the correct separator for the current OS
virtual AZ::IO::Path GetFullPath(AZ::IO::PathView path) = 0;
- //! Converts path into a relative path to the current project, this will be the paths in .prefab file.
- //! The path will always have '/' separator.
- virtual AZ::IO::Path GetRelativePathToProject(AZ::IO::PathView path) = 0;
+ //! Converts path into a path that's relative to the highest-priority containing folder of all the folders registered
+ //! with the engine.
+ //! This path will be the path that appears in the .prefab file.
+ //! The path will always use the '/' separator.
+ virtual AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) = 0;
protected:
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
index 0181050a32..9dd5199ea2 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
@@ -318,7 +318,7 @@ namespace AzToolsFramework
}
//Detect whether this instantiation would produce a cyclical dependency
- auto relativePath = m_prefabLoaderInterface->GetRelativePathToProject(filePath);
+ auto relativePath = m_prefabLoaderInterface->GenerateRelativePath(filePath);
Prefab::TemplateId templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(relativePath);
if (templateId == InvalidTemplateId)
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp
index c4e6415b02..0136f791b3 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp
@@ -95,7 +95,7 @@ namespace AzToolsFramework
const AZStd::vector& entities, AZStd::vector>&& instancesToConsume,
AZ::IO::PathView filePath, AZStd::unique_ptr containerEntity, bool shouldCreateLinks)
{
- AZ::IO::Path relativeFilePath = m_prefabLoader.GetRelativePathToProject(filePath);
+ AZ::IO::Path relativeFilePath = m_prefabLoader.GenerateRelativePath(filePath);
if (GetTemplateIdFromFilePath(relativeFilePath) != InvalidTemplateId)
{
AZ_Error("Prefab", false,
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
index cc65b61908..8293614525 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
@@ -172,7 +172,7 @@ namespace AzToolsFramework
const int autoExpandDelayMilliseconds = 2500;
m_gui->m_objectTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
- m_gui->m_objectTree->setEditTriggers(QAbstractItemView::EditKeyPressed);
+ SetDefaultTreeViewEditTriggers();
m_gui->m_objectTree->setAutoExpandDelay(autoExpandDelayMilliseconds);
m_gui->m_objectTree->setDragEnabled(true);
m_gui->m_objectTree->setDropIndicatorShown(true);
@@ -850,6 +850,11 @@ namespace AzToolsFramework
addAction(m_actionGoToEntitiesInViewport);
}
+ void EntityOutlinerWidget::SetDefaultTreeViewEditTriggers()
+ {
+ m_gui->m_objectTree->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::EditKeyPressed);
+ }
+
void EntityOutlinerWidget::OnEntityPickModeStarted()
{
m_gui->m_objectTree->setDragEnabled(false);
@@ -862,7 +867,7 @@ namespace AzToolsFramework
{
m_gui->m_objectTree->setDragEnabled(true);
m_gui->m_objectTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
- m_gui->m_objectTree->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
+ SetDefaultTreeViewEditTriggers();
m_inObjectPickMode = false;
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx
index 9a02febab2..6e3979a21e 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx
@@ -166,6 +166,8 @@ namespace AzToolsFramework
// to a given entity
void QueueScrollToNewContent(const AZ::EntityId& entityId) override;
+ void SetDefaultTreeViewEditTriggers();
+
void ScrollToNewContent();
bool m_scrollToNewContentQueued;
bool m_scrollToSelectedEntity;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
index 3edc190fb7..61d4433c0e 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
@@ -333,7 +333,8 @@ namespace AzToolsFramework
}
}
- auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, s_prefabLoaderInterface->GetRelativePathToProject(prefabFilePath.data()));
+ auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(
+ selectedEntities, s_prefabLoaderInterface->GenerateRelativePath(prefabFilePath.data()));
if (!createPrefabOutcome.IsSuccess())
{
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h
index 8e91dc945d..91eee18cb7 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h
@@ -165,15 +165,18 @@ namespace AzToolsFramework
virtual bool AngleSnappingEnabled() = 0;
/// Return the angle snapping/step size.
virtual float AngleStep() = 0;
- /// Transform a point in world space to screen space coordinates.
+ /// Transform a point in world space to screen space coordinates in Qt Widget space.
+ /// Multiply by DeviceScalingFactor to get the position in viewport pixel space.
virtual AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition) = 0;
- /// Transform a point in screen space coordinates to a vector in world space based on clip space depth.
+ /// Transform a point from Qt widget screen space to world space based on the given clip space depth.
/// Depth specifies a relative camera depth to project in the range of [0.f, 1.f].
/// Returns the world space position if successful.
virtual AZStd::optional ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) = 0;
/// Casts a point in screen space to a ray in world space originating from the viewport camera frustum's near plane.
/// Returns a ray containing the ray's origin and a direction normal, if successful.
virtual AZStd::optional ViewportScreenToWorldRay(const AzFramework::ScreenPoint& screenPosition) = 0;
+ /// Gets the DPI scaling factor that translates Qt widget space into viewport pixel space.
+ virtual float DeviceScalingFactor() = 0;
protected:
~ViewportInteractionRequests() = default;
diff --git a/Code/LauncherUnified/launcher_generator.cmake b/Code/LauncherUnified/launcher_generator.cmake
index edb6655411..c5d60eb29e 100644
--- a/Code/LauncherUnified/launcher_generator.cmake
+++ b/Code/LauncherUnified/launcher_generator.cmake
@@ -179,6 +179,7 @@ function(ly_delayed_generate_static_modules_inl)
${launcher_unified_binary_dir}/${project_name}.GameLauncher/Includes/StaticModules.inl
)
+ ly_target_link_libraries(${project_name}.GameLauncher PRIVATE ${all_game_gem_dependencies})
if(PAL_TRAIT_BUILD_SERVER_SUPPORTED)
get_property(server_gem_dependencies GLOBAL PROPERTY LY_STATIC_MODULE_PROJECTS_DEPENDENCIES_${project_name}.ServerLauncher)
@@ -204,6 +205,7 @@ function(ly_delayed_generate_static_modules_inl)
${launcher_unified_binary_dir}/${project_name}.ServerLauncher/Includes/StaticModules.inl
)
+ ly_target_link_libraries(${project_name}.ServerLauncher PRIVATE ${all_server_gem_dependencies})
endif()
endforeach()
endif()
diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp
index c8bd157b65..e0ba106875 100644
--- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp
+++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp
@@ -137,8 +137,20 @@ namespace AzAssetBrowserRequestHandlerPrivate
entityName = AZStd::string::format("Entity%d", GetIEditor()->GetObjectManager()->GetObjectCount());
}
- AZ::Entity* newEntity = aznew AZ::Entity(entityName.c_str());
- EditorEntityContextRequestBus::Broadcast(&EditorEntityContextRequests::AddRequiredComponents, *newEntity);
+ AZ::EntityId targetEntityId;
+ EditorRequests::Bus::BroadcastResult(targetEntityId, &EditorRequests::CreateNewEntityAtPosition, worldTransform.GetTranslation(), AZ::EntityId());
+
+ AZ::Entity* newEntity = nullptr;
+ AZ::ComponentApplicationBus::BroadcastResult(newEntity, &AZ::ComponentApplicationRequests::FindEntity, targetEntityId);
+
+ if (newEntity == nullptr)
+ {
+ return;
+ }
+
+ newEntity->SetName(entityName);
+
+ newEntity->Deactivate();
// Create component.
AZ::Component* newComponent = newEntity->CreateComponent(componentTypeId);
@@ -151,15 +163,7 @@ namespace AzAssetBrowserRequestHandlerPrivate
newEntity->AddComponent(newComponent);
}
- // Set entity position.
- auto* transformComponent = newEntity->FindComponent();
- if (transformComponent)
- {
- transformComponent->SetWorldTM(worldTransform);
- }
-
- // Add the entity to the editor context, which activates it and creates the sandbox object.
- EditorEntityContextRequestBus::Broadcast(&EditorEntityContextRequests::AddEditorEntity, newEntity);
+ newEntity->Activate();
// set asset after components have been activated in AddEditorEntity method
if (newComponent)
diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp
index ecd11da817..989d6e407d 100644
--- a/Code/Sandbox/Editor/EditorViewportWidget.cpp
+++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp
@@ -1221,50 +1221,73 @@ void EditorViewportWidget::SetViewportId(int id)
AzFramework::ReloadCameraKeyBindings();
auto controller = AZStd::make_shared();
- controller->SetCameraListBuilderCallback([](AzFramework::Cameras& cameras)
- {
- auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::CameraFreeLookButton);
- auto firstPersonPanCamera =
- AZStd::make_shared(AzFramework::CameraFreePanButton, AzFramework::LookPan);
- auto firstPersonTranslateCamera = AZStd::make_shared(AzFramework::LookTranslation);
- auto firstPersonWheelCamera = AZStd::make_shared();
+ controller->SetCameraListBuilderCallback(
+ [](AzFramework::Cameras& cameras)
+ {
+ auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::CameraFreeLookButton);
+ auto firstPersonPanCamera =
+ AZStd::make_shared(AzFramework::CameraFreePanButton, AzFramework::LookPan);
+ auto firstPersonTranslateCamera = AZStd::make_shared(AzFramework::LookTranslation);
+ auto firstPersonWheelCamera = AZStd::make_shared();
- auto orbitCamera = AZStd::make_shared();
- orbitCamera->SetLookAtFn([]() -> AZStd::optional {
- AZStd::optional manipulatorTransform;
- AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
- manipulatorTransform, AzToolsFramework::GetEntityContextId(),
- &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
+ auto orbitCamera = AZStd::make_shared();
+ orbitCamera->SetLookAtFn(
+ [](const AZ::Vector3& position, const AZ::Vector3& direction) -> AZStd::optional
+ {
+ AZStd::optional manipulatorTransform;
+ AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
+ manipulatorTransform, AzToolsFramework::GetEntityContextId(),
+ &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
- if (manipulatorTransform)
- {
- return manipulatorTransform->GetTranslation();
- }
+ // initially attempt to use manipulator transform if one exists (there is a selection)
+ if (manipulatorTransform)
+ {
+ return manipulatorTransform->GetTranslation();
+ }
- return {};
+ const float RayDistance = 1000.0f;
+ AzFramework::RenderGeometry::RayRequest ray;
+ ray.m_startWorldPosition = position;
+ ray.m_endWorldPosition = position + direction * RayDistance;
+ ray.m_onlyVisible = true;
+
+ AzFramework::RenderGeometry::RayResult renderGeometryIntersectionResult;
+ AzFramework::RenderGeometry::IntersectorBus::EventResult(
+ renderGeometryIntersectionResult, AzToolsFramework::GetEntityContextId(),
+ &AzFramework::RenderGeometry::IntersectorInterface::RayIntersect, ray);
+
+ // attempt a ray intersection with any visible mesh and return the intersection position if successful
+ if (renderGeometryIntersectionResult)
+ {
+ return renderGeometryIntersectionResult.m_worldPosition;
+ }
+
+ // if there is no selection or no intersection, fallback to default camera orbit behavior (ground plane
+ // intersection)
+ return {};
+ });
+
+ auto orbitRotateCamera = AZStd::make_shared(AzFramework::CameraOrbitLookButton);
+ auto orbitTranslateCamera = AZStd::make_shared(AzFramework::OrbitTranslation);
+ auto orbitDollyWheelCamera = AZStd::make_shared();
+ auto orbitDollyMoveCamera =
+ AZStd::make_shared(AzFramework::CameraOrbitDollyButton);
+ auto orbitPanCamera =
+ AZStd::make_shared(AzFramework::CameraOrbitPanButton, AzFramework::OrbitPan);
+
+ orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
+ orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
+ orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera);
+ orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera);
+ orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera);
+
+ cameras.AddCamera(firstPersonRotateCamera);
+ cameras.AddCamera(firstPersonPanCamera);
+ cameras.AddCamera(firstPersonTranslateCamera);
+ cameras.AddCamera(firstPersonWheelCamera);
+ cameras.AddCamera(orbitCamera);
});
- auto orbitRotateCamera = AZStd::make_shared(AzFramework::CameraOrbitLookButton);
- auto orbitTranslateCamera = AZStd::make_shared(AzFramework::OrbitTranslation);
- auto orbitDollyWheelCamera = AZStd::make_shared();
- auto orbitDollyMoveCamera =
- AZStd::make_shared(AzFramework::CameraOrbitDollyButton);
- auto orbitPanCamera =
- AZStd::make_shared(AzFramework::CameraOrbitPanButton, AzFramework::OrbitPan);
-
- orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
- orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
- orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera);
- orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera);
- orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera);
-
- cameras.AddCamera(firstPersonRotateCamera);
- cameras.AddCamera(firstPersonPanCamera);
- cameras.AddCamera(firstPersonTranslateCamera);
- cameras.AddCamera(firstPersonWheelCamera);
- cameras.AddCamera(orbitCamera);
- });
-
m_renderViewport->GetControllerList()->Add(controller);
}
else
diff --git a/Code/Sandbox/Editor/RenderViewport.h b/Code/Sandbox/Editor/RenderViewport.h
index d70dd59b98..b45c92b1c8 100644
--- a/Code/Sandbox/Editor/RenderViewport.h
+++ b/Code/Sandbox/Editor/RenderViewport.h
@@ -200,6 +200,7 @@ public:
{
return {};
}
+ float DeviceScalingFactor() override { return 1.0f; }
// AzToolsFramework::ViewportFreezeRequestBus
bool IsViewportInputFrozen() override;
diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss
index 5eb92964dd..a85b911c15 100644
--- a/Code/Tools/ProjectManager/Resources/ProjectManager.qss
+++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qss
@@ -336,4 +336,31 @@ QTabBar::tab:pressed
max-width:210px;;
min-height:278px;
max-height:278px;
-}
\ No newline at end of file
+}
+
+/************** Gem Catalog **************/
+
+#GemCatalogTitle {
+ font-size: 18px;
+}
+
+/************** Gem Catalog (Inspector) **************/
+
+#GemCatalogInspector {
+ background-color: #444444;
+}
+
+/************** Gem Catalog (Filter/left pane) **************/
+
+#GemCatalogFilterWidget {
+ background-color: #444444;
+}
+
+#GemCatalogHeaderWidget {
+ background-color: #1E252F;
+}
+
+#GemCatalogFilterCategoryTitle {
+ font-size: 12px;
+ font-weight: 600;
+}
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp
index 6e9ad42017..6402121e4a 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp
@@ -25,10 +25,12 @@ namespace O3DE::ProjectManager
hLayout->setMargin(0);
setLayout(hLayout);
- setStyleSheet("background-color: #1E252F;");
+ setObjectName("GemCatalogHeaderWidget");
+
+ hLayout->addSpacing(7);
QLabel* titleLabel = new QLabel(tr("Gem Catalog"));
- titleLabel->setStyleSheet("font-size: 21px;");
+ titleLabel->setObjectName("GemCatalogTitle");
hLayout->addWidget(titleLabel);
hLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
@@ -42,7 +44,7 @@ namespace O3DE::ProjectManager
hLayout->addWidget(filterLineEdit);
hLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
- hLayout->addSpacerItem(new QSpacerItem(220, 0, QSizePolicy::Fixed));
+ hLayout->addSpacerItem(new QSpacerItem(140, 0, QSizePolicy::Fixed));
setFixedHeight(60);
}
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp
index 3ece7760cf..a6a4e95ff9 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp
@@ -43,7 +43,6 @@ namespace O3DE::ProjectManager
m_collapseButton->setFlat(true);
m_collapseButton->setFocusPolicy(Qt::NoFocus);
m_collapseButton->setFixedWidth(s_collapseButtonSize);
- m_collapseButton->setStyleSheet("border: 0px; border-radius: 0px;");
connect(m_collapseButton, &QPushButton::clicked, this, [=]()
{
UpdateCollapseState();
@@ -52,7 +51,7 @@ namespace O3DE::ProjectManager
// Category title
QLabel* headerLabel = new QLabel(header);
- headerLabel->setStyleSheet("font-size: 11pt;");
+ headerLabel->setObjectName("GemCatalogFilterCategoryTitle");
collapseLayout->addWidget(headerLabel);
vLayout->addLayout(collapseLayout);
@@ -79,14 +78,14 @@ namespace O3DE::ProjectManager
elementWidget->setLayout(elementLayout);
QCheckBox* checkbox = new QCheckBox(elementNames[i]);
- checkbox->setStyleSheet("font-size: 11pt;");
+ checkbox->setStyleSheet("font-size: 12px;");
m_buttonGroup->addButton(checkbox);
elementLayout->addWidget(checkbox);
elementLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
QLabel* countLabel = new QLabel(QString::number(elementCounts[i]));
- countLabel->setStyleSheet("font-size: 11pt; background-color: #333333; border-radius: 3px; color: #94D2FF;");
+ countLabel->setStyleSheet("font-size: 12px; background-color: #333333; border-radius: 3px; color: #94D2FF;");
elementLayout->addWidget(countLabel);
m_elementWidgets.push_back(elementWidget);
@@ -110,6 +109,8 @@ namespace O3DE::ProjectManager
}
}
+ vLayout->addSpacing(5);
+
// Separating line
QFrame* hLine = new QFrame();
hLine->setFrameShape(QFrame::HLine);
@@ -181,6 +182,8 @@ namespace O3DE::ProjectManager
: QScrollArea(parent)
, m_filterProxyModel(filterProxyModel)
{
+ setObjectName("GemCatalogFilterWidget");
+
m_gemModel = m_filterProxyModel->GetSourceModel();
setWidgetResizable(true);
@@ -195,7 +198,7 @@ namespace O3DE::ProjectManager
mainWidget->setLayout(m_mainLayout);
QLabel* filterByLabel = new QLabel("Filter by");
- filterByLabel->setStyleSheet("font-size: 15pt;");
+ filterByLabel->setStyleSheet("font-size: 16px;");
m_mainLayout->addWidget(filterByLabel);
AddGemOriginFilter();
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp
index 6276ddc996..3ecc18231e 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp
@@ -23,6 +23,7 @@ namespace O3DE::ProjectManager
: QScrollArea(parent)
, m_model(model)
{
+ setObjectName("GemCatalogInspector");
setWidgetResizable(true);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
@@ -85,7 +86,7 @@ namespace O3DE::ProjectManager
QLabel* GemInspector::CreateStyledLabel(QLayout* layout, int fontSize, const QString& colorCodeString)
{
QLabel* result = new QLabel();
- result->setStyleSheet(QString("font-size: %1pt; color: %2;").arg(QString::number(fontSize), colorCodeString));
+ result->setStyleSheet(QString("font-size: %1px; color: %2;").arg(QString::number(fontSize), colorCodeString));
layout->addWidget(result);
return result;
}
@@ -93,13 +94,13 @@ namespace O3DE::ProjectManager
void GemInspector::InitMainWidget()
{
// Gem name, creator and summary
- m_nameLabel = CreateStyledLabel(m_mainLayout, 17, s_headerColor);
+ m_nameLabel = CreateStyledLabel(m_mainLayout, 18, s_headerColor);
m_creatorLabel = CreateStyledLabel(m_mainLayout, 12, s_creatorColor);
m_mainLayout->addSpacing(5);
// TODO: QLabel seems to have issues determining the right sizeHint() for our font with the given font size.
// This results into squeezed elements in the layout in case the text is a little longer than a sentence.
- m_summaryLabel = new QLabel();//CreateLabel(m_mainLayout, 12, s_textColor);
+ m_summaryLabel = CreateStyledLabel(m_mainLayout, 12, s_textColor);
m_mainLayout->addWidget(m_summaryLabel);
m_summaryLabel->setWordWrap(true);
m_mainLayout->addSpacing(5);
@@ -146,9 +147,9 @@ namespace O3DE::ProjectManager
QLabel* additionalInfoLabel = CreateStyledLabel(m_mainLayout, 14, s_headerColor);
additionalInfoLabel->setText("Additional Information");
- m_versionLabel = CreateStyledLabel(m_mainLayout, 11, s_textColor);
- m_lastUpdatedLabel = CreateStyledLabel(m_mainLayout, 11, s_textColor);
- m_binarySizeLabel = CreateStyledLabel(m_mainLayout, 11, s_textColor);
+ m_versionLabel = CreateStyledLabel(m_mainLayout, 12, s_textColor);
+ m_lastUpdatedLabel = CreateStyledLabel(m_mainLayout, 12, s_textColor);
+ m_binarySizeLabel = CreateStyledLabel(m_mainLayout, 12, s_textColor);
}
GemInspector::GemsSubWidget::GemsSubWidget(QWidget* parent)
@@ -159,8 +160,8 @@ namespace O3DE::ProjectManager
m_layout->setMargin(0);
setLayout(m_layout);
- m_titleLabel = GemInspector::CreateStyledLabel(m_layout, 15, s_headerColor);
- m_textLabel = GemInspector::CreateStyledLabel(m_layout, 9, s_textColor);
+ m_titleLabel = GemInspector::CreateStyledLabel(m_layout, 16, s_headerColor);
+ m_textLabel = GemInspector::CreateStyledLabel(m_layout, 10, s_textColor);
m_textLabel->setWordWrap(true);
m_tagWidget = new TagContainerWidget();
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp
index a40e5eb447..57200e3b36 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp
@@ -49,7 +49,7 @@ namespace O3DE::ProjectManager
painter->setRenderHint(QPainter::Antialiasing);
QRect fullRect, itemRect, contentRect;
- CalcRects(options, modelIndex, fullRect, itemRect, contentRect);
+ CalcRects(options, fullRect, itemRect, contentRect);
QFont standardFont(options.font);
standardFont.setPixelSize(s_fontSize);
@@ -99,7 +99,7 @@ namespace O3DE::ProjectManager
painter->drawText(gemCreatorRect, Qt::TextSingleLine, gemCreator);
// Gem summary
- const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - s_itemMargins.right() * 4, contentRect.height());
+ const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - s_itemMargins.right() * 3, contentRect.height());
const QRect summaryRect = QRect(/*topLeft=*/QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), summarySize);
painter->setFont(standardFont);
@@ -134,12 +134,10 @@ namespace O3DE::ProjectManager
return QStyledItemDelegate::editorEvent(event, model, option, modelIndex);
}
- void GemItemDelegate::CalcRects(const QStyleOptionViewItem& option, const QModelIndex& modelIndex, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const
+ void GemItemDelegate::CalcRects(const QStyleOptionViewItem& option, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const
{
- const bool isFirst = modelIndex.row() == 0;
-
outFullRect = QRect(option.rect);
- outItemRect = QRect(outFullRect.adjusted(s_itemMargins.left(), isFirst ? s_itemMargins.top() * 2 : s_itemMargins.top(), -s_itemMargins.right(), -s_itemMargins.bottom()));
+ outItemRect = QRect(outFullRect.adjusted(s_itemMargins.left(), s_itemMargins.top(), -s_itemMargins.right(), -s_itemMargins.bottom()));
outContentRect = QRect(outItemRect.adjusted(s_contentMargins.left(), s_contentMargins.top(), -s_contentMargins.right(), -s_contentMargins.bottom()));
}
@@ -194,12 +192,12 @@ namespace O3DE::ProjectManager
painter->setBrush(m_buttonEnabledColor);
painter->setPen(m_buttonEnabledColor);
- circleCenter = buttonRect.center() + QPoint(buttonRect.width() / 2 - s_buttonBorderRadius, 1);
+ circleCenter = buttonRect.center() + QPoint(buttonRect.width() / 2 - s_buttonBorderRadius + 1, 1);
buttonText = "Added";
}
else
{
- circleCenter = buttonRect.center() + QPoint(-buttonRect.width() / 2 + s_buttonBorderRadius + 1, 1);
+ circleCenter = buttonRect.center() + QPoint(-buttonRect.width() / 2 + s_buttonBorderRadius, 1);
buttonText = "Get";
}
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h
index d43b5d15f6..48f173ec3f 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h
@@ -45,25 +45,25 @@ namespace O3DE::ProjectManager
const QColor m_buttonEnabledColor = QColor("#00B931");
// Item
- inline constexpr static int s_height = 135; // Gem item total height
- inline constexpr static qreal s_gemNameFontSize = 16.0;
- inline constexpr static qreal s_fontSize = 15.0;
- inline constexpr static int s_summaryStartX = 200;
+ inline constexpr static int s_height = 105; // Gem item total height
+ inline constexpr static qreal s_gemNameFontSize = 13.0;
+ inline constexpr static qreal s_fontSize = 12.0;
+ inline constexpr static int s_summaryStartX = 150;
// Margin and borders
- inline constexpr static QMargins s_itemMargins = QMargins(/*left=*/20, /*top=*/10, /*right=*/20, /*bottom=*/10); // Item border distances
- inline constexpr static QMargins s_contentMargins = QMargins(/*left=*/15, /*top=*/12, /*right=*/12, /*bottom=*/12); // Distances of the elements within an item to the item borders
+ inline constexpr static QMargins s_itemMargins = QMargins(/*left=*/16, /*top=*/8, /*right=*/16, /*bottom=*/8); // Item border distances
+ inline constexpr static QMargins s_contentMargins = QMargins(/*left=*/20, /*top=*/12, /*right=*/15, /*bottom=*/12); // Distances of the elements within an item to the item borders
inline constexpr static int s_borderWidth = 4;
// Button
- inline constexpr static int s_buttonWidth = 70;
- inline constexpr static int s_buttonHeight = 24;
- inline constexpr static int s_buttonBorderRadius = 12;
- inline constexpr static int s_buttonCircleRadius = s_buttonBorderRadius - 3;
- inline constexpr static qreal s_buttonFontSize = 12.0;
+ inline constexpr static int s_buttonWidth = 55;
+ inline constexpr static int s_buttonHeight = 18;
+ inline constexpr static int s_buttonBorderRadius = 9;
+ inline constexpr static int s_buttonCircleRadius = s_buttonBorderRadius - 2;
+ inline constexpr static qreal s_buttonFontSize = 10.0;
private:
- void CalcRects(const QStyleOptionViewItem& option, const QModelIndex& modelIndex, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const;
+ void CalcRects(const QStyleOptionViewItem& option, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const;
QRect GetTextRect(QFont& font, const QString& text, qreal fontSize) const;
QRect CalcButtonRect(const QRect& contentRect) const;
void DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
@@ -73,7 +73,7 @@ namespace O3DE::ProjectManager
// Platform icons
void AddPlatformIcon(GemInfo::Platform platform, const QString& iconPath);
- inline constexpr static int s_platformIconSize = 16;
+ inline constexpr static int s_platformIconSize = 12;
QHash m_platformIcons;
};
} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp
index 128fb93345..bc287e3c61 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp
@@ -35,7 +35,7 @@ namespace O3DE::ProjectManager
topLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
QLabel* showCountLabel = new QLabel();
- showCountLabel->setStyleSheet("font-size: 11pt; font: italic;");
+ showCountLabel->setStyleSheet("font-size: 12px; font: italic;");
topLayout->addWidget(showCountLabel);
connect(proxyModel, &GemSortFilterProxyModel::OnInvalidated, this, [=]
{
@@ -61,16 +61,17 @@ namespace O3DE::ProjectManager
QHBoxLayout* columnHeaderLayout = new QHBoxLayout();
columnHeaderLayout->setAlignment(Qt::AlignLeft);
- columnHeaderLayout->addSpacing(31);
+ const int gemNameStartX = GemItemDelegate::s_itemMargins.left() + GemItemDelegate::s_contentMargins.left() - 3;
+ columnHeaderLayout->addSpacing(gemNameStartX);
QLabel* gemNameLabel = new QLabel(tr("Gem Name"));
- gemNameLabel->setStyleSheet("font-size: 11pt;");
+ gemNameLabel->setStyleSheet("font-size: 12px;");
columnHeaderLayout->addWidget(gemNameLabel);
- columnHeaderLayout->addSpacing(111);
+ columnHeaderLayout->addSpacing(77);
QLabel* gemSummaryLabel = new QLabel(tr("Gem Summary"));
- gemSummaryLabel->setStyleSheet("font-size: 11pt;");
+ gemSummaryLabel->setStyleSheet("font-size: 12px;");
columnHeaderLayout->addWidget(gemSummaryLabel);
vLayout->addLayout(columnHeaderLayout);
diff --git a/Code/Tools/ProjectManager/Source/LinkWidget.cpp b/Code/Tools/ProjectManager/Source/LinkWidget.cpp
index a6308f6c62..160d9cf7c7 100644
--- a/Code/Tools/ProjectManager/Source/LinkWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/LinkWidget.cpp
@@ -37,7 +37,7 @@ namespace O3DE::ProjectManager
void LinkLabel::enterEvent([[maybe_unused]] QEvent* event)
{
- setStyleSheet("font-size: 9pt; color: #94D2FF; text-decoration: underline;");
+ setStyleSheet("font-size: 10px; color: #94D2FF; text-decoration: underline;");
}
void LinkLabel::leaveEvent([[maybe_unused]] QEvent* event)
@@ -52,6 +52,6 @@ namespace O3DE::ProjectManager
void LinkLabel::SetDefaultStyle()
{
- setStyleSheet("font-size: 9pt; color: #94D2FF;");
+ setStyleSheet("font-size: 10px; color: #94D2FF;");
}
} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp
index 4be876e79f..72ffa686c1 100644
--- a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp
@@ -12,6 +12,7 @@
#include
+
#include
#include
#include
@@ -58,19 +59,15 @@ namespace O3DE::ProjectManager
m_overlayLabel->setText(text);
}
- ProjectButton::ProjectButton(const QString& projectName, QWidget* parent)
+ ProjectButton::ProjectButton(const ProjectInfo& projectInfo, QWidget* parent)
: QFrame(parent)
- , m_projectName(projectName)
- , m_projectImagePath(":/Resources/DefaultProjectImage.png")
+ , m_projectInfo(projectInfo)
{
- Setup();
- }
+ if (m_projectInfo.m_imagePath.isEmpty())
+ {
+ m_projectInfo.m_imagePath = ":/DefaultProjectImage.png";
+ }
- ProjectButton::ProjectButton(const QString& projectName, const QString& projectImage, QWidget* parent)
- : QFrame(parent)
- , m_projectName(projectName)
- , m_projectImagePath(projectImage)
- {
Setup();
}
@@ -85,20 +82,22 @@ namespace O3DE::ProjectManager
m_projectImageLabel = new LabelButton(this);
m_projectImageLabel->setFixedSize(s_projectImageWidth, s_projectImageHeight);
+ m_projectImageLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
vLayout->addWidget(m_projectImageLabel);
- m_projectImageLabel->setPixmap(QPixmap(m_projectImagePath).scaled(m_projectImageLabel->size(), Qt::KeepAspectRatioByExpanding));
+ m_projectImageLabel->setPixmap(
+ QPixmap(m_projectInfo.m_imagePath).scaled(m_projectImageLabel->size(), Qt::KeepAspectRatioByExpanding));
QMenu* newProjectMenu = new QMenu(this);
m_editProjectAction = newProjectMenu->addAction(tr("Edit Project Settings..."));
-
-#ifdef SHOW_ALL_PROJECT_ACTIONS
- m_editProjectGemsAction = newProjectMenu->addAction(tr("Cutomize Gems..."));
newProjectMenu->addSeparator();
m_copyProjectAction = newProjectMenu->addAction(tr("Duplicate"));
newProjectMenu->addSeparator();
m_removeProjectAction = newProjectMenu->addAction(tr("Remove from O3DE"));
- m_deleteProjectAction = newProjectMenu->addAction(tr("Delete the Project"));
+ m_deleteProjectAction = newProjectMenu->addAction(tr("Delete this Project"));
+
+#ifdef SHOW_ALL_PROJECT_ACTIONS
+ m_editProjectGemsAction = newProjectMenu->addAction(tr("Cutomize Gems..."));
#endif
QFrame* footer = new QFrame(this);
@@ -106,7 +105,7 @@ namespace O3DE::ProjectManager
hLayout->setContentsMargins(0, 0, 0, 0);
footer->setLayout(hLayout);
{
- QLabel* projectNameLabel = new QLabel(m_projectName, this);
+ QLabel* projectNameLabel = new QLabel(m_projectInfo.m_displayName, this);
hLayout->addWidget(projectNameLabel);
QPushButton* projectMenuButton = new QPushButton(this);
@@ -117,14 +116,14 @@ namespace O3DE::ProjectManager
vLayout->addWidget(footer);
- connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectName); });
- connect(m_editProjectAction, &QAction::triggered, [this]() { emit EditProject(m_projectName); });
+ connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectInfo.m_path); });
+ connect(m_editProjectAction, &QAction::triggered, [this]() { emit EditProject(m_projectInfo.m_path); });
+ connect(m_copyProjectAction, &QAction::triggered, [this]() { emit CopyProject(m_projectInfo.m_path); });
+ connect(m_removeProjectAction, &QAction::triggered, [this]() { emit RemoveProject(m_projectInfo.m_path); });
+ connect(m_deleteProjectAction, &QAction::triggered, [this]() { emit DeleteProject(m_projectInfo.m_path); });
#ifdef SHOW_ALL_PROJECT_ACTIONS
- connect(m_editProjectGemsAction, &QAction::triggered, [this]() { emit EditProjectGems(m_projectName); });
- connect(m_copyProjectAction, &QAction::triggered, [this]() { emit CopyProject(m_projectName); });
- connect(m_removeProjectAction, &QAction::triggered, [this]() { emit RemoveProject(m_projectName); });
- connect(m_deleteProjectAction, &QAction::triggered, [this]() { emit DeleteProject(m_projectName); });
+ connect(m_editProjectGemsAction, &QAction::triggered, [this]() { emit EditProjectGems(m_projectInfo.m_path); });
#endif
}
diff --git a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h
index 671debf6d0..e82b56b3fa 100644
--- a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h
+++ b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h
@@ -13,7 +13,8 @@
#pragma once
#if !defined(Q_MOC_RUN)
-#include
+#include
+
#include
#endif
@@ -52,8 +53,7 @@ namespace O3DE::ProjectManager
Q_OBJECT // AUTOMOC
public:
- explicit ProjectButton(const QString& projectName, QWidget* parent = nullptr);
- explicit ProjectButton(const QString& projectName, const QString& projectImage, QWidget* parent = nullptr);
+ explicit ProjectButton(const ProjectInfo& m_projectInfo, QWidget* parent = nullptr);
~ProjectButton() = default;
void SetButtonEnabled(bool enabled);
@@ -70,8 +70,7 @@ namespace O3DE::ProjectManager
private:
void Setup();
- QString m_projectName;
- QString m_projectImagePath;
+ ProjectInfo m_projectInfo;
LabelButton* m_projectImageLabel;
QAction* m_editProjectAction;
QAction* m_editProjectGemsAction;
diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp
new file mode 100644
index 0000000000..526e745d82
--- /dev/null
+++ b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp
@@ -0,0 +1,196 @@
+/*
+ * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+ * its licensors.
+ *
+ * For complete copyright and license terms please see the LICENSE at the root of this
+ * distribution (the "License"). All use of this software is governed by the License,
+ * or, if provided, by the license below or the license accompanying this file. Do not
+ * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+namespace O3DE::ProjectManager
+{
+ namespace ProjectUtils
+ {
+ static bool WarnDirectoryOverwrite(const QString& path, QWidget* parent)
+ {
+ if (!QDir(path).isEmpty())
+ {
+ QMessageBox::StandardButton warningResult = QMessageBox::warning(
+ parent,
+ QObject::tr("Overwrite Directory"),
+ QObject::tr("Directory is not empty! Are you sure you want to overwrite it?"),
+ QMessageBox::No | QMessageBox::Yes
+ );
+
+ if (warningResult != QMessageBox::Yes)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ static bool IsDirectoryDescedent(const QString& possibleAncestorPath, const QString& possibleDecedentPath)
+ {
+ QDir ancestor(possibleAncestorPath);
+ QDir descendent(possibleDecedentPath);
+
+ do
+ {
+ if (ancestor == descendent)
+ {
+ return false;
+ }
+
+ descendent.cdUp();
+ }
+ while (!descendent.isRoot());
+
+ return true;
+ }
+
+ static bool CopyDirectory(const QString& origPath, const QString& newPath)
+ {
+ QDir original(origPath);
+ if (!original.exists())
+ {
+ return false;
+ }
+
+ for (QString directory : original.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
+ {
+ QString newDirectoryPath = newPath + QDir::separator() + directory;
+ original.mkpath(newDirectoryPath);
+
+ if (!CopyDirectory(origPath + QDir::separator() + directory, newDirectoryPath))
+ {
+ return false;
+ }
+ }
+
+ for (QString file : original.entryList(QDir::Files))
+ {
+ if (!QFile::copy(origPath + QDir::separator() + file, newPath + QDir::separator() + file))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool AddProjectDialog(QWidget* parent)
+ {
+ QString path = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(parent, QObject::tr("Select Project Directory")));
+ if (!path.isEmpty())
+ {
+ return RegisterProject(path);
+ }
+
+ return false;
+ }
+
+ bool RegisterProject(const QString& path)
+ {
+ return PythonBindingsInterface::Get()->AddProject(path);
+ }
+
+ bool UnregisterProject(const QString& path)
+ {
+ return PythonBindingsInterface::Get()->RemoveProject(path);
+ }
+
+ bool CopyProjectDialog(const QString& origPath, QWidget* parent)
+ {
+ bool copyResult = false;
+
+ QDir parentOrigDir(origPath);
+ parentOrigDir.cdUp();
+ QString newPath = QDir::toNativeSeparators(
+ QFileDialog::getExistingDirectory(parent, QObject::tr("Select New Project Directory"), parentOrigDir.path()));
+ if (!newPath.isEmpty())
+ {
+ if (!WarnDirectoryOverwrite(newPath, parent))
+ {
+ return false;
+ }
+
+ // TODO: Block UX and Notify User they need to wait
+
+ copyResult = CopyProject(origPath, newPath);
+ }
+
+ return copyResult;
+ }
+
+ bool CopyProject(const QString& origPath, const QString& newPath)
+ {
+ // Disallow copying from or into subdirectory
+ if (!IsDirectoryDescedent(origPath, newPath) || !IsDirectoryDescedent(newPath, origPath))
+ {
+ return false;
+ }
+
+ if (!CopyDirectory(origPath, newPath))
+ {
+ // Cleanup whatever mess was made
+ DeleteProjectFiles(newPath, true);
+ return false;
+ }
+
+ if (!RegisterProject(newPath))
+ {
+ DeleteProjectFiles(newPath, true);
+ }
+
+ return true;
+ }
+
+ bool DeleteProjectFiles(const QString& path, bool force)
+ {
+ QDir projectDirectory(path);
+ if (projectDirectory.exists())
+ {
+ // Check if there is an actual project hereor just force it
+ if (force || PythonBindingsInterface::Get()->GetProject(path).IsSuccess())
+ {
+ return projectDirectory.removeRecursively();
+ }
+ }
+
+ return false;
+ }
+
+ bool MoveProject(const QString& origPath, const QString& newPath, QWidget* parent)
+ {
+ if (!WarnDirectoryOverwrite(newPath, parent) || !UnregisterProject(origPath))
+ {
+ return false;
+ }
+
+ QDir directory;
+ if (directory.rename(origPath, newPath))
+ {
+ return directory.rename(origPath, newPath);
+ }
+
+ if (!RegisterProject(newPath))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ } // namespace ProjectUtils
+} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.h b/Code/Tools/ProjectManager/Source/ProjectUtils.h
new file mode 100644
index 0000000000..5982bff634
--- /dev/null
+++ b/Code/Tools/ProjectManager/Source/ProjectUtils.h
@@ -0,0 +1,28 @@
+/*
+ * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+ * its licensors.
+ *
+ * For complete copyright and license terms please see the LICENSE at the root of this
+ * distribution (the "License"). All use of this software is governed by the License,
+ * or, if provided, by the license below or the license accompanying this file. Do not
+ * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ */
+#pragma once
+
+#include
+
+namespace O3DE::ProjectManager
+{
+ namespace ProjectUtils
+ {
+ bool AddProjectDialog(QWidget* parent = nullptr);
+ bool RegisterProject(const QString& path);
+ bool UnregisterProject(const QString& path);
+ bool CopyProjectDialog(const QString& origPath, QWidget* parent = nullptr);
+ bool CopyProject(const QString& origPath, const QString& newPath);
+ bool DeleteProjectFiles(const QString& path, bool force = false);
+ bool MoveProject(const QString& origPath, const QString& newPath, QWidget* parent = nullptr);
+ } // namespace ProjectUtils
+} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp
index 5f1c0e2b36..dd2e411ec5 100644
--- a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp
+++ b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp
@@ -14,6 +14,7 @@
#include
#include
+#include
#include
#include
@@ -65,9 +66,6 @@ namespace O3DE::ProjectManager
m_stack->addWidget(m_projectsContent);
vLayout->addWidget(m_stack);
-
- connect(m_createNewProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleNewProjectButton);
- connect(m_addExistingProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleAddProjectButton);
}
QFrame* ProjectsScreen::CreateFirstTimeContent()
@@ -167,28 +165,27 @@ namespace O3DE::ProjectManager
#endif
{
ProjectButton* projectButton;
+
QString projectPreviewPath = project.m_path + m_projectPreviewImagePath;
QFileInfo doesPreviewExist(projectPreviewPath);
if (doesPreviewExist.exists() && doesPreviewExist.isFile())
{
- projectButton = new ProjectButton(project.m_projectName, projectPreviewPath, this);
- }
- else
- {
- projectButton = new ProjectButton(project.m_projectName, this);
+ project.m_imagePath = projectPreviewPath;
}
+ projectButton = new ProjectButton(project, this);
+
flowLayout->addWidget(projectButton);
connect(projectButton, &ProjectButton::OpenProject, this, &ProjectsScreen::HandleOpenProject);
connect(projectButton, &ProjectButton::EditProject, this, &ProjectsScreen::HandleEditProject);
-
- #ifdef DISPLAY_PROJECT_DEV_DATA
- connect(projectButton, &ProjectButton::EditProjectGems, this, &ProjectsScreen::HandleEditProjectGems);
connect(projectButton, &ProjectButton::CopyProject, this, &ProjectsScreen::HandleCopyProject);
connect(projectButton, &ProjectButton::RemoveProject, this, &ProjectsScreen::HandleRemoveProject);
connect(projectButton, &ProjectButton::DeleteProject, this, &ProjectsScreen::HandleDeleteProject);
- #endif
+
+#ifdef SHOW_ALL_PROJECT_ACTIONS
+ connect(projectButton, &ProjectButton::EditProjectGems, this, &ProjectsScreen::HandleEditProjectGems);
+#endif
}
layout->addWidget(projectsScrollArea);
@@ -242,7 +239,11 @@ namespace O3DE::ProjectManager
}
void ProjectsScreen::HandleAddProjectButton()
{
- // Do nothing for now
+ if (ProjectUtils::AddProjectDialog(this))
+ {
+ emit ResetScreenRequest(ProjectManagerScreen::Projects);
+ emit ChangeScreenRequest(ProjectManagerScreen::Projects);
+ }
}
void ProjectsScreen::HandleOpenProject(const QString& projectPath)
{
@@ -300,18 +301,36 @@ namespace O3DE::ProjectManager
emit NotifyCurrentProject(projectPath);
emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog);
}
- void ProjectsScreen::HandleCopyProject([[maybe_unused]] const QString& projectPath)
+ void ProjectsScreen::HandleCopyProject(const QString& projectPath)
{
// Open file dialog and choose location for copied project then register copy with O3DE
+ if (ProjectUtils::CopyProjectDialog(projectPath, this))
+ {
+ emit ResetScreenRequest(ProjectManagerScreen::Projects);
+ emit ChangeScreenRequest(ProjectManagerScreen::Projects);
+ }
}
- void ProjectsScreen::HandleRemoveProject([[maybe_unused]] const QString& projectPath)
+ void ProjectsScreen::HandleRemoveProject(const QString& projectPath)
{
- // Unregister Project from O3DE
+ // Unregister Project from O3DE and reload projects
+ if (ProjectUtils::UnregisterProject(projectPath))
+ {
+ emit ResetScreenRequest(ProjectManagerScreen::Projects);
+ emit ChangeScreenRequest(ProjectManagerScreen::Projects);
+ }
}
- void ProjectsScreen::HandleDeleteProject([[maybe_unused]] const QString& projectPath)
+ void ProjectsScreen::HandleDeleteProject(const QString& projectPath)
{
- // Remove project from 03DE and delete from disk
- ProjectsScreen::HandleRemoveProject(projectPath);
+ QMessageBox::StandardButton warningResult = QMessageBox::warning(
+ this, tr("Delete Project"), tr("Are you sure?\nProject will be removed from O3DE and directory will be deleted!"),
+ QMessageBox::No | QMessageBox::Yes);
+
+ if (warningResult == QMessageBox::Yes)
+ {
+ // Remove project from O3DE and delete from disk
+ HandleRemoveProject(projectPath);
+ ProjectUtils::DeleteProjectFiles(projectPath);
+ }
}
void ProjectsScreen::NotifyCurrentScreen()
diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp
index 8c79a153c8..9279ad1291 100644
--- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp
+++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp
@@ -379,13 +379,13 @@ namespace O3DE::ProjectManager
pybind11::str defaultTemplatesFolder = engineInfo.m_defaultTemplatesFolder.toStdString();
auto registrationResult = m_registration.attr("register")(
- enginePath, // engine_path
- pybind11::none(), // project_path
- pybind11::none(), // gem_path
- pybind11::none(), // template_path
- pybind11::none(), // restricted_path
- pybind11::none(), // repo_uri
- pybind11::none(), // default_engines_folder
+ enginePath, // engine_path
+ pybind11::none(), // project_path
+ pybind11::none(), // gem_path
+ pybind11::none(), // template_path
+ pybind11::none(), // restricted_path
+ pybind11::none(), // repo_uri
+ pybind11::none(), // default_engines_folder
defaultProjectsFolder,
defaultGemsFolder,
defaultTemplatesFolder
@@ -456,6 +456,51 @@ namespace O3DE::ProjectManager
}
}
+ bool PythonBindings::AddProject(const QString& path)
+ {
+ bool registrationResult = false;
+ bool result = ExecuteWithLock(
+ [&]
+ {
+ pybind11::str projectPath = path.toStdString();
+ auto pythonRegistrationResult = m_registration.attr("register")(pybind11::none(), projectPath);
+
+ // Returns an exit code so boolify it then invert result
+ registrationResult = !pythonRegistrationResult.cast();
+ });
+
+ return result && registrationResult;
+ }
+
+ bool PythonBindings::RemoveProject(const QString& path)
+ {
+ bool registrationResult = false;
+ bool result = ExecuteWithLock(
+ [&]
+ {
+ pybind11::str projectPath = path.toStdString();
+ auto pythonRegistrationResult = m_registration.attr("register")(
+ pybind11::none(), // engine_path
+ projectPath, // project_path
+ pybind11::none(), // gem_path
+ pybind11::none(), // template_path
+ pybind11::none(), // restricted_path
+ pybind11::none(), // repo_uri
+ pybind11::none(), // default_engines_folder
+ pybind11::none(), // default_gems_folder
+ pybind11::none(), // default_templates_folder
+ pybind11::none(), // default_restricted_folder
+ pybind11::none(), // default_restricted_folder
+ true // remove
+ );
+
+ // Returns an exit code so boolify it then invert result
+ registrationResult = !pythonRegistrationResult.cast();
+ });
+
+ return result && registrationResult;
+ }
+
AZ::Outcome PythonBindings::CreateProject(const QString& projectTemplatePath, const ProjectInfo& projectInfo)
{
ProjectInfo createdProjectInfo;
@@ -600,7 +645,7 @@ namespace O3DE::ProjectManager
pybind11::none(), // gem_target
pybind11::none(), // project_name
pyProjectPath
- );
+ );
});
return result;
@@ -618,7 +663,7 @@ namespace O3DE::ProjectManager
pybind11::none(), // gem_target
pybind11::none(), // project_name
pyProjectPath
- );
+ );
});
return result;
diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h
index 892e13a65b..fb2303c495 100644
--- a/Code/Tools/ProjectManager/Source/PythonBindings.h
+++ b/Code/Tools/ProjectManager/Source/PythonBindings.h
@@ -46,6 +46,8 @@ namespace O3DE::ProjectManager
AZ::Outcome CreateProject(const QString& projectTemplatePath, const ProjectInfo& projectInfo) override;
AZ::Outcome GetProject(const QString& path) override;
AZ::Outcome> GetProjects() override;
+ bool AddProject(const QString& path) override;
+ bool RemoveProject(const QString& path) override;
bool UpdateProject(const ProjectInfo& projectInfo) override;
bool AddGemToProject(const QString& gemPath, const QString& projectPath) override;
bool RemoveGemFromProject(const QString& gemPath, const QString& projectPath) override;
diff --git a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h
index b5c8f1a76a..a58eea0fe6 100644
--- a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h
+++ b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h
@@ -88,6 +88,20 @@ namespace O3DE::ProjectManager
* @return an outcome with ProjectInfos on success
*/
virtual AZ::Outcome> GetProjects() = 0;
+
+ /**
+ * Adds existing project on disk
+ * @param path the absolute path to the project
+ * @return true on success, false on failure
+ */
+ virtual bool AddProject(const QString& path) = 0;
+
+ /**
+ * Adds existing project on disk
+ * @param path the absolute path to the project
+ * @return true on success, false on failure
+ */
+ virtual bool RemoveProject(const QString& path) = 0;
/**
* Update a project
diff --git a/Code/Tools/ProjectManager/Source/TagWidget.cpp b/Code/Tools/ProjectManager/Source/TagWidget.cpp
index 3e80944204..628b682b95 100644
--- a/Code/Tools/ProjectManager/Source/TagWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/TagWidget.cpp
@@ -18,9 +18,9 @@ namespace O3DE::ProjectManager
TagWidget::TagWidget(const QString& text, QWidget* parent)
: QLabel(text, parent)
{
- setFixedHeight(35);
+ setFixedHeight(24);
setMargin(5);
- setStyleSheet("font-size: 12pt; background-color: #333333; border-radius: 4px;");
+ setStyleSheet("font-size: 12px; background-color: #333333; border-radius: 3px;");
}
TagContainerWidget::TagContainerWidget(QWidget* parent)
@@ -35,7 +35,7 @@ namespace O3DE::ProjectManager
void TagContainerWidget::Update(const QStringList& tags)
{
QWidget* parentWidget = qobject_cast(parent());
- int width = 250;
+ int width = 200;
if (parentWidget)
{
width = parentWidget->width();
diff --git a/Code/Tools/ProjectManager/project_manager_files.cmake b/Code/Tools/ProjectManager/project_manager_files.cmake
index 223465f3c8..feaea4c172 100644
--- a/Code/Tools/ProjectManager/project_manager_files.cmake
+++ b/Code/Tools/ProjectManager/project_manager_files.cmake
@@ -36,6 +36,8 @@ set(FILES
Source/PythonBindingsInterface.h
Source/ProjectInfo.h
Source/ProjectInfo.cpp
+ Source/ProjectUtils.h
+ Source/ProjectUtils.cpp
Source/NewProjectSettingsScreen.h
Source/NewProjectSettingsScreen.cpp
Source/CreateProjectCtrl.h
diff --git a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp
index 2cda1e68ae..791af4bf68 100644
--- a/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp
+++ b/Code/Tools/SceneAPI/SDKWrapper/AssImpSceneWrapper.cpp
@@ -17,6 +17,13 @@
#include
#include
+#if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL
+#include
+#include
+#include
+#include
+#endif // AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL
+
namespace AZ
{
namespace AssImpSDKWrapper
@@ -34,10 +41,31 @@ namespace AZ
{
}
+#if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL
+ void signal_handler(int signal)
+ {
+ AZ_TracePrintf(
+ SceneAPI::Utilities::ErrorWindow,
+ "Failed to import scene with Asset Importer library. An %s has occured in the library, this scene file cannot be parsed by the library.",
+ signal == SIGABRT ? "assert" : "unknown error");
+ }
+#endif // AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL
+
bool AssImpSceneWrapper::LoadSceneFromFile(const char* fileName)
{
AZ_TracePrintf(SceneAPI::Utilities::LogWindow, "AssImpSceneWrapper::LoadSceneFromFile %s", fileName);
AZ_TraceContext("Filename", fileName);
+
+#if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL
+ // Turn off the abort popup because it can disrupt automation.
+ // AssImp calls abort when asserts are enabled, and an assert is encountered.
+#ifdef _WRITE_ABORT_MSG
+ _set_abort_behavior(0, _WRITE_ABORT_MSG);
+#endif // #ifdef _WRITE_ABORT_MSG
+ // Instead, capture any calls to abort with a signal handler, and report them.
+ auto previous_handler = std::signal(SIGABRT, signal_handler);
+#endif // AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL
+
// aiProcess_JoinIdenticalVertices is not enabled because O3DE has a mesh optimizer that also does this,
// this flag is disabled to keep AssImp output similar to FBX SDK to reduce downstream bugs for the initial AssImp release.
// There's currently a minimum of properties and flags set to maximize compatibility with the existing node graph.
@@ -49,6 +77,15 @@ namespace AZ
| aiProcess_LimitBoneWeights //Limits the number of bones that can affect a vertex to a maximum value
//dropping the least important and re-normalizing
| aiProcess_GenNormals); //Generate normals for meshes
+
+#if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL
+ // Reset abort behavior for anything else that may call abort.
+ std::signal(SIGABRT, previous_handler);
+#ifdef _WRITE_ABORT_MSG
+ _set_abort_behavior(1, _WRITE_ABORT_MSG);
+#endif // #ifdef _WRITE_ABORT_MSG
+#endif // AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL
+
if (!m_assImpScene)
{
AZ_TracePrintf(SceneAPI::Utilities::ErrorWindow, "Failed to import Asset Importer Scene. Error returned: %s", m_importer.GetErrorString());
diff --git a/Code/Tools/SerializeContextTools/SliceConverter.cpp b/Code/Tools/SerializeContextTools/SliceConverter.cpp
index 3fbf7cb25c..d06534e303 100644
--- a/Code/Tools/SerializeContextTools/SliceConverter.cpp
+++ b/Code/Tools/SerializeContextTools/SliceConverter.cpp
@@ -244,7 +244,7 @@ namespace AZ
}
else
{
- return SavePrefab(templateId);
+ return SavePrefab(outputPath, templateId);
}
}
@@ -318,7 +318,7 @@ namespace AZ
nestedPrefabPath.ReplaceExtension("prefab");
auto prefabLoaderInterface = AZ::Interface::Get();
- nestedPrefabPath = prefabLoaderInterface->GetRelativePathToProject(nestedPrefabPath);
+ nestedPrefabPath = prefabLoaderInterface->GenerateRelativePath(nestedPrefabPath);
AzToolsFramework::Prefab::TemplateId nestedTemplateId =
prefabSystemComponentInterface->GetTemplateIdFromFilePath(nestedPrefabPath);
@@ -439,17 +439,31 @@ namespace AZ
AZ::Debug::Trace::Instance().Output("", "\n");
}
- bool SliceConverter::SavePrefab(AzToolsFramework::Prefab::TemplateId templateId)
+ bool SliceConverter::SavePrefab(AZ::IO::PathView outputPath, AzToolsFramework::Prefab::TemplateId templateId)
{
auto prefabLoaderInterface = AZ::Interface::Get();
- if (!prefabLoaderInterface->SaveTemplate(templateId))
+ AZStd::string out;
+ if (prefabLoaderInterface->SaveTemplateToString(templateId, out))
{
- AZ_Printf("Convert-Slice", " Could not save prefab - internal error (Json write operation failure).\n");
- return false;
+ IO::SystemFile outputFile;
+ if (!outputFile.Open(
+ AZStd::string(outputPath.Native()).c_str(),
+ IO::SystemFile::OpenMode::SF_OPEN_CREATE |
+ IO::SystemFile::OpenMode::SF_OPEN_CREATE_PATH |
+ IO::SystemFile::OpenMode::SF_OPEN_WRITE_ONLY))
+ {
+ AZ_Error("Convert-Slice", false, " Unable to create output file '%.*s'.", AZ_STRING_ARG(outputPath.Native()));
+ return false;
+ }
+
+ outputFile.Write(out.data(), out.size());
+ outputFile.Close();
+ return true;
}
- return true;
+ AZ_Printf("Convert-Slice", " Could not save prefab - internal error (Json write operation failure).\n");
+ return false;
}
bool SliceConverter::ConnectToAssetProcessor()
diff --git a/Code/Tools/SerializeContextTools/SliceConverter.h b/Code/Tools/SerializeContextTools/SliceConverter.h
index a977095f02..bec893ff56 100644
--- a/Code/Tools/SerializeContextTools/SliceConverter.h
+++ b/Code/Tools/SerializeContextTools/SliceConverter.h
@@ -56,7 +56,7 @@ namespace AZ
AZ::SliceComponent::SliceInstance& instance, AZ::Data::Asset& sliceAsset,
AzToolsFramework::Prefab::TemplateReference nestedTemplate, AzToolsFramework::Prefab::Instance* topLevelInstance);
static void PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId);
- static bool SavePrefab(AzToolsFramework::Prefab::TemplateId templateId);
+ static bool SavePrefab(AZ::IO::PathView outputPath, AzToolsFramework::Prefab::TemplateId templateId);
};
} // namespace SerializeContextTools
} // namespace AZ
diff --git a/Gems/AWSCore/Code/Include/Private/Editor/AWSCoreEditorManager.h b/Gems/AWSCore/Code/Include/Private/Editor/AWSCoreEditorManager.h
index 721cd6dd6a..98467727ea 100644
--- a/Gems/AWSCore/Code/Include/Private/Editor/AWSCoreEditorManager.h
+++ b/Gems/AWSCore/Code/Include/Private/Editor/AWSCoreEditorManager.h
@@ -18,7 +18,7 @@ namespace AWSCore
class AWSCoreEditorManager
{
public:
- static constexpr const char CLOUD_SERVICES_MENU_TEXT[] = "&Cloud services";
+ static constexpr const char AWS_MENU_TEXT[] = "&AWS";
AWSCoreEditorManager();
virtual ~AWSCoreEditorManager();
diff --git a/Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuLinks.h b/Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuLinks.h
new file mode 100644
index 0000000000..46acfbd4a3
--- /dev/null
+++ b/Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuLinks.h
@@ -0,0 +1,53 @@
+/*
+ * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+ * its licensors.
+ *
+ * For complete copyright and license terms please see the LICENSE at the root of this
+ * distribution (the "License"). All use of this software is governed by the License,
+ * or, if provided, by the license below or the license accompanying this file. Do not
+ * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ */
+
+#pragma once
+
+namespace AWSCore
+{
+ static constexpr const char NewToAWSUrl[] = "https://docs.o3de.org/docs/user-guide/gems/reference/aws/";
+
+ static constexpr const char AWSAndScriptCanvasUrl[] = "https://docs.o3de.org/docs/user-guide/components/reference/aws/";
+ static constexpr const char AWSAndComponentsUrl[] = "https://docs.o3de.org/docs/user-guide/components/reference/aws/";
+ static constexpr const char CallAWSResourcesUrl[] = "https://docs.o3de.org/docs/user-guide/components/reference/aws/";
+
+ static constexpr const char AWSCredentialConfigurationUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-core/configuring-credentials/";
+
+ static constexpr const char AWSClientAuthGemOverviewUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
+ static constexpr const char AWSClientAuthCDKAndResourcesUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
+ static constexpr const char AWSClientAuthScriptCanvasAndLuaUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
+ static constexpr const char AWSClientAuth3rdPartyAuthProviderUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
+ static constexpr const char AWSClientAuthCustomAuthProviderUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
+ static constexpr const char AWSClientAuthPlatformSpecificUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
+ static constexpr const char AWSClientAuthAPIReferenceUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
+
+ static constexpr const char AWSMetricsGemOverviewUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/";
+ static constexpr const char AWSMetricsSetupGemUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/";
+ static constexpr const char AWSMetricsScriptingUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/";
+ static constexpr const char AWSMetricsAPIReferenceUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/";
+ static constexpr const char AWSMetricsAdvancedTopicsUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/";
+ static constexpr const char AWSMetricsSettingsUrl[] =
+ "https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/";
+} // namespace AWSCore
diff --git a/Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuNames.h b/Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuNames.h
new file mode 100644
index 0000000000..a9a8198e52
--- /dev/null
+++ b/Gems/AWSCore/Code/Include/Private/Editor/Constants/AWSCoreEditorMenuNames.h
@@ -0,0 +1,44 @@
+/*
+ * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+ * its licensors.
+ *
+ * For complete copyright and license terms please see the LICENSE at the root of this
+ * distribution (the "License"). All use of this software is governed by the License,
+ * or, if provided, by the license below or the license accompanying this file. Do not
+ * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ */
+
+#pragma once
+
+namespace AWSCore
+{
+ static constexpr const char NewToAWSActionText[] = "Getting started with AWS?";
+
+ static constexpr const char AWSAndO3DEGlobalDocsText[] = "AWS & O3DE global docs";
+ static constexpr const char AWSAndScriptCanvasActionText[] = "AWS && ScriptCanvas";
+ static constexpr const char AWSAndComponentsActionText[] = "AWS & Components";
+ static constexpr const char CallAWSResourcesActionText[] = "Call AWS resources";
+
+ static constexpr const char AWSCredentialConfigurationActionText[] = "AWS credential configuration";
+
+ static constexpr const char AWSResourceMappingToolActionText[] = "AWS Resource Mapping Tool...";
+
+ static constexpr const char AWSClientAuthActionText[] = "Client Auth";
+ static constexpr const char AWSClientAuthGemOverviewActionText[] = "Gem Overview";
+ static constexpr const char AWSClientAuthCDKAndResourcesActionText[] = "CDK Application and Resource Mappings";
+ static constexpr const char AWSClientAuthScriptCanvasAndLuaActionText[] = "Script Canvas and Lua";
+ static constexpr const char AWSClientAuth3rdPartyAuthProviderActionText[] = "3rd Party developer Authentication Provider support";
+ static constexpr const char AWSClientAuthCustomAuthProviderActionText[] = "Custom developer Authentication Provider support";
+ static constexpr const char AWSClientAuthPlatformSpecificActionText[] = "Platform specific Callouts";
+ static constexpr const char AWSClientAuthAPIReferenceActionText[] = "API Reference";
+
+ static constexpr const char AWSMetricsActionText[] = "Metrics";
+ static constexpr const char AWSMetricsGemOverviewActionText[] = "Metrics Overview";
+ static constexpr const char AWSMetricsSetupGemActionText[] = "Setup Metrics Gem";
+ static constexpr const char AWSMetricsScriptingActionText[] = "Scripting with AWS Metrics";
+ static constexpr const char AWSMetricsAPIReferenceActionText[] = "C++ API with AWS Metrics Gem";
+ static constexpr const char AWSMetricsAdvancedTopicsActionText[] = "Advanced topics";
+ static constexpr const char AWSMetricsSettingsActionText[] = "Metrics Settings";
+} // namespace AWSCore
diff --git a/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h b/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h
index 19f241e368..c892f86b66 100644
--- a/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h
+++ b/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h
@@ -35,29 +35,23 @@ namespace AWSCore
static constexpr const char AWSResourceMappingToolIsRunningText[] = "Resource Mapping Tool is running...";
static constexpr const char AWSResourceMappingToolLogWarningText[] =
"Failed to launch Resource Mapping Tool, please check logs for details.";
- static constexpr const char AWSResourceMappingToolActionText[] = "AWS Resource Mapping Tool...";
- static constexpr const char CredentialConfigurationActionText[] = "Credential Configuration";
- static constexpr const char CredentialConfigurationUrl[] = "https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/credentials.html";
- static constexpr const char NewToAWSActionText[] = "New to AWS?";
- static constexpr const char NewToAWSUrl[] = "https://o3deorg.netlify.app/docs/user-guide/gems/reference/aws";
- static constexpr const char AWSAndScriptCanvasActionText[] = "AWS && ScriptCanvas";
- static constexpr const char AWSAndScriptCanvasUrl[] = "https://o3deorg.netlify.app/docs/user-guide/gems/reference/aws";
- static constexpr const char AWSClientAuthActionText[] = "Client Auth";
- static constexpr const char AWSMetricsActionText[] = "Metrics";
AWSCoreEditorMenu(const QString& text);
~AWSCoreEditorMenu();
private:
+ QAction* AddExternalLinkAction(const AZStd::string& name, const AZStd::string& url, const AZStd::string& icon = "");
+
void InitializeResourceMappingToolAction();
void InitializeAWSDocActions();
+ void InitializeAWSGlobalDocsSubMenu();
void InitializeAWSFeatureGemActions();
// AWSCoreEditorRequestBus interface implementation
void SetAWSClientAuthEnabled() override;
void SetAWSMetricsEnabled() override;
- void SetAWSFeatureActionsEnabled(const AZStd::string actionText);
+ QMenu* SetAWSFeatureSubMenu(const AZStd::string& menuText);
// To improve experience, use process watcher to keep track of ongoing tool process
AZStd::unique_ptr m_resourceMappingToolWatcher;
diff --git a/Gems/AWSCore/Code/Source/Editor/AWSCoreEditorManager.cpp b/Gems/AWSCore/Code/Source/Editor/AWSCoreEditorManager.cpp
index 1e3e44255a..89956d61b8 100644
--- a/Gems/AWSCore/Code/Source/Editor/AWSCoreEditorManager.cpp
+++ b/Gems/AWSCore/Code/Source/Editor/AWSCoreEditorManager.cpp
@@ -16,7 +16,7 @@
namespace AWSCore
{
AWSCoreEditorManager::AWSCoreEditorManager()
- : m_awsCoreEditorMenu(new AWSCoreEditorMenu(CLOUD_SERVICES_MENU_TEXT))
+ : m_awsCoreEditorMenu(new AWSCoreEditorMenu(AWS_MENU_TEXT))
{
}
diff --git a/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp b/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp
index 754cc32751..c319788547 100644
--- a/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp
+++ b/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp
@@ -13,10 +13,13 @@
#include
#include
#include
+#include
#include
#include
#include
+#include
+#include
#include
#include
@@ -36,8 +39,8 @@ namespace AWSCore
: QMenu(text)
, m_resourceMappingToolWatcher(nullptr)
{
- InitializeResourceMappingToolAction();
InitializeAWSDocActions();
+ InitializeResourceMappingToolAction();
this->addSeparator();
InitializeAWSFeatureGemActions();
@@ -58,6 +61,21 @@ namespace AWSCore
this->clear();
}
+ QAction* AWSCoreEditorMenu::AddExternalLinkAction(
+ const AZStd::string& name, const AZStd::string& url, const AZStd::string& icon)
+ {
+ QAction* linkAction = new QAction(QObject::tr(name.c_str()));
+ QObject::connect(linkAction, &QAction::triggered, this,
+ [url]() {
+ QDesktopServices::openUrl(QUrl(url.c_str()));
+ });
+ if (!icon.empty())
+ {
+ linkAction->setIcon(QIcon(icon.c_str()));
+ }
+ return linkAction;
+ }
+
void AWSCoreEditorMenu::InitializeResourceMappingToolAction()
{
#ifdef AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED
@@ -103,21 +121,21 @@ namespace AWSCore
void AWSCoreEditorMenu::InitializeAWSDocActions()
{
- QAction* credentialConfiguration = new QAction(QObject::tr(CredentialConfigurationActionText));
- QObject::connect(credentialConfiguration, &QAction::triggered, this, []() {
- QDesktopServices::openUrl(QUrl(CredentialConfigurationUrl));
- });
- this->addAction(credentialConfiguration);
+ this->addAction(AddExternalLinkAction(NewToAWSActionText, NewToAWSUrl, ":/Notifications/link.svg"));
- QAction* newToAWS = new QAction(QObject::tr(NewToAWSActionText));
- QObject::connect(newToAWS, &QAction::triggered, this, []() {
- QDesktopServices::openUrl(QUrl(NewToAWSUrl)); });
- this->addAction(newToAWS);
+ InitializeAWSGlobalDocsSubMenu();
- QAction* awsAndScriptCanvas = new QAction(QObject::tr(AWSAndScriptCanvasActionText));
- QObject::connect(awsAndScriptCanvas, &QAction::triggered, this, []() {
- QDesktopServices::openUrl(QUrl(AWSAndScriptCanvasUrl)); });
- this->addAction(awsAndScriptCanvas);
+ this->addAction(AddExternalLinkAction(
+ AWSCredentialConfigurationActionText, AWSCredentialConfigurationUrl, ":/Notifications/link.svg"));
+ }
+
+ void AWSCoreEditorMenu::InitializeAWSGlobalDocsSubMenu()
+ {
+ QMenu* globalDocsMenu = this->addMenu(QObject::tr(AWSAndO3DEGlobalDocsText));
+
+ globalDocsMenu->addAction(AddExternalLinkAction(AWSAndScriptCanvasActionText, AWSAndScriptCanvasUrl, ":/Notifications/link.svg"));
+ globalDocsMenu->addAction(AddExternalLinkAction(AWSAndComponentsActionText, AWSAndComponentsUrl, ":/Notifications/link.svg"));
+ globalDocsMenu->addAction(AddExternalLinkAction(CallAWSResourcesActionText, CallAWSResourcesUrl, ":/Notifications/link.svg"));
}
void AWSCoreEditorMenu::InitializeAWSFeatureGemActions()
@@ -135,25 +153,67 @@ namespace AWSCore
void AWSCoreEditorMenu::SetAWSClientAuthEnabled()
{
- SetAWSFeatureActionsEnabled(AWSClientAuthActionText);
+ // TODO: instead of creating submenu in core editor, aws feature gem should return submenu component directly
+ QMenu* subMenu = SetAWSFeatureSubMenu(AWSClientAuthActionText);
+
+ subMenu->addAction(AddExternalLinkAction(
+ AWSClientAuthGemOverviewActionText, AWSClientAuthGemOverviewUrl, ":/Notifications/link.svg"));
+ subMenu->addAction(AddExternalLinkAction(
+ AWSClientAuthCDKAndResourcesActionText, AWSClientAuthCDKAndResourcesUrl, ":/Notifications/link.svg"));
+ subMenu->addAction(AddExternalLinkAction(
+ AWSClientAuthScriptCanvasAndLuaActionText, AWSClientAuthScriptCanvasAndLuaUrl, ":/Notifications/link.svg"));
+ subMenu->addAction(AddExternalLinkAction(
+ AWSClientAuth3rdPartyAuthProviderActionText, AWSClientAuth3rdPartyAuthProviderUrl, ":/Notifications/link.svg"));
+ subMenu->addAction(AddExternalLinkAction(
+ AWSClientAuthCustomAuthProviderActionText, AWSClientAuthCustomAuthProviderUrl, ":/Notifications/link.svg"));
+ subMenu->addAction(AddExternalLinkAction(
+ AWSClientAuthPlatformSpecificActionText, AWSClientAuthPlatformSpecificUrl, ":/Notifications/link.svg"));
+ subMenu->addAction(AddExternalLinkAction(
+ AWSClientAuthAPIReferenceActionText, AWSClientAuthAPIReferenceUrl, ":/Notifications/link.svg"));
}
void AWSCoreEditorMenu::SetAWSMetricsEnabled()
{
- SetAWSFeatureActionsEnabled(AWSMetricsActionText);
+ // TODO: instead of creating submenu in core editor, aws feature gem should return submenu component directly
+ QMenu* subMenu = SetAWSFeatureSubMenu(AWSMetricsActionText);
+
+ subMenu->addAction(AddExternalLinkAction(
+ AWSMetricsGemOverviewActionText, AWSMetricsGemOverviewUrl, ":/Notifications/link.svg"));
+ subMenu->addAction(AddExternalLinkAction(
+ AWSMetricsSetupGemActionText, AWSMetricsSetupGemUrl, ":/Notifications/link.svg"));
+ subMenu->addAction(AddExternalLinkAction(
+ AWSMetricsScriptingActionText, AWSMetricsScriptingUrl, ":/Notifications/link.svg"));
+ subMenu->addAction(AddExternalLinkAction(
+ AWSMetricsAPIReferenceActionText, AWSMetricsAPIReferenceUrl, ":/Notifications/link.svg"));
+ subMenu->addAction(AddExternalLinkAction(
+ AWSMetricsAdvancedTopicsActionText, AWSMetricsAdvancedTopicsUrl, ":/Notifications/link.svg"));
+
+ AZStd::string priorAlias = AZ::IO::FileIOBase::GetInstance()->GetAlias("@devroot@");
+ AZStd::string configFilePath = priorAlias + "\\Gems\\AWSMetrics\\Code\\" + AZ::SettingsRegistryInterface::RegistryFolder;
+ AzFramework::StringFunc::Path::Normalize(configFilePath);
+
+ QAction* settingsAction = new QAction(QObject::tr(AWSMetricsSettingsActionText));
+ QObject::connect(settingsAction, &QAction::triggered, this,
+ [configFilePath](){
+ QDesktopServices::openUrl(QUrl::fromLocalFile(configFilePath.c_str()));
+ });
+ subMenu->addAction(settingsAction);
}
- void AWSCoreEditorMenu::SetAWSFeatureActionsEnabled(const AZStd::string actionText)
+ QMenu* AWSCoreEditorMenu::SetAWSFeatureSubMenu(const AZStd::string& menuText)
{
auto actionList = this->actions();
for (QList::iterator itr = actionList.begin(); itr != actionList.end(); itr++)
{
- if (QString::compare((*itr)->text(), actionText.c_str()) == 0)
+ if (QString::compare((*itr)->text(), menuText.c_str()) == 0)
{
- (*itr)->setIcon(QIcon(QString(":/Notifications/checkmark.svg")));
- (*itr)->setEnabled(true);
- break;
+ QMenu* subMenu = new QMenu(QObject::tr(menuText.c_str()));
+ subMenu->setIcon(QIcon(QString(":/Notifications/checkmark.svg")));
+ this->insertMenu(*itr, subMenu);
+ this->removeAction(*itr);
+ return subMenu;
}
}
+ return nullptr;
}
} // namespace AWSCore
diff --git a/Gems/AWSCore/Code/Tests/AWSCoreEditorSystemComponentTest.cpp b/Gems/AWSCore/Code/Tests/AWSCoreEditorSystemComponentTest.cpp
index e9c249f1c8..ff78d8e252 100644
--- a/Gems/AWSCore/Code/Tests/AWSCoreEditorSystemComponentTest.cpp
+++ b/Gems/AWSCore/Code/Tests/AWSCoreEditorSystemComponentTest.cpp
@@ -85,7 +85,7 @@ TEST_F(AWSCoreEditorSystemComponentTest, NotifyMainWindowInitialized_HaveDummyMe
testMenuBar->addMenu("dummy menu");
AzToolsFramework::EditorEvents::Bus::Broadcast(&AzToolsFramework::EditorEvents::NotifyMainWindowInitialized, &testMainWindow);
EXPECT_TRUE(testMenuBar->actions().size() == 2);
- EXPECT_TRUE(QString::compare(testMenuBar->actions()[1]->text(), AWSCoreEditorManager::CLOUD_SERVICES_MENU_TEXT) == 0);
+ EXPECT_TRUE(QString::compare(testMenuBar->actions()[1]->text(), AWSCoreEditorManager::AWS_MENU_TEXT) == 0);
}
TEST_F(AWSCoreEditorSystemComponentTest, NotifyMainWindowInitialized_HaveHelpMenuInMenuBar_ExpectedMenuGetsAddedAtFront)
@@ -95,5 +95,5 @@ TEST_F(AWSCoreEditorSystemComponentTest, NotifyMainWindowInitialized_HaveHelpMen
testMenuBar->addMenu(AWSCoreEditorSystemComponent::EDITOR_HELP_MENU_TEXT);
AzToolsFramework::EditorEvents::Bus::Broadcast(&AzToolsFramework::EditorEvents::NotifyMainWindowInitialized, &testMainWindow);
EXPECT_TRUE(testMenuBar->actions().size() == 2);
- EXPECT_TRUE(QString::compare(testMenuBar->actions()[0]->text(), AWSCoreEditorManager::CLOUD_SERVICES_MENU_TEXT) == 0);
+ EXPECT_TRUE(QString::compare(testMenuBar->actions()[0]->text(), AWSCoreEditorManager::AWS_MENU_TEXT) == 0);
}
diff --git a/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreEditorMenuTest.cpp b/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreEditorMenuTest.cpp
index 7a578d2bbe..bde2a43993 100644
--- a/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreEditorMenuTest.cpp
+++ b/Gems/AWSCore/Code/Tests/Editor/UI/AWSCoreEditorMenuTest.cpp
@@ -14,6 +14,7 @@
#include
#include
+#include
#include
#include
#include
@@ -35,6 +36,7 @@ class AWSCoreEditorMenuTest
{
AWSCoreEditorUIFixture::SetUp();
AWSCoreFixture::SetUp();
+ m_localFileIO->SetAlias("@devroot@", "dummy engine root");
}
void TearDown() override
@@ -77,12 +79,12 @@ TEST_F(AWSCoreEditorMenuTest, AWSCoreEditorMenu_BroadcastFeatureGemsAreEnabled_C
QList actualActions = testMenu.actions();
for (QList::iterator itr = actualActions.begin(); itr != actualActions.end(); itr++)
{
- if (QString::compare((*itr)->text(), AWSCoreEditorMenu::AWSClientAuthActionText) == 0)
+ if (QString::compare((*itr)->text(), AWSClientAuthActionText) == 0)
{
EXPECT_TRUE((*itr)->isEnabled());
}
- if (QString::compare((*itr)->text(), AWSCoreEditorMenu::AWSMetricsActionText) == 0)
+ if (QString::compare((*itr)->text(), AWSMetricsActionText) == 0)
{
EXPECT_TRUE((*itr)->isEnabled());
}
diff --git a/Gems/AWSCore/Code/awscore_editor_files.cmake b/Gems/AWSCore/Code/awscore_editor_files.cmake
index 652f0455e1..13bfbb6102 100644
--- a/Gems/AWSCore/Code/awscore_editor_files.cmake
+++ b/Gems/AWSCore/Code/awscore_editor_files.cmake
@@ -12,6 +12,8 @@
set(FILES
Include/Private/AWSCoreEditorSystemComponent.h
Include/Private/Editor/AWSCoreEditorManager.h
+ Include/Private/Editor/Constants/AWSCoreEditorMenuLinks.h
+ Include/Private/Editor/Constants/AWSCoreEditorMenuNames.h
Include/Private/Editor/UI/AWSCoreEditorMenu.h
Include/Private/Editor/UI/AWSCoreResourceMappingToolAction.h
Source/AWSCoreEditorSystemComponent.cpp
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype
index 954e01c592..4d13663aae 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype
@@ -1,5 +1,5 @@
{
- "description": "Material Type with properties used to define Enhanced PBR material shading model.",
+ "description": "Material Type with properties used to define Enhanced PBR, a metallic-roughness Physically-Based Rendering (PBR) material shading model, with advanced features like subsurface scattering, transmission, and anisotropy.",
"propertyLayout": {
"version": 3,
"groups": [
@@ -32,7 +32,7 @@
"id": "clearCoat",
"displayName": "Clear Coat",
"description": "Properties for configuring gloss clear coat"
- },
+ },
{
"id": "normal",
"displayName": "Normal",
@@ -205,6 +205,13 @@
"id": "m_baseColorMap"
}
},
+ {
+ "id": "useTexture",
+ "displayName": "Use Texture",
+ "description": "Whether to use the texture map.",
+ "type": "Bool",
+ "defaultValue": true
+ },
{
"id": "textureMapUv",
"displayName": "UV",
@@ -228,13 +235,6 @@
"type": "ShaderOption",
"id": "o_baseColorTextureBlendMode"
}
- },
- {
- "id": "useTexture",
- "displayName": "Use Texture",
- "description": "Whether to use the texture map.",
- "type": "Bool",
- "defaultValue": true
}
],
"metallic": [
@@ -261,6 +261,13 @@
"id": "m_metallicMap"
}
},
+ {
+ "id": "useTexture",
+ "displayName": "Use Texture",
+ "description": "Whether to use the texture map, or just default to the Factor value.",
+ "type": "Bool",
+ "defaultValue": true
+ },
{
"id": "textureMapUv",
"displayName": "UV",
@@ -272,29 +279,9 @@
"type": "ShaderInput",
"id": "m_metallicMapUvIndex"
}
- },
- {
- "id": "useTexture",
- "displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
- "type": "Bool",
- "defaultValue": true
}
],
"roughness": [
- {
- "id": "factor",
- "displayName": "Factor",
- "description": "Strength factor for scaling the values",
- "type": "Float",
- "defaultValue": 1.0,
- "min": 0.0,
- "max": 1.0,
- "connection": {
- "type": "ShaderInput",
- "id": "m_roughnessFactor"
- }
- },
{
"id": "textureMap",
"displayName": "Texture Map",
@@ -305,6 +292,13 @@
"id": "m_roughnessMap"
}
},
+ {
+ "id": "useTexture",
+ "displayName": "Use Texture",
+ "description": "Whether to use the texture map, or just default to the Factor value.",
+ "type": "Bool",
+ "defaultValue": true
+ },
{
"id": "textureMapUv",
"displayName": "UV",
@@ -346,11 +340,18 @@
}
},
{
- "id": "useTexture",
- "displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
- "type": "Bool",
- "defaultValue": true
+ // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
+ "id": "factor",
+ "displayName": "Factor",
+ "description": "Controls the roughness value",
+ "type": "Float",
+ "defaultValue": 1.0,
+ "min": 0.0,
+ "max": 1.0,
+ "connection": {
+ "type": "ShaderInput",
+ "id": "m_roughnessFactor"
+ }
}
],
"anisotropy": [
@@ -416,6 +417,13 @@
"id": "m_specularF0Map"
}
},
+ {
+ "id": "useTexture",
+ "displayName": "Use Texture",
+ "description": "Whether to use the texture map, or just default to the Factor value.",
+ "type": "Bool",
+ "defaultValue": true
+ },
{
"id": "textureMapUv",
"displayName": "UV",
@@ -428,13 +436,7 @@
"id": "m_specularF0MapUvIndex"
}
},
- {
- "id": "useTexture",
- "displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
- "type": "Bool",
- "defaultValue": true
- },
+ // Consider moving this to the "general" group to be consistent with StandardMultilayerPBR
{
"id": "enableMultiScatterCompensation",
"displayName": "Multiscattering Compensation",
@@ -452,11 +454,7 @@
"displayName": "Enable",
"description": "Enable clear coat",
"type": "Bool",
- "defaultValue": false,
- "connection": {
- "type": "ShaderOption",
- "id": "o_clearCoat_feature_enabled"
- }
+ "defaultValue": false
},
{
"id": "factor",
@@ -481,6 +479,13 @@
"id": "m_clearCoatInfluenceMap"
}
},
+ {
+ "id": "useInfluenceMap",
+ "displayName": " Use Texture",
+ "description": "Whether to use the texture map, or just default to the Factor value.",
+ "type": "Bool",
+ "defaultValue": true
+ },
{
"id": "influenceMapUv",
"displayName": " UV",
@@ -493,13 +498,6 @@
"id": "m_clearCoatInfluenceMapUvIndex"
}
},
- {
- "id": "useInfluenceMap",
- "displayName": " Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
- "type": "Bool",
- "defaultValue": true
- },
{
"id": "roughness",
"displayName": "Roughness",
@@ -523,6 +521,13 @@
"id": "m_clearCoatRoughnessMap"
}
},
+ {
+ "id": "useRoughnessMap",
+ "displayName": " Use Texture",
+ "description": "Whether to use the texture map, or just default to the roughness value.",
+ "type": "Bool",
+ "defaultValue": true
+ },
{
"id": "roughnessMapUv",
"displayName": " UV",
@@ -535,13 +540,6 @@
"id": "m_clearCoatRoughnessMapUvIndex"
}
},
- {
- "id": "useRoughnessMap",
- "displayName": " Use Texture",
- "description": "Whether to use the texture map, or just default to the roughness value.",
- "type": "Bool",
- "defaultValue": true
- },
{
"id": "normalStrength",
"displayName": "Normal Strength",
@@ -565,9 +563,16 @@
"id": "m_clearCoatNormalMap"
}
},
+ {
+ "id": "useNormalMap",
+ "displayName": " Use Texture",
+ "description": "Whether to use the normal map",
+ "type": "Bool",
+ "defaultValue": true
+ },
{
"id": "normalMapUv",
- "displayName": "UV",
+ "displayName": " UV",
"description": "Normal texture map UV set",
"type": "Enum",
"enumIsUv": true,
@@ -576,29 +581,9 @@
"type": "ShaderInput",
"id": "m_clearCoatNormalMapUvIndex"
}
- },
- {
- "id": "useNormalMap",
- "displayName": "Use Texture",
- "description": "Whether to use the normal map",
- "type": "Bool",
- "defaultValue": true
}
],
"normal": [
- {
- "id": "factor",
- "displayName": "Factor",
- "description": "Strength factor for scaling the values",
- "type": "Float",
- "defaultValue": 1.0,
- "min": 0.0,
- "softMax": 2.0,
- "connection": {
- "type": "ShaderInput",
- "id": "m_normalFactor"
- }
- },
{
"id": "textureMap",
"displayName": "Texture Map",
@@ -609,6 +594,13 @@
"id": "m_normalMap"
}
},
+ {
+ "id": "useTexture",
+ "displayName": "Use Texture",
+ "description": "Whether to use the texture map, or just rely on vertex normals.",
+ "type": "Bool",
+ "defaultValue": true
+ },
{
"id": "textureMapUv",
"displayName": "UV",
@@ -621,13 +613,6 @@
"id": "m_normalMapUvIndex"
}
},
- {
- "id": "useTexture",
- "displayName": "Use Texture",
- "description": "Whether to use the texture map, or just rely on vertex normals.",
- "type": "Bool",
- "defaultValue": true
- },
{
"id": "flipX",
"displayName": "Flip X Channel",
@@ -649,6 +634,19 @@
"type": "ShaderInput",
"id": "m_flipNormalY"
}
+ },
+ {
+ "id": "factor",
+ "displayName": "Factor",
+ "description": "Strength factor for scaling the values",
+ "type": "Float",
+ "defaultValue": 1.0,
+ "min": 0.0,
+ "softMax": 2.0,
+ "connection": {
+ "type": "ShaderInput",
+ "id": "m_normalFactor"
+ }
}
],
"opacity": [
@@ -725,7 +723,7 @@
"description": "Center point for scaling and rotation transformations.",
"type": "vector2",
"vectorLabels": [ "U", "V" ],
- "defaultValue": [ 0.0, 0.0 ]
+ "defaultValue": [ 0.5, 0.5 ]
},
{
"id": "tileU",
@@ -872,18 +870,14 @@
"displayName": "Enable",
"description": "Enable the emissive group",
"type": "Bool",
- "defaultValue": false,
- "connection": {
- "type": "ShaderOption",
- "id": "o_emissiveEnabled"
- }
+ "defaultValue": false
},
{
"id": "unit",
"displayName": "Units",
"description": "The photometric units of the Intensity property.",
"type": "Enum",
- "enumValues": [ "Ev100" ],
+ "enumValues": ["Ev100"],
"defaultValue": "Ev100"
},
{
@@ -918,34 +912,27 @@
"id": "m_emissiveMap"
}
},
- {
- "id": "textureMapUv",
- "displayName": "UV",
- "description": "Emissive texture map UV set",
- "type": "Enum",
- "enumValues": [ "UV0", "UV1" ],
- "defaultValue": "UV0",
- "connection": {
- "type": "ShaderInput",
- "id": "m_emissiveMapUvIndex"
- }
- },
{
"id": "useTexture",
"displayName": "Use Texture",
"description": "Whether to use the texture map.",
"type": "Bool",
"defaultValue": true
+ },
+ {
+ "id": "textureMapUv",
+ "displayName": "UV",
+ "description": "Emissive texture map UV set",
+ "type": "Enum",
+ "enumIsUv": true,
+ "defaultValue": "Tiled",
+ "connection": {
+ "type": "ShaderInput",
+ "id": "m_emissiveMapUvIndex"
+ }
}
],
"parallax": [
- {
- "id": "enable",
- "displayName": "Enable",
- "description": "Whether to enable the parallax feature.",
- "type": "Bool",
- "defaultValue": false
- },
{
"id": "textureMap",
"displayName": "Texture Map",
@@ -956,13 +943,20 @@
"id": "m_depthMap"
}
},
+ {
+ "id": "useTexture",
+ "displayName": "Use Texture",
+ "description": "Whether to use the texture map.",
+ "type": "Bool",
+ "defaultValue": true
+ },
{
"id": "textureMapUv",
"displayName": "UV",
"description": "Depth texture map UV set",
"type": "Enum",
- "enumValues": [ "UV0", "UV1" ],
- "defaultValue": "UV0",
+ "enumIsUv": true,
+ "defaultValue": "Tiled",
"connection": {
"type": "ShaderInput",
"id": "m_parallaxUvIndex"
@@ -973,7 +967,7 @@
"displayName": "Heightmap Scale",
"description": "The total height of the heightmap in local model units.",
"type": "Float",
- "defaultValue": 0.0,
+ "defaultValue": 0.05,
"min": 0.0,
"softMax": 0.1,
"connection": {
@@ -1011,7 +1005,7 @@
"description": "Select the algorithm to use for parallax mapping.",
"type": "Enum",
"enumValues": [ "Basic", "Steep", "POM", "Relief", "ContactRefinement" ],
- "defaultValue": "Basic",
+ "defaultValue": "POM",
"connection": {
"type": "ShaderOption",
"id": "o_parallax_algorithm"
@@ -1055,7 +1049,7 @@
"subsurfaceScattering": [
{
"id": "enableSubsurfaceScattering",
- "displayName": "Enable Subsurface Scattering",
+ "displayName": "Subsurface Scattering",
"description": "Enable subsurface scattering feature, this will disable metallic and parallax mapping property due to incompatibility",
"type": "Bool",
"defaultValue": false,
@@ -1069,7 +1063,7 @@
"displayName": " Factor",
"description": "Strength factor for scaling percentage of subsurface scattering effect applied",
"type": "float",
- "defaultValue": 0.0,
+ "defaultValue": 1.0,
"min": 0.0,
"max": 1.0,
"connection": {
@@ -1087,18 +1081,6 @@
"id": "m_subsurfaceScatteringInfluenceMap"
}
},
- {
- "id": "influenceMapUv",
- "displayName": " UV",
- "description": "Influence map UV set",
- "type": "Enum",
- "enumValues": [ "UV0", "UV1" ],
- "defaultValue": "UV0",
- "connection": {
- "type": "ShaderInput",
- "id": "m_subsurfaceScatteringInfluenceMapUvIndex"
- }
- },
{
"id": "useInfluenceMap",
"displayName": " Use Influence Map",
@@ -1106,6 +1088,18 @@
"type": "Bool",
"defaultValue": true
},
+ {
+ "id": "influenceMapUv",
+ "displayName": " UV",
+ "description": "Influence map UV set",
+ "type": "Enum",
+ "enumIsUv": true,
+ "defaultValue": "Tiled",
+ "connection": {
+ "type": "ShaderInput",
+ "id": "m_subsurfaceScatteringInfluenceMapUvIndex"
+ }
+ },
{
"id": "scatterColor",
"displayName": " Scatter color",
@@ -1136,11 +1130,16 @@
}
},
{
- "id": "enableTransmission",
- "displayName": "Enable Transmission",
- "description": "Enable transmission feature",
- "type": "Bool",
- "defaultValue": false
+ "id": "transmissionMode",
+ "displayName": "Transmission",
+ "description": "Algorithm used for calculating transmission",
+ "type": "Enum",
+ "enumValues": [ "None", "ThickObject", "ThinObject" ],
+ "defaultValue": "None",
+ "connection": {
+ "type": "ShaderOption",
+ "id": "o_transmission_mode"
+ }
},
{
"id": "thickness",
@@ -1161,18 +1160,6 @@
"id": "m_transmissionThicknessMap"
}
},
- {
- "id": "thicknessMapUv",
- "displayName": " UV",
- "description": "Thickness map UV set",
- "type": "Enum",
- "enumValues": [ "UV0", "UV1" ],
- "defaultValue": "UV0",
- "connection": {
- "type": "ShaderInput",
- "id": "m_transmissionThicknessMapUvIndex"
- }
- },
{
"id": "useThicknessMap",
"displayName": " Use Thickness Map",
@@ -1180,6 +1167,18 @@
"type": "Bool",
"defaultValue": true
},
+ {
+ "id": "thicknessMapUv",
+ "displayName": " UV",
+ "description": "Thickness map UV set",
+ "type": "Enum",
+ "enumIsUv": true,
+ "defaultValue": "Tiled",
+ "connection": {
+ "type": "ShaderInput",
+ "id": "m_transmissionThicknessMapUvIndex"
+ }
+ },
{
"id": "transmissionTint",
"displayName": " Transmission Tint",
@@ -1187,18 +1186,6 @@
"type": "Color",
"defaultValue": [ 1.0, 0.8, 0.6 ]
},
- {
- "id": "transmissionMode",
- "displayName": " Mode",
- "description": "Algorithm used for calculating transmission",
- "type": "Enum",
- "enumValues": [ "None", "ThickObject", "ThinObject" ],
- "defaultValue": "None",
- "connection": {
- "type": "ShaderOption",
- "id": "o_transmission_mode"
- }
- },
{
"id": "transmissionPower",
"displayName": " Power",
@@ -1287,7 +1274,7 @@
}
},
{
- "id": "detailMapsMapUv",
+ "id": "textureMapUv",
"displayName": "Detail Map UVs",
"description": "Which UV set to use for detail map texture sampling",
"type": "Enum",
@@ -1388,7 +1375,7 @@
"description": "Center point for scaling and rotation transformations.",
"type": "vector2",
"vectorLabels": [ "U", "V" ],
- "defaultValue": [ 0.0, 0.0 ]
+ "defaultValue": [ 0.5, 0.5 ]
},
{
"id": "tileU",
@@ -1506,7 +1493,7 @@
{
"file": "Shaders/Depth/DepthPassTransparentMax.shader",
"tag": "DepthPassTransparentMax"
- }
+ }
],
"functors": [
{
@@ -1549,26 +1536,9 @@
"lightUnitProperty": "emissive.unit",
"shaderInput": "m_emissiveIntensity",
"ev100Index": 0,
- "nitIndex": 1,
- "ev100MinMax": [ -10, 20 ],
- "nitMinMax": [ 0.001, 100000.0 ]
- }
- },
- {
- // Enable/Disable shader based on different option.
- "type": "ShaderEnable",
- "args": {
- "opacityMode": "opacity.mode",
- "parallaxEnable": "parallax.enable",
- "parallaxPdoEnable": "parallax.pdo",
- "pbrShaderNoEdsIndex": 0,
- "pbrShaderWithEdsIndex": 1,
- "shadowShaderNoPSIndex": 2,
- "shadowShaderWithPSIndex": 3,
- "depthShaderNoPSIndex": 4,
- "depthShaderWithPSIndex": 5,
- "depthShaderTransparentMin": 8,
- "depthShaderTransparentMax": 9
+ "nitIndex" : 1,
+ "ev100MinMax": [-10, 20],
+ "nitMinMax": [0.001, 100000.0]
}
},
{
@@ -1590,120 +1560,40 @@
"tintThickenssShaderInput": "m_transmissionTintThickness"
}
},
- {
- // Reads material properties to determine whether a specific texture map should be sampled at runtime, and sets a shader option accordingly.
- // @param textureProperty - which material property contains the texture asset reference (or maybe null)
- // @param useTextureProperty - a boolean flag that toggles whether the texture should be sampled (if it's not null)
- // @param shaderTags - which shader in the 'shaders' list above is configured by this functor
- // @param shaderOption - the name of a shader option in the AZSL file that controls sampling of this texture
+ {
"type": "UseTexture",
"args": {
"textureProperty": "baseColor.textureMap",
- "dependentProperties": ["baseColor.textureMapUv"],
"useTextureProperty": "baseColor.useTexture",
- "shaderTags": [
- "ForwardPass",
- "ForwardPass_EDS"
- ],
+ "dependentProperties": ["baseColor.textureMapUv", "baseColor.textureBlendMode"],
"shaderOption": "o_baseColor_useTexture"
}
},
{
- // See the comment above for details.
"type": "UseTexture",
"args": {
"textureProperty": "metallic.textureMap",
- "dependentProperties": ["metallic.textureMapUv"],
"useTextureProperty": "metallic.useTexture",
- "shaderTags": [
- "ForwardPass",
- "ForwardPass_EDS"
- ],
+ "dependentProperties": ["metallic.textureMapUv"],
"shaderOption": "o_metallic_useTexture"
}
},
{
- // See the comment above for details.
- "type": "UseTexture",
- "args": {
- "textureProperty": "roughness.textureMap",
- "dependentProperties": ["roughness.textureMapUv"],
- "useTextureProperty": "roughness.useTexture",
- "shaderTags": [
- "ForwardPass",
- "ForwardPass_EDS"
- ],
- "shaderOption": "o_roughness_useTexture"
- }
- },
- {
- // See the comment above for details.
"type": "UseTexture",
"args": {
"textureProperty": "specularF0.textureMap",
- "dependentProperties": ["specularF0.textureMapUv"],
"useTextureProperty": "specularF0.useTexture",
- "shaderTags": [
- "ForwardPass",
- "ForwardPass_EDS"
- ],
+ "dependentProperties": ["specularF0.textureMapUv"],
"shaderOption": "o_specularF0_useTexture"
}
},
{
- // See the comment above for details.
- "type": "UseTexture",
- "args": {
- "textureProperty": "clearCoat.influenceMap",
- "dependentProperties": ["clearCoat.influenceMapUv"],
- "useTextureProperty": "clearCoat.useInfluenceMap",
- "shaderTags": [
- "ForwardPass",
- "ForwardPass_EDS"
- ],
- "shaderOption": "o_clearCoat_factor_useTexture"
- }
- },
- {
- // See the comment above for details.
- "type": "UseTexture",
- "args": {
- "textureProperty": "clearCoat.roughnessMap",
- "dependentProperties": ["clearCoat.roughnessMapUv"],
- "useTextureProperty": "clearCoat.useRoughnessMap",
- "shaderTags": [
- "ForwardPass",
- "ForwardPass_EDS"
- ],
- "shaderOption": "o_clearCoat_roughness_useTexture"
- }
- },
- {
- // See the comment above for details.
- "type": "UseTexture",
- "args": {
- "textureProperty": "clearCoat.normalMap",
- "dependentProperties": ["clearCoat.normalMapUv"],
- "useTextureProperty": "clearCoat.useNormalMap",
- "shaderTags": [
- "ForwardPass",
- "ForwardPass_EDS"
- ],
- "shaderOption": "o_clearCoat_normal_useTexture"
- }
- },
- {
- // See the comment above for details.
"type": "UseTexture",
"args": {
"textureProperty": "normal.textureMap",
- "dependentProperties": ["normal.textureMapUv"],
"useTextureProperty": "normal.useTexture",
- "shaderTags": [
- "ForwardPass",
- "ForwardPass_EDS"
- ],
- "shaderOption": "o_normal_useTexture"
+ "dependentProperties": ["normal.textureMapUv", "normal.factor", "normal.flipX", "normal.flipY"],
+ "shaderOption": "o_normal_useTexture"
}
},
{
@@ -1725,335 +1615,21 @@
}
},
{
- // See the comment above for details.
- "type": "UseTexture",
+ "type": "Lua",
"args": {
- "textureProperty": "emissive.textureMap",
- "dependentProperties": ["emissive.textureMapUv"],
- "useTextureProperty": "emissive.useTexture",
- "shaderTags": [
- "ForwardPass",
- "ForwardPass_EDS"
- ],
- "shaderOption": "o_emissive_useTexture"
+ "file": "StandardPBR_ClearCoatState.lua"
}
},
{
- // See the comment above for details.
- "type": "UseTexture",
+ "type": "Lua",
"args": {
- "textureProperty": "subsurfaceScattering.influenceMap",
- "dependentProperties": ["subsurfaceScattering.influenceMapUv"],
- "useTextureProperty": "subsurfaceScattering.useInfluenceMap",
- "shaderTags": [
- "ForwardPass",
- "ForwardPass_EDS"
- ],
- "shaderOption": "o_subsurfaceScattering_useTexture"
+ "file": "StandardPBR_ClearCoatEnableFeature.lua"
}
},
{
- // See the comment above for details.
- "type": "UseTexture",
+ "type": "Lua",
"args": {
- "textureProperty": "subsurfaceScattering.thicknessMap",
- "dependentProperties": ["subsurfaceScattering.thicknessMapUv"],
- "useTextureProperty": "subsurfaceScattering.useThicknessMap",
- "shaderTags": [
- "ForwardPass",
- "ForwardPass_EDS"
- ],
- "shaderOption": "o_transmission_useTexture"
- }
- },
- {
- // Controls visibility for properties in the editor.
- // @param actions - a list of actions that are executed in order. visibility will be set when triggerProperty hits the triggerValue.
- // @param affectedProperties - the properties that are affected by actions.
- "type": "UpdatePropertyVisibility",
- "args": {
- "actions": [
- {
- "triggerProperty": "emissive.enable",
- "triggerValue": true,
- "visibility": "Enabled"
- },
- {
- "triggerProperty": "emissive.enable",
- "triggerValue": false,
- "visibility": "Hidden"
- }
- ],
- "affectedProperties": [
- "emissive.color",
- "emissive.intensity",
- "emissive.useTexture",
- "emissive.unit"
- ]
- }
- },
- {
- // Controls visibility for properties in the editor.
- // @param actions - a list of actions that are executed in order. visibility will be set when triggerProperty hits the triggerValue.
- // @param affectedProperties - the properties that are affected by actions.
- "type": "UpdatePropertyVisibility",
- "args": {
- "actions": [
- {
- "triggerProperty": "emissive.useTexture",
- "triggerValue": true,
- "visibility": "Enabled"
- },
- {
- "triggerProperty": "emissive.useTexture",
- "triggerValue": false,
- "visibility": "Disabled"
- },
- {
- "triggerProperty": "emissive.enable",
- "triggerValue": false,
- "visibility": "Hidden"
- }
- ],
- "affectedProperties": [
- "emissive.textureMap",
- "emissive.textureMapUv"
- ]
- }
- },
- {
- "type": "UpdatePropertyVisibility",
- "args": {
- "actions": [
- {
- "triggerProperty": "clearCoat.useInfluenceMap",
- "triggerValue": true,
- "visibility": "Enabled"
- },
- {
- "triggerProperty": "clearCoat.useInfluenceMap",
- "triggerValue": false,
- "visibility": "Disabled"
- },
- {
- "triggerProperty": "clearCoat.enable",
- "triggerValue": false,
- "visibility": "Hidden"
- }
- ],
- "affectedProperties": [
- "clearCoat.influenceMap",
- "clearCoat.influenceMapUv"
- ]
- }
- },
- {
- "type": "UpdatePropertyVisibility",
- "args": {
- "actions": [
- {
- "triggerProperty": "clearCoat.useRoughnessMap",
- "triggerValue": true,
- "visibility": "Enabled"
- },
- {
- "triggerProperty": "clearCoat.useRoughnessMap",
- "triggerValue": false,
- "visibility": "Disabled"
- },
- {
- "triggerProperty": "clearCoat.enable",
- "triggerValue": false,
- "visibility": "Hidden"
- }
- ],
- "affectedProperties": [
- "clearCoat.roughnessMap",
- "clearCoat.roughnessMapUv"
- ]
- }
- },
- {
- "type": "UpdatePropertyVisibility",
- "args": {
- "actions": [
- {
- "triggerProperty": "clearCoat.useNormalMap",
- "triggerValue": true,
- "visibility": "Enabled"
- },
- {
- "triggerProperty": "clearCoat.useNormalMap",
- "triggerValue": false,
- "visibility": "Disabled"
- },
- {
- "triggerProperty": "clearCoat.enable",
- "triggerValue": false,
- "visibility": "Hidden"
- }
- ],
- "affectedProperties": [
- "clearCoat.normalMap",
- "clearCoat.normalMapUv"
- ]
- }
-
- },
- {
- "type": "UpdatePropertyVisibility",
- "args": {
- "actions": [
- {
- "triggerProperty": "subsurfaceScattering.useInfluenceMap",
- "triggerValue": true,
- "visibility": "Enabled"
- },
- {
- "triggerProperty": "subsurfaceScattering.useInfluenceMap",
- "triggerValue": false,
- "visibility": "Disabled"
- },
- {
- "triggerProperty": "subsurfaceScattering.enableSubsurfaceScattering",
- "triggerValue": false,
- "visibility": "Hidden"
- }
- ],
- "affectedProperties": [
- "subsurfaceScattering.influenceMap",
- "subsurfaceScattering.influenceMapUv"
- ]
- }
- },
- {
- "type": "UpdatePropertyVisibility",
- "args": {
- "actions": [
- {
- "triggerProperty": "subsurfaceScattering.useThicknessMap",
- "triggerValue": true,
- "visibility": "Enabled"
- },
- {
- "triggerProperty": "subsurfaceScattering.useThicknessMap",
- "triggerValue": false,
- "visibility": "Disabled"
- },
- {
- "triggerProperty": "subsurfaceScattering.enableTransmission",
- "triggerValue": false,
- "visibility": "Hidden"
- }
- ],
- "affectedProperties": [
- "subsurfaceScattering.thicknessMap",
- "subsurfaceScattering.thicknessMapUv"
- ]
- }
- },
- {
- "type": "UpdatePropertyVisibility",
- "args": {
- "actions": [
- {
- "triggerProperty": "clearCoat.enable",
- "triggerValue": true,
- "visibility": "Enabled"
- },
- {
- "triggerProperty": "clearCoat.enable",
- "triggerValue": false,
- "visibility": "Hidden"
- }
- ],
- "affectedProperties": [
- "clearCoat.factor",
- "clearCoat.useInfluenceMap",
- "clearCoat.roughness",
- "clearCoat.useRoughnessMap",
- "clearCoat.useNormalMap"
- ]
- }
- },
- {
- "type": "UpdatePropertyVisibility",
- "args": {
- "actions": [
- {
- "triggerProperty": "subsurfaceScattering.transmissionMode",
- "triggerValue": "ThickObject",
- "visibility": "Enabled"
- },
- {
- "triggerProperty": "subsurfaceScattering.transmissionMode",
- "triggerValue": "None",
- "visibility": "Hidden"
- },
- {
- "triggerProperty": "subsurfaceScattering.transmissionMode",
- "triggerValue": "ThinObject",
- "visibility": "Hidden"
- },
- {
- "triggerProperty": "subsurfaceScattering.enableTransmission",
- "triggerValue": false,
- "visibility": "Hidden"
- }
- ],
- "affectedProperties": [
- "subsurfaceScattering.transmissionPower",
- "subsurfaceScattering.transmissionDistortion",
- "subsurfaceScattering.transmissionAttenuation"
- ]
- }
- },
- {
- "type": "UpdatePropertyVisibility",
- "args": {
- "actions": [
- {
- "triggerProperty": "subsurfaceScattering.enableSubsurfaceScattering",
- "triggerValue": true,
- "visibility": "Enabled"
- },
- {
- "triggerProperty": "subsurfaceScattering.enableSubsurfaceScattering",
- "triggerValue": false,
- "visibility": "Hidden"
- }
- ],
- "affectedProperties": [
- "subsurfaceScattering.subsurfaceScatterFactor",
- "subsurfaceScattering.useInfluenceMap",
- "subsurfaceScattering.scatterColor",
- "subsurfaceScattering.scatterDistance",
- "subsurfaceScattering.quality"
- ]
- }
- },
- {
- "type": "UpdatePropertyVisibility",
- "args": {
- "actions": [
- {
- "triggerProperty": "subsurfaceScattering.enableTransmission",
- "triggerValue": true,
- "visibility": "Enabled"
- },
- {
- "triggerProperty": "subsurfaceScattering.enableTransmission",
- "triggerValue": false,
- "visibility": "Hidden"
- }
- ],
- "affectedProperties": [
- "subsurfaceScattering.thickness",
- "subsurfaceScattering.useThicknessMap",
- "subsurfaceScattering.transmissionTint",
- "subsurfaceScattering.transmissionMode",
- "subsurfaceScattering.transmissionScale"
- ]
+ "file": "StandardPBR_EmissiveState.lua"
}
},
{
@@ -2062,30 +1638,24 @@
"file": "StandardPBR_ParallaxState.lua"
}
},
+ {
+ "type": "Lua",
+ "args": {
+ "file": "StandardPBR_Roughness.lua"
+ }
+ },
+ {
+ "type": "Lua",
+ "args": {
+ "file": "StandardPBR_SubsurfaceState.lua"
+ }
+ },
{
"type": "Lua",
"args": {
"file": "StandardPBR_HandleOpacityDoubleSided.lua"
}
},
- {
- "type": "OverrideDrawList",
- "args": {
- "triggerProperty": "opacity.mode",
- "triggerValue": "Blended",
- "shaderIndex": 1,
- "drawList": "transparent"
- }
- },
- {
- "type": "OverrideDrawList",
- "args": {
- "triggerProperty": "opacity.mode",
- "triggerValue": "TintedTransparent",
- "shaderIndex": 1,
- "drawList": "transparent"
- }
- },
{
"type": "Lua",
"args": {
@@ -2097,6 +1667,12 @@
"args": {
"file": "MaterialInputs/DetailMapsCommonFunctor.lua"
}
+ },
+ {
+ "type": "Lua",
+ "args": {
+ "file": "StandardPBR_ShaderEnable.lua"
+ }
}
],
"uvNameMap": {
@@ -2104,3 +1680,4 @@
"UV1": "Unwrapped"
}
}
+
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl
index 440bb97c4e..a4fcccb5f5 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl
@@ -267,16 +267,16 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
// Directional light shadow coordinates
lightingData.shadowCoords = IN.m_shadowCoords;
- // ------- Occlusion -------
-
- lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture);
- lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture);
-
// ------- Emissive -------
float2 emissiveUv = IN.m_uv[MaterialSrg::m_emissiveMapUvIndex];
lightingData.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture);
+ // ------- Occlusion -------
+
+ lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture);
+ lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture);
+
// ------- Clearcoat -------
// [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype
index 101a03b907..f8c49d579c 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype
@@ -287,6 +287,13 @@
"id": "m_specularF0Map"
}
},
+ {
+ "id": "useTexture",
+ "displayName": "Use Texture",
+ "description": "Whether to use the texture map, or just default to the Factor value.",
+ "type": "Bool",
+ "defaultValue": true
+ },
{
"id": "textureMapUv",
"displayName": "UV",
@@ -299,13 +306,7 @@
"id": "m_specularF0MapUvIndex"
}
},
- {
- "id": "useTexture",
- "displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
- "type": "Bool",
- "defaultValue": true
- },
+ // Consider moving this to the "general" group to be consistent with StandardMultilayerPBR
{
"id": "enableMultiScatterCompensation",
"displayName": "Multiscattering Compensation",
@@ -616,7 +617,7 @@
"type": "float",
"defaultValue": 6.0,
"min": 0.0,
- "softMax": 20.0
+ "softMax": 20.0
},
{
"id": "transmissionDistortion",
@@ -909,7 +910,7 @@
"description": "Center point for scaling and rotation transformations.",
"type": "vector2",
"vectorLabels": [ "U", "V" ],
- "defaultValue": [ 0.0, 0.0 ]
+ "defaultValue": [ 0.5, 0.5 ]
},
{
"id": "tileU",
@@ -1011,18 +1012,18 @@
"type": "HandleSubsurfaceScatteringParameters",
"args": {
"mode": "subsurfaceScattering.transmissionMode",
- "scale" : "subsurfaceScattering.transmissionScale",
- "power" : "subsurfaceScattering.transmissionPower",
- "distortion" : "subsurfaceScattering.transmissionDistortion",
- "attenuation" : "subsurfaceScattering.transmissionAttenuation",
- "tintColor" : "subsurfaceScattering.transmissionTint",
- "thickness" : "subsurfaceScattering.thickness",
+ "scale": "subsurfaceScattering.transmissionScale",
+ "power": "subsurfaceScattering.transmissionPower",
+ "distortion": "subsurfaceScattering.transmissionDistortion",
+ "attenuation": "subsurfaceScattering.transmissionAttenuation",
+ "tintColor": "subsurfaceScattering.transmissionTint",
+ "thickness": "subsurfaceScattering.thickness",
"enabled": "subsurfaceScattering.enableSubsurfaceScattering",
- "scatterDistanceColor" : "subsurfaceScattering.scatterColor",
- "scatterDistanceIntensity" : "subsurfaceScattering.scatterDistance",
- "scatterDistanceShaderInput" : "m_scatterDistance",
- "parametersShaderInput" : "m_transmissionParams",
- "tintThickenssShaderInput" : "m_transmissionTintThickness"
+ "scatterDistanceColor": "subsurfaceScattering.scatterColor",
+ "scatterDistanceIntensity": "subsurfaceScattering.scatterDistance",
+ "scatterDistanceShaderInput": "m_scatterDistance",
+ "parametersShaderInput": "m_transmissionParams",
+ "tintThickenssShaderInput": "m_transmissionTintThickness"
}
},
{
@@ -1038,8 +1039,8 @@
"type": "UseTexture",
"args": {
"textureProperty": "specularF0.textureMap",
- "dependentProperties": ["specularF0.textureMapUv"],
"useTextureProperty": "specularF0.useTexture",
+ "dependentProperties": ["specularF0.textureMapUv"],
"shaderOption": "o_specularF0_useTexture"
}
},
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype
index 274cb4dcb5..ec1298ae77 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype
@@ -369,15 +369,14 @@
],
"parallax": [
{
+ // Note parallax is enabled by default so that as soon as a user hooks up displacement settings they will see some parallax applied.
+ // The functor that controls parallax will set o_parallax_feature_enabled=false when all the individual layers have no displacement, so
+ // a default value of true here will not have any initial impact on performance.
"id": "enable",
"displayName": "Enable",
"description": "Whether to enable the parallax feature for this material.",
"type": "Bool",
- "defaultValue": false,
- "connection": {
- "type": "ShaderOption",
- "id": "o_parallax_feature_enabled"
- }
+ "defaultValue": true
},
{
"id": "parallaxUv",
@@ -409,7 +408,7 @@
"description": "Quality of parallax mapping.",
"type": "Enum",
"enumValues": [ "Low", "Medium", "High", "Ultra" ],
- "defaultValue": "Medium",
+ "defaultValue": "Low",
"connection": {
"type": "ShaderOption",
"id": "o_parallax_quality"
@@ -445,7 +444,7 @@
"description": "Center point for scaling and rotation transformations.",
"type": "vector2",
"vectorLabels": [ "U", "V" ],
- "defaultValue": [ 0.0, 0.0 ]
+ "defaultValue": [ 0.5, 0.5 ]
},
{
"id": "tileU",
@@ -1141,7 +1140,7 @@
"displayName": "Scale",
"description": "The total height of the displacement texture map in local model units.",
"type": "Float",
- "defaultValue": 0.0,
+ "defaultValue": 0.05,
"min": 0.0,
"softMax": 0.1,
"connection": {
@@ -1170,7 +1169,7 @@
"description": "Center point for scaling and rotation transformations.",
"type": "vector2",
"vectorLabels": [ "U", "V" ],
- "defaultValue": [ 0.0, 0.0 ]
+ "defaultValue": [ 0.5, 0.5 ]
},
{
"id": "tileU",
@@ -1847,7 +1846,7 @@
"displayName": "Scale",
"description": "The total height of the displacement texture map in local model units.",
"type": "Float",
- "defaultValue": 0.0,
+ "defaultValue": 0.05,
"min": 0.0,
"softMax": 0.1,
"connection": {
@@ -1876,7 +1875,7 @@
"description": "Center point for scaling and rotation transformations.",
"type": "vector2",
"vectorLabels": [ "U", "V" ],
- "defaultValue": [ 0.0, 0.0 ]
+ "defaultValue": [ 0.5, 0.5 ]
},
{
"id": "tileU",
@@ -2553,7 +2552,7 @@
"displayName": "Scale",
"description": "The total height of the displacement texture map in local model units.",
"type": "Float",
- "defaultValue": 0.0,
+ "defaultValue": 0.05,
"min": 0.0,
"softMax": 0.1,
"connection": {
@@ -2582,7 +2581,7 @@
"description": "Center point for scaling and rotation transformations.",
"type": "vector2",
"vectorLabels": [ "U", "V" ],
- "defaultValue": [ 0.0, 0.0 ]
+ "defaultValue": [ 0.5, 0.5 ]
},
{
"id": "tileU",
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua
index 34a067577d..d2bf8f28d3 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua
@@ -35,6 +35,10 @@ function GetMaterialPropertyDependencies()
}
end
+function GetShaderOptionDependencies()
+ return {"o_parallax_feature_enabled"}
+end
+
-- These values must align with LayerBlendSource in StandardMultilayerPBR_Common.azsli.
LayerBlendSource_BlendMaskTexture = 0
LayerBlendSource_BlendMaskVertexColors = 1
@@ -50,6 +54,39 @@ function BlendSourceUsesDisplacement(context)
return blendSourceIncludesDisplacement
end
+function IsParallaxNeededForLayer(context, layerNumber)
+ local enableLayer = true
+ if(layerNumber > 1) then -- layer 1 is always enabled, it is the implicit base layer
+ enableLayer = context:GetMaterialPropertyValue_bool("blend.enableLayer" .. layerNumber)
+ end
+
+ if not enableLayer then
+ return false
+ end
+
+ local parallaxGroupName = "layer" .. layerNumber .. "_parallax."
+
+ local factor = context:GetMaterialPropertyValue_float(parallaxGroupName .. "factor")
+ local offset = context:GetMaterialPropertyValue_float(parallaxGroupName .. "offset")
+
+ if factor == 0.0 and offset == 0.0 then
+ return false
+ end
+
+ local hasTexture = nil ~= context:GetMaterialPropertyValue_Image(parallaxGroupName .. "textureMap")
+ local useTexture = context:GetMaterialPropertyValue_bool(parallaxGroupName .. "useTexture")
+
+ if not hasTexture or not useTexture then
+ factorLayer = 0.0
+ end
+
+ if factor == 0.0 and offset == 0.0 then
+ return false
+ end
+
+ return true
+end
+
-- Calculates the min and max displacement height values encompassing all enabled layers.
-- @return a table with two values {min,max}. Negative values are below the surface and positive values are above the surface.
function CalcOverallHeightRange(context)
@@ -114,21 +151,32 @@ function Process(context)
local heightMinMax = CalcOverallHeightRange(context)
context:SetShaderConstant_float("m_displacementMin", heightMinMax[0])
context:SetShaderConstant_float("m_displacementMax", heightMinMax[1])
+
+ local parallaxFeatureEnabled = context:GetMaterialPropertyValue_bool("parallax.enable")
+ if parallaxFeatureEnabled then
+ if not IsParallaxNeededForLayer(context, 1) and
+ not IsParallaxNeededForLayer(context, 2) and
+ not IsParallaxNeededForLayer(context, 3) then
+ parallaxFeatureEnabled = false
+ end
+ end
+
+ context:SetShaderOptionValue_bool("o_parallax_feature_enabled", parallaxFeatureEnabled)
end
function ProcessEditor(context)
- local enable = context:GetMaterialPropertyValue_bool("parallax.enable")
+ local enableParallaxSettings = context:GetMaterialPropertyValue_bool("parallax.enable")
- local visibility = MaterialPropertyVisibility_Enabled
- if(not enable) then
- visibility = MaterialPropertyVisibility_Hidden
+ local parallaxSettingVisibility = MaterialPropertyVisibility_Enabled
+ if(not enableParallaxSettings) then
+ parallaxSettingVisibility = MaterialPropertyVisibility_Hidden
end
- context:SetMaterialPropertyVisibility("parallax.parallaxUv", visibility)
- context:SetMaterialPropertyVisibility("parallax.algorithm", visibility)
- context:SetMaterialPropertyVisibility("parallax.quality", visibility)
- context:SetMaterialPropertyVisibility("parallax.pdo", visibility)
- context:SetMaterialPropertyVisibility("parallax.showClipping", visibility)
+ context:SetMaterialPropertyVisibility("parallax.parallaxUv", parallaxSettingVisibility)
+ context:SetMaterialPropertyVisibility("parallax.algorithm", parallaxSettingVisibility)
+ context:SetMaterialPropertyVisibility("parallax.quality", parallaxSettingVisibility)
+ context:SetMaterialPropertyVisibility("parallax.pdo", parallaxSettingVisibility)
+ context:SetMaterialPropertyVisibility("parallax.showClipping", parallaxSettingVisibility)
if BlendSourceUsesDisplacement(context) then
context:SetMaterialPropertyVisibility("blend.displacementBlendDistance", MaterialPropertyVisibility_Enabled)
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype
index 2b0d09bc5c..ca3e5e1ce4 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype
@@ -601,7 +601,7 @@
"displayName": "Opacity Mode",
"description": "Opacity mode for this texture.",
"type": "Enum",
- "enumValues": [ "Opaque", "Cutout", "Blended" ],
+ "enumValues": [ "Opaque", "Cutout", "Blended", "TintedTransparent" ],
"defaultValue": "Opaque",
"connection": {
"type": "ShaderOption",
@@ -669,12 +669,12 @@
"description": "Center point for scaling and rotation transformations.",
"type": "vector2",
"vectorLabels": [ "U", "V" ],
- "defaultValue": [ 0.0, 0.0 ]
+ "defaultValue": [ 0.5, 0.5 ]
},
{
"id": "tileU",
"displayName": "Tile U",
- "description": "Scales texture coordinates in V.",
+ "description": "Scales texture coordinates in U.",
"type": "float",
"defaultValue": 1.0,
"step": 0.1
@@ -879,13 +879,6 @@
}
],
"parallax": [
- {
- "id": "enable",
- "displayName": "Enable",
- "description": "Whether to enable the parallax feature.",
- "type": "Bool",
- "defaultValue": false
- },
{
"id": "textureMap",
"displayName": "Texture Map",
@@ -896,6 +889,13 @@
"id": "m_depthMap"
}
},
+ {
+ "id": "useTexture",
+ "displayName": "Use Texture",
+ "description": "Whether to use the texture map.",
+ "type": "Bool",
+ "defaultValue": true
+ },
{
"id": "textureMapUv",
"displayName": "UV",
@@ -913,7 +913,7 @@
"displayName": "Heightmap Scale",
"description": "The total height of the heightmap in local model units.",
"type": "Float",
- "defaultValue": 0.0,
+ "defaultValue": 0.05,
"min": 0.0,
"softMax": 0.1,
"connection": {
@@ -951,7 +951,7 @@
"description": "Select the algorithm to use for parallax mapping.",
"type": "Enum",
"enumValues": [ "Basic", "Steep", "POM", "Relief", "ContactRefinement" ],
- "defaultValue": "Basic",
+ "defaultValue": "POM",
"connection": {
"type": "ShaderOption",
"id": "o_parallax_algorithm"
@@ -1139,7 +1139,7 @@
"type": "float",
"defaultValue": 6.0,
"min": 0.0,
- "softMax": 20.0
+ "softMax": 20.0
},
{
"id": "transmissionDistortion",
@@ -1170,7 +1170,7 @@
}
],
"irradiance": [
- // Note: this property group is used in the DiffuseGlobalIllumination pass, it is not read by the StandardPBR shader
+ // Note: this property group is used in the DiffuseGlobalIllumination pass and not by the main forward shader
{
"id": "color",
"displayName": "Color",
@@ -1277,18 +1277,18 @@
"type": "HandleSubsurfaceScatteringParameters",
"args": {
"mode": "subsurfaceScattering.transmissionMode",
- "scale" : "subsurfaceScattering.transmissionScale",
- "power" : "subsurfaceScattering.transmissionPower",
- "distortion" : "subsurfaceScattering.transmissionDistortion",
- "attenuation" : "subsurfaceScattering.transmissionAttenuation",
- "tintColor" : "subsurfaceScattering.transmissionTint",
- "thickness" : "subsurfaceScattering.thickness",
+ "scale": "subsurfaceScattering.transmissionScale",
+ "power": "subsurfaceScattering.transmissionPower",
+ "distortion": "subsurfaceScattering.transmissionDistortion",
+ "attenuation": "subsurfaceScattering.transmissionAttenuation",
+ "tintColor": "subsurfaceScattering.transmissionTint",
+ "thickness": "subsurfaceScattering.thickness",
"enabled": "subsurfaceScattering.enableSubsurfaceScattering",
- "scatterDistanceColor" : "subsurfaceScattering.scatterColor",
- "scatterDistanceIntensity" : "subsurfaceScattering.scatterDistance",
- "scatterDistanceShaderInput" : "m_scatterDistance",
- "parametersShaderInput" : "m_transmissionParams",
- "tintThickenssShaderInput" : "m_transmissionTintThickness"
+ "scatterDistanceColor": "subsurfaceScattering.scatterColor",
+ "scatterDistanceIntensity": "subsurfaceScattering.scatterDistance",
+ "scatterDistanceShaderInput": "m_scatterDistance",
+ "parametersShaderInput": "m_transmissionParams",
+ "tintThickenssShaderInput": "m_transmissionTintThickness"
}
},
{
@@ -1387,15 +1387,6 @@
"file": "StandardPBR_HandleOpacityDoubleSided.lua"
}
},
- {
- "type": "OverrideDrawList",
- "args": {
- "triggerProperty": "opacity.mode",
- "triggerValue": "Blended",
- "shaderIndex": 1,
- "drawList": "transparent"
- }
- },
{
"type": "Lua",
"args": {
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl
index 2667c8123b..10fa3814f3 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl
@@ -294,6 +294,24 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse
lightingOutput.m_diffuseColor.rgb += lightingOutput.m_specularColor.rgb; // add specular
}
+ else if (o_opacity_mode == OpacityMode::TintedTransparent)
+ {
+ // See OpacityMode::Blended above for the basic method. TintedTransparent adds onto the above concept by supporting
+ // colored alpha. This is currently a very basic calculation that uses the baseColor as a multiplier with strength
+ // determined by the alpha. We'll modify this later to be more physically accurate and allow surface depth,
+ // absorption, and interior color to be specified.
+ //
+ // The technique uses dual source blending to allow two separate sources to be part of the blending equation
+ // even though ultimately only a single render target is being written to. m_diffuseColor is render target 0 and
+ // m_specularColor render target 1, and the blend mode is (dest * source1color) + (source * 1.0).
+ //
+ // This means that m_specularColor.rgb (source 1) is multiplied against the destination, then
+ // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0.
+
+ lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse
+ lightingOutput.m_diffuseColor.rgb += lightingOutput.m_specularColor.rgb; // add specular
+ lightingOutput.m_specularColor.rgb = baseColor * (1.0 - lightingOutput.m_diffuseColor.w);
+ }
else
{
// Pack factor and quality, drawback: because of precision limit of float16 cannot represent exact 1, maximum representable value is 0.9961
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua
index 541b1ac1ce..20d3ee47ae 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_HandleOpacityMode.lua
@@ -60,10 +60,13 @@ function Process(context)
if(opacityMode == OpacityMode_Blended) then
ConfigureAlphaBlending(context:GetShader(ForwardPassIndex))
+ context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent")
elseif(opacityMode == OpacityMode_TintedTransparent) then
ConfigureDualSourceBlending(context:GetShader(ForwardPassIndex))
+ context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent")
else
ResetAlphaBlending(context:GetShader(ForwardPassIndex))
+ context:GetShader(ForwardPassIndex):SetDrawListTagOverride("") -- reset to default draw list
end
end
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua
index e6689da327..53d6334f28 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ParallaxState.lua
@@ -13,7 +13,7 @@
----------------------------------------------------------------------------------------------------
function GetMaterialPropertyDependencies()
- return {"parallax.enable", "parallax.textureMap"}
+ return {"parallax.textureMap", "parallax.useTexture"}
end
function GetShaderOptionDependencies()
@@ -21,27 +21,31 @@ function GetShaderOptionDependencies()
end
function Process(context)
- local enable = context:GetMaterialPropertyValue_bool("parallax.enable")
local textureMap = context:GetMaterialPropertyValue_Image("parallax.textureMap")
+ local useTexture = context:GetMaterialPropertyValue_bool("parallax.useTexture")
+ local enable = textureMap ~= nil and useTexture
context:SetShaderOptionValue_bool("o_parallax_feature_enabled", enable)
- context:SetShaderOptionValue_bool("o_useDepthMap", enable and textureMap ~= nil)
+ context:SetShaderOptionValue_bool("o_useDepthMap", enable)
end
function ProcessEditor(context)
- local enable = context:GetMaterialPropertyValue_bool("parallax.enable")
-
- if enable then
- context:SetMaterialPropertyVisibility("parallax.textureMap", MaterialPropertyVisibility_Enabled)
- else
- context:SetMaterialPropertyVisibility("parallax.textureMap", MaterialPropertyVisibility_Hidden)
- end
-
local textureMap = context:GetMaterialPropertyValue_Image("parallax.textureMap")
- local visibility = MaterialPropertyVisibility_Enabled
- if(not enable or textureMap == nil) then
- visibility = MaterialPropertyVisibility_Hidden
+
+ if textureMap ~= nil then
+ context:SetMaterialPropertyVisibility("parallax.useTexture", MaterialPropertyVisibility_Enabled)
+ else
+ context:SetMaterialPropertyVisibility("parallax.useTexture", MaterialPropertyVisibility_Hidden)
end
+ local useTexture = context:GetMaterialPropertyValue_bool("parallax.useTexture")
+
+ local visibility = MaterialPropertyVisibility_Enabled
+ if(textureMap == nil) then
+ visibility = MaterialPropertyVisibility_Hidden
+ elseif not useTexture then
+ visibility = MaterialPropertyVisibility_Disabled
+ end
+
context:SetMaterialPropertyVisibility("parallax.factor", visibility)
context:SetMaterialPropertyVisibility("parallax.offset", visibility)
context:SetMaterialPropertyVisibility("parallax.showClipping", visibility)
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua
index e502eb38f8..b245fde3df 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua
@@ -13,7 +13,7 @@
----------------------------------------------------------------------------------------------------
function GetMaterialPropertyDependencies()
- return {"opacity.mode", "parallax.enable", "parallax.pdo"}
+ return {"opacity.mode", "parallax.textureMap", "parallax.useTexture", "parallax.pdo"}
end
OpacityMode_Opaque = 0
@@ -21,41 +21,61 @@ OpacityMode_Cutout = 1
OpacityMode_Blended = 2
OpacityMode_TintedTransparent = 3
+function TryGetShaderByTag(context, shaderTag)
+ if context:HasShaderWithTag(shaderTag) then
+ return context:GetShaderByTag(shaderTag)
+ else
+ return nil
+ end
+end
+
+function TrySetShaderEnabled(shader, enabled)
+ if shader then
+ shader:SetEnabled(enabled)
+ end
+end
+
function Process(context)
local opacityMode = context:GetMaterialPropertyValue_enum("opacity.mode")
- local parallaxEnabled = context:GetMaterialPropertyValue_bool("parallax.enable")
+ local displacementMap = context:GetMaterialPropertyValue_Image("parallax.textureMap")
+ local useDisplacementMap = context:GetMaterialPropertyValue_bool("parallax.useTexture")
+ local parallaxEnabled = displacementMap ~= nil and useDisplacementMap
local parallaxPdoEnabled = context:GetMaterialPropertyValue_bool("parallax.pdo")
local depthPass = context:GetShaderByTag("DepthPass")
local shadowMap = context:GetShaderByTag("Shadowmap")
local forwardPassEDS = context:GetShaderByTag("ForwardPass_EDS")
- local lowEndForwardEDS = context:GetShaderByTag("LowEndForward_EDS")
local depthPassWithPS = context:GetShaderByTag("DepthPass_WithPS")
local shadowMapWithPS = context:GetShaderByTag("Shadowmap_WithPS")
local forwardPass = context:GetShaderByTag("ForwardPass")
- local lowEndForward = context:GetShaderByTag("LowEndForward")
+
+ -- Use TryGetShaderByTag because these shaders only exist in StandardPBR but this script is also used for EnhancedPBR
+ local lowEndForwardEDS = TryGetShaderByTag(context, "LowEndForward_EDS")
+ local lowEndForward = TryGetShaderByTag(context, "LowEndForward")
if parallaxEnabled and parallaxPdoEnabled then
depthPass:SetEnabled(false)
shadowMap:SetEnabled(false)
forwardPassEDS:SetEnabled(false)
- lowEndForwardEDS:SetEnabled(false)
depthPassWithPS:SetEnabled(true)
shadowMapWithPS:SetEnabled(true)
forwardPass:SetEnabled(true)
- lowEndForward:SetEnabled(true)
+
+ TrySetShaderEnabled(lowEndForwardEDS, false)
+ TrySetShaderEnabled(lowEndForward, true)
else
depthPass:SetEnabled(opacityMode == OpacityMode_Opaque)
shadowMap:SetEnabled(opacityMode == OpacityMode_Opaque)
forwardPassEDS:SetEnabled((opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent))
- lowEndForwardEDS:SetEnabled((opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent))
depthPassWithPS:SetEnabled(opacityMode == OpacityMode_Cutout)
shadowMapWithPS:SetEnabled(opacityMode == OpacityMode_Cutout)
forwardPass:SetEnabled(opacityMode == OpacityMode_Cutout)
- lowEndForward:SetEnabled(opacityMode == OpacityMode_Cutout)
+
+ TrySetShaderEnabled(lowEndForwardEDS, (opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent))
+ TrySetShaderEnabled(lowEndForward, opacityMode == OpacityMode_Cutout)
end
context:GetShaderByTag("DepthPassTransparentMin"):SetEnabled((opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent))
diff --git a/Gems/Atom/Feature/Common/Assets/Passes/LowEndPipeline.pass b/Gems/Atom/Feature/Common/Assets/Passes/LowEndPipeline.pass
index b19569fb9d..38a4524aa2 100644
--- a/Gems/Atom/Feature/Common/Assets/Passes/LowEndPipeline.pass
+++ b/Gems/Atom/Feature/Common/Assets/Passes/LowEndPipeline.pass
@@ -243,6 +243,13 @@
"Attachment": "LightListRemapped"
}
},
+ {
+ "LocalSlot": "InputLinearDepth",
+ "AttachmentRef": {
+ "Pass": "DepthPrePass",
+ "Attachment": "DepthLinear"
+ }
+ },
{
"LocalSlot": "DepthStencil",
"AttachmentRef": {
diff --git a/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass b/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass
index ee943f6d39..af7408b48c 100644
--- a/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass
+++ b/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass
@@ -251,6 +251,13 @@
"Attachment": "LightListRemapped"
}
},
+ {
+ "LocalSlot": "InputLinearDepth",
+ "AttachmentRef": {
+ "Pass": "DepthPrePass",
+ "Attachment": "DepthLinear"
+ }
+ },
{
"LocalSlot": "DepthStencil",
"AttachmentRef": {
diff --git a/Gems/Atom/Feature/Common/Assets/Passes/Transparent.pass b/Gems/Atom/Feature/Common/Assets/Passes/Transparent.pass
index 415aa2fec0..3bb184a1f8 100644
--- a/Gems/Atom/Feature/Common/Assets/Passes/Transparent.pass
+++ b/Gems/Atom/Feature/Common/Assets/Passes/Transparent.pass
@@ -67,6 +67,12 @@
"ShaderInputName": "m_lightListRemapped",
"ScopeAttachmentUsage": "Shader"
},
+ {
+ "Name": "InputLinearDepth",
+ "SlotType": "Input",
+ "ShaderInputName": "m_linearDepthTexture",
+ "ScopeAttachmentUsage": "Shader"
+ },
// Input/Outputs
{
"Name": "DepthStencil",
diff --git a/Gems/Atom/Feature/Common/Assets/Passes/TransparentParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/TransparentParent.pass
index 32517484f3..b278f2bcb4 100644
--- a/Gems/Atom/Feature/Common/Assets/Passes/TransparentParent.pass
+++ b/Gems/Atom/Feature/Common/Assets/Passes/TransparentParent.pass
@@ -32,6 +32,10 @@
"Name": "LightListRemapped",
"SlotType": "Input"
},
+ {
+ "Name": "InputLinearDepth",
+ "SlotType": "Input"
+ },
// Input/Outputs...
{
"Name": "DepthStencil",
@@ -91,6 +95,13 @@
"Attachment": "LightListRemapped"
}
},
+ {
+ "LocalSlot": "InputLinearDepth",
+ "AttachmentRef": {
+ "Pass": "Parent",
+ "Attachment": "InputLinearDepth"
+ }
+ },
// Input/Outputs...
{
"LocalSlot": "DepthStencil",
diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/TransparentPassSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/TransparentPassSrg.azsli
index 14cff21739..d9367f9d03 100644
--- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/TransparentPassSrg.azsli
+++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/TransparentPassSrg.azsli
@@ -35,4 +35,5 @@ ShaderResourceGroup PassSrg : SRG_PerPass
Texture2D m_tileLightData;
StructuredBuffer m_lightListRemapped;
+ Texture2D m_linearDepthTexture;
}
diff --git a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp
index 089a6168b1..16f20d7178 100644
--- a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp
@@ -14,8 +14,6 @@
#include
#include
#include
-#include
-#include
#include
#include
@@ -114,7 +112,6 @@ namespace AZ
ProjectedShadowFeatureProcessor::Reflect(context);
SkyBoxFeatureProcessor::Reflect(context);
UseTextureFunctor::Reflect(context);
- PropertyVisibilityFunctor::Reflect(context);
DrawListFunctor::Reflect(context);
SubsurfaceTransmissionParameterFunctor::Reflect(context);
Transform2DFunctor::Reflect(context);
@@ -126,7 +123,6 @@ namespace AZ
DisplayMapperPassData::Reflect(context);
ConvertEmissiveUnitFunctor::Reflect(context);
LookupTableAsset::Reflect(context);
- ShaderEnableFunctor::Reflect(context);
ReflectionProbeFeatureProcessor::Reflect(context);
DecalTextureArrayFeatureProcessor::Reflect(context);
SMAAFeatureProcessor::Reflect(context);
diff --git a/Gems/Atom/Feature/Common/Code/Source/EditorCommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/EditorCommonSystemComponent.cpp
index 32a29cf4d3..2373d0cb00 100644
--- a/Gems/Atom/Feature/Common/Code/Source/EditorCommonSystemComponent.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/EditorCommonSystemComponent.cpp
@@ -12,11 +12,9 @@
#include
#include
-#include
#include
#include
#include
-#include
#include
#include
@@ -58,11 +56,9 @@ namespace AZ
}
AZ::Render::UseTextureFunctorSourceData::Reflect(context);
- AZ::Render::PropertyVisibilityFunctorSourceData::Reflect(context);
AZ::Render::DrawListFunctorSourceData::Reflect(context);
AZ::Render::Transform2DFunctorSourceData::Reflect(context);
AZ::Render::ConvertEmissiveUnitFunctorSourceData::Reflect(context);
- AZ::Render::ShaderEnableFunctorSourceData::Reflect(context);
AZ::Render::SubsurfaceTransmissionParameterFunctorSourceData::Reflect(context);
AZ::Render::EditorLightingPreset::Reflect(context);
@@ -104,11 +100,9 @@ namespace AZ
}
materialFunctorRegistration->RegisterMaterialFunctor("UseTexture", azrtti_typeid());
- materialFunctorRegistration->RegisterMaterialFunctor("UpdatePropertyVisibility", azrtti_typeid());
materialFunctorRegistration->RegisterMaterialFunctor("OverrideDrawList", azrtti_typeid());
materialFunctorRegistration->RegisterMaterialFunctor("Transform2D", azrtti_typeid());
materialFunctorRegistration->RegisterMaterialFunctor("ConvertEmissiveUnit", azrtti_typeid());
- materialFunctorRegistration->RegisterMaterialFunctor("ShaderEnable", azrtti_typeid());
materialFunctorRegistration->RegisterMaterialFunctor("HandleSubsurfaceScatteringParameters", azrtti_typeid());
materialFunctorRegistration->RegisterMaterialFunctor("Lua", azrtti_typeid());
diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.cpp
deleted file mode 100644
index da8730f1ed..0000000000
--- a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-
-#include "PropertyVisibilityFunctor.h"
-
-namespace AZ
-{
- namespace Render
- {
- void PropertyVisibilityFunctor::Reflect(ReflectContext* context)
- {
- if (auto* serializeContext = azrtti_cast(context))
- {
- serializeContext->Class()
- ->Version(1)
- ->Field("triggerProperty", &Action::m_triggerPropertyIndex)
- ->Field("triggerValue", &Action::m_triggerValue)
- ->Field("visibility", &Action::m_visibility)
- ;
- serializeContext->Class()
- ->Version(1)
- ->Field("actions", &PropertyVisibilityFunctor::m_actions)
- ->Field("affectedProperties", &PropertyVisibilityFunctor::m_affectedProperties)
- ;
- }
- }
-
- void PropertyVisibilityFunctor::Process(EditorContext& context)
- {
- bool visibilityApplied = false;
- RPI::MaterialPropertyVisibility lastAppliedVisibility;
-
- for (const auto& action : m_actions)
- {
- bool willSetVisibility = false;
- if (action.m_triggerValue.Is() || action.m_triggerValue.Is() || action.m_triggerValue.Is())
- {
- willSetVisibility = action.m_triggerValue == context.GetMaterialPropertyValue(action.m_triggerPropertyIndex);
- }
- else if (action.m_triggerValue.Is())
- {
- willSetVisibility = AZ::IsClose(action.m_triggerValue.GetValue(),
- context.GetMaterialPropertyValue(action.m_triggerPropertyIndex),
- std::numeric_limits::epsilon());
- }
- else // for types Vector2, Vector3, Vector4, Color, Image
- {
- AZ_Error("PropertyVisibilityFunctor", false, "Unsupported property data type as an enable property.");
- }
-
- if (willSetVisibility)
- {
- visibilityApplied = true;
- lastAppliedVisibility = action.m_visibility;
- }
- }
-
- if (visibilityApplied)
- {
- for (const auto& propertyIndex : m_affectedProperties)
- {
- context.SetMaterialPropertyVisibility(propertyIndex, lastAppliedVisibility);
- }
- }
- }
-
- } // namespace Render
-} // namespace AZ
diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.h b/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.h
deleted file mode 100644
index d1a7772fc8..0000000000
--- a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctor.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-
-#pragma once
-
-#include
-#include
-
-namespace AZ
-{
- namespace Render
- {
- //! Materials can use this functor to control when and how to set the visibility of a group of properties.
- class PropertyVisibilityFunctor final
- : public RPI::MaterialFunctor
- {
- friend class PropertyVisibilityFunctorSourceData;
- public:
- AZ_RTTI(AZ::Render::PropertyVisibilityFunctor, "{2582B36F-FA7C-450F-B46A-39AAE18356A0}", RPI::MaterialFunctor);
-
- static void Reflect(ReflectContext* context);
-
- void Process(EditorContext& context) override;
-
- private:
- struct Action
- {
- AZ_TYPE_INFO(AZ::Render::PropertyVisibilityFunctor::Action, "{5DF4D981-9D0C-4040-A6C5-52E1D0BD876B}");
-
- RPI::MaterialPropertyIndex m_triggerPropertyIndex; //! The control property for affected properties.
- RPI::MaterialPropertyValue m_triggerValue; //! The trigger value of the control property.
- RPI::MaterialPropertyVisibility m_visibility; //! The visibility of affected properties when the trigger value is hit.
- };
- // Material property inputs...
- AZStd::vector m_actions; //! The actions that describes when and what to do with visibilities.
- AZStd::vector m_affectedProperties; //! The properties that are affected by actions.
- };
-
- } // namespace Render
-} // namespace AZ
diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.cpp
deleted file mode 100644
index 3baf27de60..0000000000
--- a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-
-#include "PropertyVisibilityFunctorSourceData.h"
-#include
-#include
-
-#include
-
-namespace AZ
-{
- namespace Render
- {
- void PropertyVisibilityFunctorSourceData::Reflect(ReflectContext* context)
- {
- if (auto* serializeContext = azrtti_cast(context))
- {
- serializeContext->Class()
- ->Version(1)
- ->Field("triggerProperty", &ActionSourceData::m_triggerPropertyName)
- ->Field("triggerValue", &ActionSourceData::m_triggerValue)
- ->Field("visibility", &ActionSourceData::m_visibility)
- ;
- serializeContext->Class()
- ->Version(2)
- ->Field("actions", &PropertyVisibilityFunctorSourceData::m_actions)
- ->Field("affectedProperties", &PropertyVisibilityFunctorSourceData::m_affectedPropertyNames)
- ;
- }
- }
-
- RPI::MaterialFunctorSourceData::FunctorResult PropertyVisibilityFunctorSourceData::CreateFunctor(const EditorContext& context) const
- {
- using namespace RPI;
-
- RPI::Ptr functor = aznew PropertyVisibilityFunctor;
-
- functor->m_actions.reserve(m_actions.size());
-
- for (const auto& actionSource : m_actions)
- {
- functor->m_actions.emplace_back();
- PropertyVisibilityFunctor::Action& action = functor->m_actions.back();
- action.m_triggerPropertyIndex = context.FindMaterialPropertyIndex(AZ::Name{ actionSource.m_triggerPropertyName });
- if (action.m_triggerPropertyIndex.IsNull())
- {
- return Failure();
- }
- AddMaterialPropertyDependency(functor, action.m_triggerPropertyIndex);
-
- if (!actionSource.m_triggerValue.Resolve(*context.GetMaterialPropertiesLayout(), Name{ actionSource.m_triggerPropertyName }))
- {
- // Error is reported in Resolve().
- return Failure();
- }
-
- const MaterialPropertyDescriptor* propertyDescriptor = context.GetMaterialPropertiesLayout()->GetPropertyDescriptor(action.m_triggerPropertyIndex);
- // Enum type should resolve further to a unit32_t from the string source.
- if (propertyDescriptor->GetDataType() == RPI::MaterialPropertyDataType::Enum)
- {
- if (!RPI::MaterialUtils::ResolveMaterialPropertyEnumValue(
- propertyDescriptor,
- Name(actionSource.m_triggerValue.GetValue().GetValue()),
- action.m_triggerValue))
- {
- return Failure();
- }
- }
- else
- {
- action.m_triggerValue = actionSource.m_triggerValue.GetValue();
- }
-
- action.m_visibility = actionSource.m_visibility;
- }
-
- functor->m_affectedProperties.reserve(m_affectedPropertyNames.size());
- for (const AZStd::string& name : m_affectedPropertyNames)
- {
- RPI::MaterialPropertyIndex index = context.FindMaterialPropertyIndex(AZ::Name{ name });
- if (index.IsNull())
- {
- return Failure();
- }
- functor->m_affectedProperties.push_back(index);
- }
-
- return Success(RPI::Ptr(functor));
- }
- } // namespace Render
-} // namespace AZ
diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.h b/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.h
deleted file mode 100644
index 6b212f78a0..0000000000
--- a/Gems/Atom/Feature/Common/Code/Source/Material/PropertyVisibilityFunctorSourceData.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-
-#pragma once
-
-#include "PropertyVisibilityFunctor.h"
-#include
-#include
-
-namespace AZ
-{
- namespace Render
- {
- //! Builds a PropertyVisibilityFunctor.
- //! Materials can use this functor to control whether a specific property group will be enabled.
- class PropertyVisibilityFunctorSourceData final
- : public RPI::MaterialFunctorSourceData
- {
- public:
- AZ_RTTI(AZ::Render::PropertyVisibilityFunctorSourceData, "{B44E6929-8FFF-405F-9056-B9B811F97676}", RPI::MaterialFunctorSourceData);
-
- static void Reflect(ReflectContext* context);
-
- FunctorResult CreateFunctor(const EditorContext& context) const override;
- private:
- struct ActionSourceData
- {
- AZ_TYPE_INFO(AZ::Render::PropertyVisibilityFunctorSourceData::ActionSourceData, "{70E01DA6-0B42-4CCB-AAD0-51980DB43F62}");
- AZStd::string m_triggerPropertyName; //! The control property for affected properties.
- RPI::MaterialPropertyValueSourceData m_triggerValue; //! The trigger value of the control property.
- RPI::MaterialPropertyVisibility m_visibility; //! The visibility of affected properties when the trigger value is hit.
- };
- // Material property inputs...
- AZStd::vector m_actions; //! The actions that describes when and what to do with visibilities.
- AZStd::vector m_affectedPropertyNames; //! The properties that are affected by actions.
- };
-
- } // namespace Render
-} // namespace AZ
diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.cpp
deleted file mode 100644
index dd602cc4ba..0000000000
--- a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-
-#include "./ShaderEnableFunctor.h"
-#include
-#include
-#include
-
-namespace AZ
-{
- namespace Render
- {
- void ShaderEnableFunctor::Reflect(ReflectContext* context)
- {
- if (auto* serializeContext = azrtti_cast(context))
- {
- serializeContext->Class()
- ->Version(4)
- ->Field("opacityModeIndex", &ShaderEnableFunctor::m_opacityModeIndex)
- ->Field("parallaxEnableIndex", &ShaderEnableFunctor::m_parallaxEnableIndex)
- ->Field("parallaxPdoEnableIndex", &ShaderEnableFunctor::m_parallaxPdoEnableIndex)
- ->Field("shadowShaderNoPSIndex", &ShaderEnableFunctor::m_shadowShaderNoPSIndex)
- ->Field("shadowShaderWithPSIndex", &ShaderEnableFunctor::m_shadowShaderWithPSIndex)
- ->Field("depthShaderNoPSIndex", &ShaderEnableFunctor::m_depthShaderNoPSIndex)
- ->Field("depthShaderWithPSIndex", &ShaderEnableFunctor::m_depthShaderWithPSIndex)
- ->Field("pbrShaderNoEdsIndex", &ShaderEnableFunctor::m_pbrShaderNoEdsIndex)
- ->Field("pbrShaderWithEdsIndex", &ShaderEnableFunctor::m_pbrShaderWithEdsIndex)
- ->Field("depthShaderTransparentMin", &ShaderEnableFunctor::m_depthShaderTransparentMin)
- ->Field("depthShaderTransparentMax", &ShaderEnableFunctor::m_depthShaderTransparentMax)
- ;
- }
- }
-
- void ShaderEnableFunctor::Process(RuntimeContext& context)
- {
- unsigned int opacityMode = context.GetMaterialPropertyValue(m_opacityModeIndex);
- bool parallaxEnabled = context.GetMaterialPropertyValue(m_parallaxEnableIndex);
- bool parallaxPdoEnabled = context.GetMaterialPropertyValue(m_parallaxPdoEnableIndex);
-
- if (parallaxEnabled && parallaxPdoEnabled)
- {
- context.SetShaderEnabled(m_depthShaderNoPSIndex, false);
- context.SetShaderEnabled(m_shadowShaderNoPSIndex, false);
- context.SetShaderEnabled(m_pbrShaderWithEdsIndex, false);
-
- context.SetShaderEnabled(m_depthShaderWithPSIndex, true);
- context.SetShaderEnabled(m_shadowShaderWithPSIndex, true);
- context.SetShaderEnabled(m_pbrShaderNoEdsIndex, true);
- }
- else
- {
- context.SetShaderEnabled(m_depthShaderNoPSIndex, opacityMode == OpacityMode::Opaque );
- context.SetShaderEnabled(m_shadowShaderNoPSIndex, opacityMode == OpacityMode::Opaque);
- context.SetShaderEnabled(m_pbrShaderWithEdsIndex, opacityMode == OpacityMode::Opaque || opacityMode == OpacityMode::Blended || opacityMode == OpacityMode::TintedTransparent);
-
- context.SetShaderEnabled(m_depthShaderWithPSIndex, opacityMode == OpacityMode::Cutout);
- context.SetShaderEnabled(m_shadowShaderWithPSIndex, opacityMode == OpacityMode::Cutout);
- context.SetShaderEnabled(m_pbrShaderNoEdsIndex, opacityMode == OpacityMode::Cutout);
- }
-
- context.SetShaderEnabled(m_depthShaderTransparentMin, opacityMode == OpacityMode::Blended || opacityMode == OpacityMode::TintedTransparent);
- context.SetShaderEnabled(m_depthShaderTransparentMax, opacityMode == OpacityMode::Blended || opacityMode == OpacityMode::TintedTransparent);
- }
- }
-}
diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.h b/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.h
deleted file mode 100644
index ac5f31ba30..0000000000
--- a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctor.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-
-#pragma once
-
-#include
-#include
-#include
-
-namespace AZ
-{
- namespace Render
- {
- enum OpacityMode
- {
- Opaque = 0,
- Cutout,
- Blended,
- TintedTransparent,
- };
-
- //! Select shadow and depth shader based on opacity mode and parallax state
- //! Opaque: Enable shader without PS
- //! Cutout or Parallax enable: Enable shader with PS
- //! Blended: Disable both
- //! TintedTransparent: Disable both
- class ShaderEnableFunctor final
- : public RPI::MaterialFunctor
- {
- friend class ShaderEnableFunctorSourceData;
- public:
- AZ_RTTI(ShaderEnableFunctor, "{2079A693-FE4F-46A7-95C0-09D88AC156D0}", RPI::MaterialFunctor);
-
- static void Reflect(ReflectContext* context);
-
- void Process(RuntimeContext& context) override;
-
- private:
- RPI::MaterialPropertyIndex m_opacityModeIndex;
- RPI::MaterialPropertyIndex m_parallaxEnableIndex;
- RPI::MaterialPropertyIndex m_parallaxPdoEnableIndex;
-
- uint32_t m_shadowShaderNoPSIndex = -1;
- uint32_t m_shadowShaderWithPSIndex = -1;
- uint32_t m_depthShaderNoPSIndex = -1;
- uint32_t m_depthShaderWithPSIndex = -1;
- uint32_t m_pbrShaderWithEdsIndex = -1;
- uint32_t m_pbrShaderNoEdsIndex = -1;
- // The following are used by the light culling system to produce min/max depth bounds
- uint32_t m_depthShaderTransparentMin = -1;
- uint32_t m_depthShaderTransparentMax = -1;
- };
- }
-}
diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.cpp b/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.cpp
deleted file mode 100644
index 3c16666f82..0000000000
--- a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-
-#include "./ShaderEnableFunctorSourceData.h"
-#include
-#include
-
-namespace AZ
-{
- namespace Render
- {
- void ShaderEnableFunctorSourceData::Reflect(ReflectContext* context)
- {
- if (auto* serializeContext = azrtti_cast(context))
- {
- serializeContext->Class()
- ->Version(5)
- ->Field("opacityMode", &ShaderEnableFunctorSourceData::m_opacityMode)
- ->Field("parallaxEnable", &ShaderEnableFunctorSourceData::m_parallaxEnable)
- ->Field("parallaxPdoEnable", &ShaderEnableFunctorSourceData::m_parallaxPdoEnable)
- ->Field("shadowShaderNoPSIndex", &ShaderEnableFunctorSourceData::m_shadowShaderNoPSIndex)
- ->Field("shadowShaderWithPSIndex", &ShaderEnableFunctorSourceData::m_shadowShaderWithPSIndex)
- ->Field("depthShaderNoPSIndex", &ShaderEnableFunctorSourceData::m_depthShaderNoPSIndex)
- ->Field("depthShaderWithPSIndex", &ShaderEnableFunctorSourceData::m_depthShaderWithPSIndex)
- ->Field("pbrShaderNoEdsIndex", &ShaderEnableFunctorSourceData::m_pbrShaderNoEdsIndex)
- ->Field("pbrShaderWithEdsIndex", &ShaderEnableFunctorSourceData::m_pbrShaderWithEdsIndex)
- ->Field("depthShaderTransparentMin", &ShaderEnableFunctorSourceData::m_depthShaderTransparentMin)
- ->Field("depthShaderTransparentMax", &ShaderEnableFunctorSourceData::m_depthShaderTransparentMax)
- ;
- }
- }
-
- RPI::MaterialFunctorSourceData::FunctorResult ShaderEnableFunctorSourceData::CreateFunctor(const RuntimeContext& context) const
- {
- RPI::Ptr functor = aznew ShaderEnableFunctor;
-
- functor->m_opacityModeIndex = context.FindMaterialPropertyIndex(Name{ m_opacityMode });
- if (functor->m_opacityModeIndex.IsNull())
- {
- return Failure();
- }
- AddMaterialPropertyDependency(functor, functor->m_opacityModeIndex);
-
- functor->m_parallaxEnableIndex = context.FindMaterialPropertyIndex(Name{ m_parallaxEnable });
- if (functor->m_parallaxEnableIndex.IsNull())
- {
- return Failure();
- }
- AddMaterialPropertyDependency(functor, functor->m_parallaxEnableIndex);
-
- functor->m_parallaxPdoEnableIndex = context.FindMaterialPropertyIndex(Name{ m_parallaxPdoEnable });
- if (functor->m_parallaxPdoEnableIndex.IsNull())
- {
- return Failure();
- }
- AddMaterialPropertyDependency(functor, functor->m_parallaxPdoEnableIndex);
-
- if (!context.CheckShaderIndexValid(m_shadowShaderWithPSIndex))
- {
- return Failure();
- }
- functor->m_shadowShaderWithPSIndex = m_shadowShaderWithPSIndex;
-
- if (!context.CheckShaderIndexValid(m_shadowShaderNoPSIndex))
- {
- return Failure();
- }
- functor->m_shadowShaderNoPSIndex = m_shadowShaderNoPSIndex;
-
- if (!context.CheckShaderIndexValid(m_depthShaderWithPSIndex))
- {
- return Failure();
- }
- functor->m_depthShaderWithPSIndex = m_depthShaderWithPSIndex;
-
- if (!context.CheckShaderIndexValid(m_depthShaderNoPSIndex))
- {
- return Failure();
- }
- functor->m_depthShaderNoPSIndex = m_depthShaderNoPSIndex;
-
- if (!context.CheckShaderIndexValid(m_pbrShaderNoEdsIndex))
- {
- return Failure();
- }
- functor->m_pbrShaderNoEdsIndex = m_pbrShaderNoEdsIndex;
-
- if (!context.CheckShaderIndexValid(m_pbrShaderWithEdsIndex))
- {
- return Failure();
- }
- functor->m_pbrShaderWithEdsIndex = m_pbrShaderWithEdsIndex;
- if (!context.CheckShaderIndexValid(m_depthShaderTransparentMin))
- {
- return Failure();
- }
- functor->m_depthShaderTransparentMin = m_depthShaderTransparentMin;
- if (!context.CheckShaderIndexValid(m_depthShaderTransparentMax))
- {
- return Failure();
- }
- functor->m_depthShaderTransparentMax = m_depthShaderTransparentMax;
-
- return Success(RPI::Ptr(functor));
- }
- }
-}
diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.h b/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.h
deleted file mode 100644
index 2d00a4a015..0000000000
--- a/Gems/Atom/Feature/Common/Code/Source/Material/ShaderEnableFunctorSourceData.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-
-#pragma once
-
-#include "./ShaderEnableFunctor.h"
-#include
-
-namespace AZ
-{
- namespace Render
- {
- class ShaderEnableFunctor;
-
- //! Builds a ShaderEnableFunctor
- class ShaderEnableFunctorSourceData final
- : public RPI::MaterialFunctorSourceData
- {
- public:
- AZ_RTTI(ShaderEnableFunctorSourceData, "{63775ECB-5C3E-44D3-B175-4537BF76C3A7}", RPI::MaterialFunctorSourceData);
-
- static void Reflect(ReflectContext* context);
-
- FunctorResult CreateFunctor(const RuntimeContext& context) const override;
-
- private:
-
- AZStd::string m_opacityMode;
- AZStd::string m_parallaxEnable;
- AZStd::string m_parallaxPdoEnable;
-
- uint32_t m_shadowShaderNoPSIndex = -1;
- uint32_t m_shadowShaderWithPSIndex = -1;
- uint32_t m_depthShaderNoPSIndex = -1;
- uint32_t m_depthShaderWithPSIndex = -1;
- uint32_t m_pbrShaderWithEdsIndex = -1;
- uint32_t m_pbrShaderNoEdsIndex = -1;
- // The following are used by the light culling system to produce min/max depth bounds
- uint32_t m_depthShaderTransparentMin = -1;
- uint32_t m_depthShaderTransparentMax = -1;
- };
- }
-}
diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_editor_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_editor_files.cmake
index 3a749a4b67..4e7cc9dab3 100644
--- a/Gems/Atom/Feature/Common/Code/atom_feature_common_editor_files.cmake
+++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_editor_files.cmake
@@ -24,16 +24,12 @@ set(FILES
Source/Material/ConvertEmissiveUnitFunctorSourceData.h
Source/Material/MaterialConverterSystemComponent.cpp
Source/Material/MaterialConverterSystemComponent.h
- Source/Material/ShaderEnableFunctorSourceData.cpp
- Source/Material/ShaderEnableFunctorSourceData.h
Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.cpp
Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.h
Source/Material/Transform2DFunctorSourceData.cpp
Source/Material/Transform2DFunctorSourceData.h
Source/Material/UseTextureFunctorSourceData.cpp
Source/Material/UseTextureFunctorSourceData.h
- Source/Material/PropertyVisibilityFunctorSourceData.cpp
- Source/Material/PropertyVisibilityFunctorSourceData.h
Source/Material/DrawListFunctorSourceData.cpp
Source/Material/DrawListFunctorSourceData.h
)
diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake
index 46a4e06ac2..4f98046adb 100644
--- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake
+++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake
@@ -155,16 +155,12 @@ set(FILES
Source/LookupTable/LookupTableAsset.cpp
Source/Material/ConvertEmissiveUnitFunctor.cpp
Source/Material/ConvertEmissiveUnitFunctor.h
- Source/Material/ShaderEnableFunctor.cpp
- Source/Material/ShaderEnableFunctor.h
Source/Material/SubsurfaceTransmissionParameterFunctor.cpp
Source/Material/SubsurfaceTransmissionParameterFunctor.h
Source/Material/Transform2DFunctor.cpp
Source/Material/Transform2DFunctor.h
Source/Material/UseTextureFunctor.cpp
Source/Material/UseTextureFunctor.h
- Source/Material/PropertyVisibilityFunctor.cpp
- Source/Material/PropertyVisibilityFunctor.h
Source/Material/DrawListFunctor.cpp
Source/Material/DrawListFunctor.h
Source/Math/GaussianMathFilter.h
diff --git a/Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp b/Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp
index 3a04bf6b88..09cd1c125e 100644
--- a/Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp
+++ b/Gems/Atom/RHI/Code/Source/RHI.Edit/ShaderCompilerArguments.cpp
@@ -164,7 +164,7 @@ namespace AZ
arguments += " -Zi"; // Generate debug information
arguments += " -Zss"; // Compute Shader Hash considering source information
}
- arguments += m_dxcAdditionalFreeArguments;
+ arguments += " " + m_dxcAdditionalFreeArguments;
return arguments;
}
}
diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp
index cdacd2578f..791fa006b0 100644
--- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp
+++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/NullDescriptorManager.cpp
@@ -180,6 +180,7 @@ namespace AZ
for (uint32_t imageIndex = static_cast(NullDescriptorManager::ImageTypes::General2D); imageIndex < static_cast(NullDescriptorManager::ImageTypes::Count); imageIndex++)
{
// different options for the images
+ imageCreateInfo.imageType = (imageIndex >= static_cast(NullDescriptorManager::ImageTypes::General3D)) ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D;
imageCreateInfo.extent = { m_imageNullDescriptor.m_images[imageIndex].m_dimension, m_imageNullDescriptor.m_images[imageIndex].m_dimension, 1 };
imageCreateInfo.samples = m_imageNullDescriptor.m_images[imageIndex].m_sampleCountFlag;
imageCreateInfo.format = m_imageNullDescriptor.m_images[imageIndex].m_format;
diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h
index 396ba14810..f372f40981 100644
--- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h
+++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h
@@ -288,6 +288,7 @@ namespace AZ
AZStd::size_t GetShaderCount() const;
LuaMaterialFunctorShaderItem GetShader(AZStd::size_t index);
LuaMaterialFunctorShaderItem GetShaderByTag(const char* shaderTag);
+ bool HasShaderWithTag(const char* shaderTag);
private:
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/Query.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/Query.cpp
index 227e096594..1d6e8cdc65 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/Query.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/Query.cpp
@@ -96,12 +96,6 @@ namespace AZ
return QueryResultCode::Fail;
}
- // Limit calling BeginQuery() to the first CommandList in the array.
- if (context.GetCommandListIndex() != 0)
- {
- return QueryResultCode::Success;
- }
-
const auto rhiQueryIndices = GetRhiQueryIndicesFromCurrentFrame();
if (!rhiQueryIndices)
{
@@ -124,12 +118,6 @@ namespace AZ
return QueryResultCode::Fail;
}
- // Limit calling EndQuery() to the last CommandList in the array.
- if (context.GetCommandListIndex() != context.GetCommandListCount() - 1)
- {
- return QueryResultCode::Success;
- }
-
// Validate that the queries are recorded for the same scope.
if (m_cachedScopeId != context.GetScopeId())
{
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp
index 9c6a95e582..3a2a556429 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp
@@ -522,8 +522,11 @@ namespace AZ
}
};
- ExecuteOnTimestampQuery(beginQuery);
- ExecuteOnPipelineStatisticsQuery(beginQuery);
+ if (context.GetCommandListIndex() == 0)
+ {
+ ExecuteOnTimestampQuery(beginQuery);
+ ExecuteOnPipelineStatisticsQuery(beginQuery);
+ }
}
void RenderPass::EndScopeQuery(const RHI::FrameGraphExecuteContext& context)
@@ -533,8 +536,23 @@ namespace AZ
query->EndQuery(context);
};
- ExecuteOnTimestampQuery(endQuery);
- ExecuteOnPipelineStatisticsQuery(endQuery);
+ // This scopy query implmentation should be replaced by
+ // [ATOM-5407] [RHI][Core] - Add GPU timestamp and pipeline statistic support for scopes
+
+ // For timestamp query, it's okay to execute across different command lists
+ if (context.GetCommandListIndex() == context.GetCommandListCount() - 1)
+ {
+ ExecuteOnTimestampQuery(endQuery);
+ }
+ // For all the other types of queries except timestamp, the query start and end has to be in the same command list
+ // Here only tracks the PipelineStatistics for the first command list due to that we don't know how many queries are
+ // needed when AddScopeQueryToFrameGraph is called.
+ // This implementation leads to an issue that we may not get accurate pipeline statistic data
+ // for passes which were executed with more than one command list
+ if (context.GetCommandListIndex() == 0)
+ {
+ ExecuteOnPipelineStatisticsQuery(endQuery);
+ }
}
void RenderPass::ReadbackScopeQueryResults()
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp
index 6579e6a98d..3fc2bbd197 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderVariantAsyncLoader.cpp
@@ -150,10 +150,7 @@ namespace AZ
}
}
- if (!shaderVariantTreePendingRequests.empty() || !shaderVariantPendingRequests.empty())
- {
- AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(1000));
- }
+ AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(1000));
}
}
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp
index 7db5f12560..d6421e1337 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp
@@ -296,6 +296,7 @@ namespace AZ
->Method("GetShaderCount", &LuaMaterialFunctorRuntimeContext::GetShaderCount)
->Method("GetShader", &LuaMaterialFunctorRuntimeContext::GetShader)
->Method("GetShaderByTag", &LuaMaterialFunctorRuntimeContext::GetShaderByTag)
+ ->Method("HasShaderWithTag", &LuaMaterialFunctorRuntimeContext::HasShaderWithTag)
;
}
@@ -424,6 +425,11 @@ namespace AZ
return LuaMaterialFunctorShaderItem{nullptr};
}
}
+
+ bool LuaMaterialFunctorRuntimeContext::HasShaderWithTag(const char* shaderTag)
+ {
+ return m_runtimeContextImpl->m_shaderCollection->HasShaderTag(AZ::Name{shaderTag});
+ }
void LuaMaterialFunctorEditorContext::LuaMaterialFunctorEditorContext::Reflect(BehaviorContext* behaviorContext)
{
diff --git a/Gems/Atom/RPI/Code/Tests/System/GpuQueryTests.cpp b/Gems/Atom/RPI/Code/Tests/System/GpuQueryTests.cpp
index e55ec8012b..98ff6befdd 100644
--- a/Gems/Atom/RPI/Code/Tests/System/GpuQueryTests.cpp
+++ b/Gems/Atom/RPI/Code/Tests/System/GpuQueryTests.cpp
@@ -159,7 +159,9 @@ namespace UnitTest
const uint32_t ResultSize = sizeof(uint64_t);
uint64_t mockData;
- const RHI::FrameGraphExecuteContext::Descriptor desc = {};
+ RHI::FrameGraphExecuteContext::Descriptor desc = {};
+ uint64_t dummyCommandList;
+ desc.m_commandList = reinterpret_cast(&dummyCommandList);
RHI::FrameGraphExecuteContext context(desc);
RHI::Scope scope;
@@ -209,7 +211,9 @@ namespace UnitTest
const uint32_t ResultSize = sizeof(uint64_t) * 4u;
uint64_t mockData;
- const RHI::FrameGraphExecuteContext::Descriptor desc = {};
+ RHI::FrameGraphExecuteContext::Descriptor desc = {};
+ uint64_t dummyCommandList;
+ desc.m_commandList = reinterpret_cast(&dummyCommandList);
RHI::FrameGraphExecuteContext context(desc);
RHI::Scope scope;
@@ -273,7 +277,9 @@ namespace UnitTest
const uint32_t ResultSize = sizeof(uint64_t) * 2u;
uint64_t mockData;
- const RHI::FrameGraphExecuteContext::Descriptor desc = {};
+ RHI::FrameGraphExecuteContext::Descriptor desc = {};
+ uint64_t dummyCommandList;
+ desc.m_commandList = reinterpret_cast(&dummyCommandList);
RHI::FrameGraphExecuteContext context(desc);
RHI::Scope scope;
diff --git a/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material b/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material
index 4c3a925e52..c9276216eb 100644
--- a/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material
+++ b/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material
@@ -17,7 +17,6 @@
"textureMap": "TestData/Textures/cc0/Rock030_2K_Normal.jpg"
},
"parallax": {
- "enable": true,
"algorithm": "POM",
"factor": 0.03,
"quality": "High",
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material
index 17353a0603..415bd36dcf 100644
--- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material
+++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material
@@ -86,6 +86,10 @@
"textureMap": "TestData/Textures/cc0/Lava004_1K_Roughness.jpg"
},
"layer2_uv": {
+ "center": [
+ 0.0,
+ 0.0
+ ],
"offsetU": 0.5,
"offsetV": 0.25
},
@@ -128,11 +132,15 @@
"factor": 0.47474750876426699
},
"layer3_uv": {
+ "center": [
+ 0.0,
+ 0.0
+ ],
"offsetU": 0.11999999731779099,
"rotateDegrees": -57.599998474121097
},
"parallax": {
- "enable": true
+ "quality": "Medium"
},
"uv": {
"center": [
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material
index 8cddab24bc..64adf317a9 100644
--- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material
+++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material
@@ -48,8 +48,8 @@
"textureMap": "TestData/Textures/cc0/Concrete019_1K_Color.jpg"
},
"parallax": {
- "enable": true,
- "pdo": true
+ "pdo": true,
+ "quality": "Medium"
}
}
}
\ No newline at end of file
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material
index 3201fa3864..ea3ea8b519 100644
--- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material
+++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/004_UseVertexColors.material
@@ -6,6 +6,9 @@
"properties": {
"blend": {
"blendSource": "BlendMaskVertexColors"
+ },
+ "parallax": {
+ "quality": "Medium"
}
}
-}
+}
\ No newline at end of file
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material
index 55a4774d49..9163fe0a0c 100644
--- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material
+++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/005_UseDisplacement.material
@@ -46,8 +46,8 @@
},
"layer2_uv": {
"center": [
- 0.5,
- 0.5
+ 0.0,
+ 0.0
],
"offsetU": 0.1599999964237213,
"offsetV": 0.07999999821186066,
@@ -67,13 +67,15 @@
"textureMap": "TestData/Textures/cc0/Rocks002_1K_Roughness.jpg"
},
"layer3_uv": {
+ "center": [
+ 0.0,
+ 0.0
+ ],
"scale": 3.4999988079071047
},
"parallax": {
"algorithm": "Relief",
- "enable": true,
- "pdo": true,
- "quality": "Low"
+ "pdo": true
}
}
}
\ No newline at end of file
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_TintedTransparent.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_TintedTransparent.material
new file mode 100644
index 0000000000..1716792af1
--- /dev/null
+++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_TintedTransparent.material
@@ -0,0 +1,23 @@
+{
+ "description": "",
+ "materialType": "Materials/Types/StandardPBR.materialtype",
+ "parentMaterial": "",
+ "propertyLayoutVersion": 3,
+ "properties": {
+ "baseColor": {
+ "color": [
+ 0.5906767249107361,
+ 1.0,
+ 0.11703670024871826,
+ 1.0
+ ],
+ "textureMap": "Textures/Default/default_basecolor.tif"
+ },
+ "opacity": {
+ "alphaSource": "Split",
+ "factor": 0.75,
+ "mode": "TintedTransparent",
+ "textureMap": "TestData/Textures/checker8x8_gray_512.png"
+ }
+ }
+}
\ No newline at end of file
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM.material
index a94d90d04d..ed070d5de2 100644
--- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM.material
+++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM.material
@@ -8,7 +8,6 @@
},
"parallax": {
"algorithm": "POM",
- "enable": true,
"factor": 0.02500000037252903,
"quality": "High",
"textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_disp.png"
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material
index fb862dc5d3..f5ec0e8287 100644
--- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material
+++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/012_Parallax_POM_Cutout.material
@@ -13,13 +13,15 @@
"textureMap": "TestData/Textures/checker8x8_512.png"
},
"parallax": {
- "algorithm": "POM",
- "enable": true,
"factor": 0.10000000149011612,
"quality": "High",
"textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_disp.png"
},
"uv": {
+ "center": [
+ 0.0,
+ 0.0
+ ],
"scale": 0.5
}
}
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission.material
index dbaf6cb587..38adbc70cd 100644
--- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission.material
+++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/015_SubsurfaceScattering_Transmission.material
@@ -6,7 +6,6 @@
"properties": {
"subsurfaceScattering": {
"enableSubsurfaceScattering": true,
- "enableTransmission": true,
"scatterDistance": 64.6464614868164,
"subsurfaceScatterFactor": 1.0,
"thicknessMap": "TestData/Textures/checker8x8_512.png",
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_A.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_A.material
index 7bf12e5358..b3e69212db 100644
--- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_A.material
+++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_A.material
@@ -13,7 +13,6 @@
},
"parallax": {
"algorithm": "POM",
- "enable": true,
"factor": 0.10000000149011612,
"quality": "High",
"textureMap": "TestData/Objects/cube/cube_diff.tif"
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_B.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_B.material
index 4b9f233a85..3d52f3b9e6 100644
--- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_B.material
+++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_Parallax_B.material
@@ -13,7 +13,6 @@
},
"parallax": {
"algorithm": "POM",
- "enable": true,
"factor": 0.05000000074505806,
"quality": "High",
"textureMap": "TestData/Objects/cube/cube_diff.tif"
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/101_DetailMaps_LucyBaseNoDetailMaps.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/101_DetailMaps_LucyBaseNoDetailMaps.material
index 7b1f0ba6a9..6d77be5a49 100644
--- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/101_DetailMaps_LucyBaseNoDetailMaps.material
+++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/101_DetailMaps_LucyBaseNoDetailMaps.material
@@ -8,18 +8,24 @@
"textureMap": "Objects/Lucy/Lucy_bronze_BaseColor.png",
"textureMapUv": "Unwrapped"
},
+ "detailUV": {
+ "center": [
+ 0.0,
+ 0.0
+ ]
+ },
"metallic": {
- "textureMap": "Objects/Lucy/Lucy_bronze_metallic.png",
+ "textureMap": "Objects/Lucy/Lucy_bronze_Metallic.png",
"textureMapUv": "Unwrapped"
},
"normal": {
"flipY": true,
- "textureMap": "Objects/Lucy/Lucy_normal.png",
+ "textureMap": "Objects/Lucy/Lucy_Normal.png",
"textureMapUv": "Unwrapped"
},
"roughness": {
- "textureMap": "Objects/Lucy/Lucy_bronze_roughness.png",
+ "textureMap": "Objects/Lucy/Lucy_bronze_Roughness.png",
"textureMapUv": "Unwrapped"
}
}
-}
+}
\ No newline at end of file
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/102_DetailMaps_All.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/102_DetailMaps_All.material
index 55a01866b5..1a29f392c8 100644
--- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/102_DetailMaps_All.material
+++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/102_DetailMaps_All.material
@@ -5,7 +5,7 @@
"propertyLayoutVersion": 3,
"properties": {
"baseColor": {
- "textureMap": "Objects/Lucy/Lucy_bronze_baseColor.png",
+ "textureMap": "Objects/Lucy/Lucy_bronze_BaseColor.png",
"textureMapUv": "Unwrapped"
},
"detailLayerGroup": {
@@ -19,20 +19,24 @@
"normalDetailStrength": 1.5
},
"detailUV": {
+ "center": [
+ 0.0,
+ 0.0
+ ],
"scale": 10.0
},
"metallic": {
- "textureMap": "Objects/Lucy/Lucy_bronze_metallic.png",
+ "textureMap": "Objects/Lucy/Lucy_bronze_Metallic.png",
"textureMapUv": "Unwrapped"
},
"normal": {
"flipY": true,
- "textureMap": "Objects/Lucy/Lucy_normal.png",
+ "textureMap": "Objects/Lucy/Lucy_Normal.png",
"textureMapUv": "Unwrapped"
},
"roughness": {
- "textureMap": "Objects/Lucy/Lucy_bronze_roughness.png",
+ "textureMap": "Objects/Lucy/Lucy_bronze_Roughness.png",
"textureMapUv": "Unwrapped"
}
}
-}
+}
\ No newline at end of file
diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/105_DetailMaps_BlendMaskUsingDetailUVs.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/105_DetailMaps_BlendMaskUsingDetailUVs.material
index 6193cf4eed..a69b72b623 100644
--- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/105_DetailMaps_BlendMaskUsingDetailUVs.material
+++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/105_DetailMaps_BlendMaskUsingDetailUVs.material
@@ -5,7 +5,7 @@
"propertyLayoutVersion": 3,
"properties": {
"baseColor": {
- "textureMap": "Objects/Lucy/Lucy_bronze_baseColor.png",
+ "textureMap": "Objects/Lucy/Lucy_bronze_BaseColor.png",
"textureMapUv": "Unwrapped"
},
"detailLayerGroup": {
@@ -18,20 +18,24 @@
"normalDetailStrength": 1.5
},
"detailUV": {
+ "center": [
+ 0.0,
+ 0.0
+ ],
"scale": 10.0
},
"metallic": {
- "textureMap": "Objects/Lucy/Lucy_bronze_metallic.png",
+ "textureMap": "Objects/Lucy/Lucy_bronze_Metallic.png",
"textureMapUv": "Unwrapped"
},
"normal": {
"flipY": true,
- "textureMap": "Objects/Lucy/Lucy_normal.png",
+ "textureMap": "Objects/Lucy/Lucy_Normal.png",
"textureMapUv": "Unwrapped"
},
"roughness": {
- "textureMap": "Objects/Lucy/Lucy_bronze_roughness.png",
+ "textureMap": "Objects/Lucy/Lucy_bronze_Roughness.png",
"textureMapUv": "Unwrapped"
}
}
-}
+}
\ No newline at end of file
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h
index a41c8221f0..f2c120dbcd 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h
@@ -98,6 +98,7 @@ namespace AtomToolsFramework
AZStd::optional ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) override;
AZStd::optional ViewportScreenToWorldRay(
const AzFramework::ScreenPoint& screenPosition) override;
+ float DeviceScalingFactor() override;
//! Set interface for providing viewport specific settings (e.g. snapping properties).
void SetViewportSettings(const AzToolsFramework::ViewportInteraction::ViewportSettings* viewportSettings);
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp
index cee178c724..35edb3af5b 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp
@@ -313,8 +313,7 @@ namespace AtomToolsFramework
// Scale the size by the DPI of the platform to
// get the proper size in pixels.
const QSize uiWindowSize = size();
- const qreal deficePixelRatio = devicePixelRatioF();
- const QSize windowSize = uiWindowSize * deficePixelRatio;
+ const QSize windowSize = uiWindowSize * devicePixelRatioF();
const AzFramework::NativeWindowHandle windowId = reinterpret_cast(winId());
AzFramework::WindowNotificationBus::Event(windowId, &AzFramework::WindowNotifications::OnWindowResized, windowSize.width(), windowSize.height());
@@ -465,6 +464,11 @@ namespace AtomToolsFramework
return AzToolsFramework::ViewportInteraction::ProjectedViewportRay{rayOrigin, rayDirection};
}
+ float RenderViewportWidget::DeviceScalingFactor()
+ {
+ return aznumeric_cast(devicePixelRatioF());
+ }
+
AzFramework::ScreenPoint RenderViewportWidget::ViewportCursorScreenPosition()
{
return AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(m_mousePosition.toPoint());
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp
index 6a4bb8c0f4..887019787b 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp
@@ -71,6 +71,8 @@ namespace MaterialEditor
QObject::connect(m_ui->m_materialTypeComboBox, static_cast(&QComboBox::currentIndexChanged), this, [this]() { UpdateMaterialTypeSelection(); });
QObject::connect(m_ui->m_materialTypeComboBox, &QComboBox::currentTextChanged, this, [this]() { UpdateMaterialTypeSelection(); });
+ m_ui->m_materialTypeComboBox->model()->sort(0, Qt::AscendingOrder);
+
// Select the default material type from settings
auto settings =
AZ::UserSettings::CreateFind(AZ::Crc32("MaterialDocumentSettings"), AZ::UserSettings::CT_GLOBAL);
diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material
index 25e29b55e5..82b1cdb590 100644
--- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material
+++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material
@@ -26,7 +26,6 @@
},
"parallax": {
"algorithm": "POM",
- "enable": true,
"factor": 0.02500000037252903,
"pdo": true,
"quality": "Ultra",
diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016.material
index 336d479b30..03fb0ea5be 100644
--- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016.material
+++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Concrete016_8K/Concrete016.material
@@ -31,7 +31,8 @@
"algorithm": "ContactRefinement",
"factor": 0.019999999552965165,
"quality": "Ultra",
- "textureMap": "Materials/Concrete016_8K/Concrete016_8K_Displacement.png"
+ "textureMap": "Materials/Concrete016_8K/Concrete016_8K_Displacement.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Materials/Concrete016_8K/Concrete016_8K_Roughness.png"
diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001.material
index 72610e8bb6..7d8c3d5142 100644
--- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001.material
+++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric001_8K/Fabric001.material
@@ -20,7 +20,6 @@
},
"parallax": {
"algorithm": "ContactRefinement",
- "enable": true,
"factor": 0.004999999888241291,
"quality": "Ultra",
"textureMap": "Materials/Fabric001_8K/Fabric001_8K_Displacement.png"
diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030.material
index 458ab811b6..493bfab455 100644
--- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030.material
+++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Fabric030_4K/Fabric030.material
@@ -20,7 +20,6 @@
},
"parallax": {
"algorithm": "ContactRefinement",
- "enable": true,
"factor": 0.0020000000949949028,
"pdo": true,
"quality": "Medium",
diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material
index 57163f520d..a2bb2c7704 100644
--- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material
+++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material
@@ -19,7 +19,6 @@
},
"parallax": {
"algorithm": "ContactRefinement",
- "enable": true,
"factor": 0.009999999776482582,
"pdo": true,
"quality": "Ultra",
diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material
index 625d872475..f75490c2ad 100644
--- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material
+++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material
@@ -30,7 +30,8 @@
"factor": 0.02500000037252903,
"pdo": true,
"quality": "Ultra",
- "textureMap": "Materials/Bricks038_8K/Bricks038_8K_Displacement.png"
+ "textureMap": "Materials/Bricks038_8K/Bricks038_8K_Displacement.png",
+ "useTexture": false
},
"roughness": {
"factor": 0.4343433976173401,
diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material
index e3c6d9eae6..d7e2050dbd 100644
--- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material
+++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material
@@ -22,7 +22,6 @@
},
"parallax": {
"algorithm": "POM",
- "enable": true,
"factor": 0.02500000037252903,
"pdo": true,
"quality": "Ultra",
diff --git a/Gems/AtomContent/ReferenceMaterials/Assets/Materials/ConcreteStucco/concrete_stucco.material b/Gems/AtomContent/ReferenceMaterials/Assets/Materials/ConcreteStucco/concrete_stucco.material
index ab9f366ff6..d4e2016022 100644
--- a/Gems/AtomContent/ReferenceMaterials/Assets/Materials/ConcreteStucco/concrete_stucco.material
+++ b/Gems/AtomContent/ReferenceMaterials/Assets/Materials/ConcreteStucco/concrete_stucco.material
@@ -19,7 +19,8 @@
},
"parallax": {
"factor": 0.0010101000079885126,
- "textureMap": "Materials/ConcreteStucco/concrete_stucco_height.jpg"
+ "textureMap": "Materials/ConcreteStucco/concrete_stucco_height.jpg",
+ "useTexture": false
},
"specularF0": {
"factor": 0.5050504803657532
diff --git a/Gems/AtomContent/Sponza/Assets/license.txt b/Gems/AtomContent/Sponza/Assets/license.txt
new file mode 100644
index 0000000000..e303d8c767
--- /dev/null
+++ b/Gems/AtomContent/Sponza/Assets/license.txt
@@ -0,0 +1,8 @@
+The content in this gem "O3DE\Gems\AtomContent\Sponza" is ported
+from the original source, and modified for the O3DE Engine and Atom Renderer.
+
+The original "Crytek Sponza" scene data can be downloaded from the
+"McGuire Computer Graphics Archive": https://casual-effects.com/data/
+
+The original content is under the "CC BY 3.0" License:
+https://creativecommons.org/licenses/by/3.0/
\ No newline at end of file
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material
index 1102fb150a..d95e84121c 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material
@@ -41,7 +41,8 @@
"factor": 0.050999999046325687,
"pdo": true,
"quality": "High",
- "textureMap": "Textures/arch_1k_height.png"
+ "textureMap": "Textures/arch_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/arch_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material
index c1853250d7..710f790419 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material
@@ -47,7 +47,8 @@
"factor": 0.03099999949336052,
"pdo": true,
"quality": "High",
- "textureMap": "Textures/background_1k_height.png"
+ "textureMap": "Textures/background_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/background_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material
index a269098b4d..26d64c7db9 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material
@@ -46,7 +46,8 @@
"algorithm": "ContactRefinement",
"factor": 0.03500000014901161,
"quality": "Medium",
- "textureMap": "Textures/bricks_1k_height.png"
+ "textureMap": "Textures/bricks_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/bricks_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material
index 94225cd00e..95d08d398b 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material
@@ -48,7 +48,8 @@
"factor": 0.019999999552965165,
"pdo": true,
"quality": "Medium",
- "textureMap": "Textures/ceiling_1k_height.png"
+ "textureMap": "Textures/ceiling_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/ceiling_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material
index 8f1cea8649..cc1f685c7c 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material
@@ -47,7 +47,8 @@
"factor": 0.017000000923871995,
"pdo": true,
"quality": "High",
- "textureMap": "Textures/columnA_1k_height.png"
+ "textureMap": "Textures/columnA_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/columnA_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material
index ac474d7e76..a1e8747f65 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material
@@ -46,7 +46,8 @@
"factor": 0.020999999716877939,
"pdo": true,
"quality": "High",
- "textureMap": "Textures/columnB_1k_height.png"
+ "textureMap": "Textures/columnB_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/columnB_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material
index 81fd03fc4a..6edbfde47c 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material
@@ -47,7 +47,8 @@
"factor": 0.014000000432133675,
"pdo": true,
"quality": "High",
- "textureMap": "Textures/columnC_1k_height.png"
+ "textureMap": "Textures/columnC_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/columnC_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material
index fde599fd4c..1b66a51ec0 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material
@@ -38,7 +38,8 @@
"algorithm": "POM",
"factor": 0.02500000037252903,
"pdo": true,
- "textureMap": "Textures/details_1k_height.png"
+ "textureMap": "Textures/details_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/details_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material
index e50e8a0ed2..19010d66e5 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material
@@ -41,7 +41,8 @@
"factor": 0.014000000432133675,
"pdo": true,
"quality": "High",
- "textureMap": "Textures/flagpole_1k_height.png"
+ "textureMap": "Textures/flagpole_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/flagpole_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material
index 064a2b24a6..bee92e0edb 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material
@@ -43,7 +43,8 @@
"algorithm": "POM",
"factor": 0.012000000104308129,
"pdo": true,
- "textureMap": "Textures/floor_1k_height.png"
+ "textureMap": "Textures/floor_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/floor_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material
index 269e1e5684..ac326ae935 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material
@@ -42,7 +42,8 @@
"mode": "Cutout"
},
"parallax": {
- "textureMap": "Textures/thorn_height.png"
+ "textureMap": "Textures/thorn_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/thorn_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material
index 8dc4852b03..b1f78aa33f 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material
@@ -38,7 +38,6 @@
},
"parallax": {
"algorithm": "ContactRefinement",
- "enable": true,
"factor": 0.009999999776482582,
"pdo": true,
"quality": "Ultra",
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material
index 0a7246703c..a3e066a438 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material
@@ -35,7 +35,8 @@
"algorithm": "ContactRefinement",
"factor": 0.019999999552965165,
"quality": "Medium",
- "textureMap": "Textures/roof_1k_height.png"
+ "textureMap": "Textures/roof_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/roof_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material
index 77adc798a0..dea9aa2a8a 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material
@@ -41,7 +41,8 @@
"factor": 0.027000000700354577,
"pdo": true,
"quality": "High",
- "textureMap": "Textures/vase_1k_height.png"
+ "textureMap": "Textures/vase_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/vase_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material
index 22e78f03ae..b2a342dd76 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material
@@ -41,7 +41,8 @@
"factor": 0.04600000008940697,
"pdo": true,
"quality": "High",
- "textureMap": "Textures/vaseHanging_1k_height.png"
+ "textureMap": "Textures/vaseHanging_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/vaseHanging_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material
index c773146b51..fba07379c0 100644
--- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material
+++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material
@@ -45,7 +45,8 @@
"factor": 0.019999999552965165,
"pdo": true,
"quality": "High",
- "textureMap": "Textures/vaseRound_1k_height.png"
+ "textureMap": "Textures/vaseRound_1k_height.png",
+ "useTexture": false
},
"roughness": {
"textureMap": "Textures/vaseRound_1k_roughness.png"
diff --git a/Gems/AtomContent/Sponza/Assets/stub b/Gems/AtomContent/Sponza/Assets/stub
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp
index dce83c3072..5fe8c50350 100644
--- a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp
+++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp
@@ -18,6 +18,7 @@
#include
#include
+#include
#include
#include
@@ -145,12 +146,24 @@ namespace AZ::Render
}
// Initialize our shader
- auto viewportSize = viewportContext->GetViewportSize();
+ AZ::Vector2 viewportSize;
+ {
+ AzFramework::WindowSize viewportWindowSize = viewportContext->GetViewportSize();
+ viewportSize = AZ::Vector2{aznumeric_cast(viewportWindowSize.m_width), aznumeric_cast(viewportWindowSize.m_height)};
+ }
AZ::Data::Instance drawSrg = dynamicDraw->NewDrawSrg();
- drawSrg->SetConstant(m_viewportSizeIndex, AZ::Vector2(aznumeric_cast(viewportSize.m_width), aznumeric_cast(viewportSize.m_height)));
+ drawSrg->SetConstant(m_viewportSizeIndex,viewportSize);
drawSrg->SetImageView(m_textureParameterIndex, image->GetImageView());
drawSrg->Compile();
+ // Scale icons by screen DPI
+ float scalingFactor = 1.0f;
+ {
+ using ViewportRequestBus = AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus;
+ ViewportRequestBus::EventResult(
+ scalingFactor, drawParameters.m_viewport, &ViewportRequestBus::Events::DeviceScalingFactor);
+ }
+
AZ::Vector3 screenPosition;
if (drawParameters.m_positionSpace == CoordinateSpace::ScreenSpace)
{
@@ -158,9 +171,11 @@ namespace AZ::Render
}
else if (drawParameters.m_positionSpace == CoordinateSpace::WorldSpace)
{
- using ViewportRequestBus = AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus;
- AzFramework::ScreenPoint position;
- ViewportRequestBus::EventResult(position, drawParameters.m_viewport, &ViewportRequestBus::Events::ViewportWorldToScreen, drawParameters.m_position);
+ // Calculate our screen space position using the viewport size
+ // We want this instead of RenderViewportWidget::WorldToScreen which works in QWidget virtual coordinate space
+ AzFramework::ScreenPoint position = AzFramework::WorldToScreen(
+ drawParameters.m_position, viewportContext->GetCameraViewMatrix(), viewportContext->GetCameraProjectionMatrix(),
+ viewportSize);
screenPosition.SetX(aznumeric_cast(position.m_x));
screenPosition.SetY(aznumeric_cast(position.m_y));
}
@@ -179,8 +194,8 @@ namespace AZ::Render
{
Vertex vertex;
screenPosition.StoreToFloat3(vertex.m_position);
- vertex.m_position[0] += offsetX * drawParameters.m_size.GetX();
- vertex.m_position[1] += offsetY * drawParameters.m_size.GetY();
+ vertex.m_position[0] += offsetX * drawParameters.m_size.GetX() * scalingFactor;
+ vertex.m_position[1] += offsetY * drawParameters.m_size.GetY() * scalingFactor;
vertex.m_color = drawParameters.m_color.ToU32();
vertex.m_uv[0] = u;
vertex.m_uv[1] = v;
@@ -197,8 +212,15 @@ namespace AZ::Render
dynamicDraw->DrawIndexed(&vertices, vertices.size(), &indices, indices.size(), RHI::IndexFormat::Uint16, drawSrg);
}
- QString AtomViewportDisplayIconsSystemComponent::FindAssetPath(const QString& sourceRelativePath) const
+ QString AtomViewportDisplayIconsSystemComponent::FindAssetPath(const QString& path) const
{
+ // If we get an absolute path, just use it.
+ QFileInfo pathInfo(path);
+ if (pathInfo.isAbsolute())
+ {
+ return path;
+ }
+
bool found = false;
AZStd::vector scanFolders;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
@@ -212,9 +234,9 @@ namespace AZ::Render
for (const auto& folder : scanFolders)
{
QDir dir(folder.data());
- if (dir.exists(sourceRelativePath))
+ if (dir.exists(path))
{
- return dir.absoluteFilePath(sourceRelativePath);
+ return dir.absoluteFilePath(path);
}
}
@@ -256,10 +278,6 @@ namespace AZ::Render
AzToolsFramework::EditorViewportIconDisplayInterface::IconId AtomViewportDisplayIconsSystemComponent::GetOrLoadIconForPath(
AZStd::string_view path)
{
- AZ_Error(
- "AtomViewportDisplayIconsSystemComponent", AzFramework::StringFunc::Path::IsRelative(path.data()),
- "GetOrLoadIconForPath assumes that it will always be given a relative path, but got '%s'", path.data());
-
// Check our cache to see if the image is already loaded
auto existingEntryIt = AZStd::find_if(m_iconData.begin(), m_iconData.end(), [&path](const auto& iconData)
{
diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h
index 0c7366f23b..b44957b51d 100644
--- a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h
+++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h
@@ -61,7 +61,7 @@ namespace AZ
static constexpr QSize MinimumRenderedSvgSize = QSize(128, 128);
static constexpr QImage::Format QtImageFormat = QImage::Format_RGBA8888;
- QString FindAssetPath(const QString& sourceRelativePath) const;
+ QString FindAssetPath(const QString& path) const;
QImage RenderSvgToImage(const QString& svgPath) const;
AZ::Data::Instance ConvertToAtomImage(AZ::Uuid assetId, QImage image) const;
diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt
index de4ee9b4b5..0f134d4218 100644
--- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt
+++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/CMakeLists.txt
@@ -10,7 +10,7 @@
#
ly_add_target(
- NAME AtomViewportDisplayInfo GEM_MODULE
+ NAME AtomViewportDisplayInfo ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE}
NAMESPACE Gem
FILES_CMAKE
atomviewportdisplayinfo_files.cmake
diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp
index 672c26a9ab..7d830b4ca9 100644
--- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp
+++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp
@@ -18,10 +18,11 @@
#include
#include
+#include
+#include
#include
#include
#include
-#include
#include
#include
@@ -146,7 +147,7 @@ namespace AZ::Render
if (m_updateRootPassQuery)
{
- if (auto rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass())
+ if (auto rootPass = viewportContext->GetCurrentPipeline()->GetRootPass())
{
rootPass->SetPipelineStatisticsQueryEnabled(displayLevel != AtomBridge::ViewportInfoDisplayState::CompactInfo);
m_updateRootPassQuery = false;
@@ -226,7 +227,8 @@ namespace AZ::Render
void AtomViewportDisplayInfoSystemComponent::DrawPassInfo()
{
- auto rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass();
+ AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext();
+ auto rootPass = viewportContext->GetCurrentPipeline()->GetRootPass();
const RPI::PipelineStatisticsResult stats = rootPass->GetLatestPipelineStatisticsResult();
AZStd::function)> containingPassCount = [&containingPassCount](const AZ::RPI::Ptr pass)
{
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h
index 1acaa6fdf8..41ea80f8d1 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h
@@ -35,14 +35,13 @@ namespace AZ
, private MeshComponentNotificationBus::Handler
{
public:
-
using BaseClass = EditorRenderComponentAdapter;
AZ_EDITOR_COMPONENT(AZ::Render::EditorMeshComponent, EditorMeshComponentTypeId, BaseClass);
static void Reflect(AZ::ReflectContext* context);
EditorMeshComponent() = default;
- EditorMeshComponent(const MeshComponentConfig& config);
+ explicit EditorMeshComponent(const MeshComponentConfig& config);
// AZ::Component overrides ...
void Activate() override;
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponent.h
index a57780c384..fe7f45d7d1 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponent.h
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponent.h
@@ -25,12 +25,11 @@ namespace AZ
: public AzFramework::Components::ComponentAdapter
{
public:
-
using BaseClass = AzFramework::Components::ComponentAdapter;
AZ_COMPONENT(AZ::Render::MeshComponent, MeshComponentTypeId, BaseClass);
MeshComponent() = default;
- MeshComponent(const MeshComponentConfig& config);
+ explicit MeshComponent(const MeshComponentConfig& config);
static void Reflect(AZ::ReflectContext* context);
};
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp
index a4a91cf708..c089dd01f9 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp
@@ -177,28 +177,33 @@ namespace AZ
FixUpModelAsset(m_configuration.m_modelAsset);
}
- void MeshComponentController::Activate(AZ::EntityId entityId)
+ void MeshComponentController::Activate(const AZ::EntityComponentIdPair& entityComponentIdPair)
{
FixUpModelAsset(m_configuration.m_modelAsset);
- m_entityId = entityId;
+ const AZ::EntityId entityId = entityComponentIdPair.GetEntityId();
+ m_entityComponentIdPair = entityComponentIdPair;
- m_transformInterface = TransformBus::FindFirstHandler(m_entityId);
+ m_transformInterface = TransformBus::FindFirstHandler(entityId);
AZ_Warning("MeshComponentController", m_transformInterface, "Unable to attach to a TransformBus handler. This mesh will always be rendered at the origin.");
- m_meshFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity(m_entityId);
+ m_meshFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity(entityId);
AZ_Error("MeshComponentController", m_meshFeatureProcessor, "Unable to find a MeshFeatureProcessorInterface on the entityId.");
m_cachedNonUniformScale = AZ::Vector3::CreateOne();
- AZ::NonUniformScaleRequestBus::EventResult(m_cachedNonUniformScale, m_entityId, &AZ::NonUniformScaleRequests::GetScale);
- AZ::NonUniformScaleRequestBus::Event(m_entityId, &AZ::NonUniformScaleRequests::RegisterScaleChangedEvent,
+ AZ::NonUniformScaleRequestBus::EventResult(m_cachedNonUniformScale, entityId, &AZ::NonUniformScaleRequests::GetScale);
+ AZ::NonUniformScaleRequestBus::Event(entityId, &AZ::NonUniformScaleRequests::RegisterScaleChangedEvent,
m_nonUniformScaleChangedHandler);
- MeshComponentRequestBus::Handler::BusConnect(m_entityId);
- TransformNotificationBus::Handler::BusConnect(m_entityId);
- MaterialReceiverRequestBus::Handler::BusConnect(m_entityId);
- MaterialComponentNotificationBus::Handler::BusConnect(m_entityId);
- AzFramework::BoundsRequestBus::Handler::BusConnect(m_entityId);
+ MeshComponentRequestBus::Handler::BusConnect(entityId);
+ TransformNotificationBus::Handler::BusConnect(entityId);
+ MaterialReceiverRequestBus::Handler::BusConnect(entityId);
+ MaterialComponentNotificationBus::Handler::BusConnect(entityId);
+ AzFramework::BoundsRequestBus::Handler::BusConnect(entityId);
+ AzFramework::EntityContextId contextId;
+ AzFramework::EntityIdContextQueryBus::EventResult(
+ contextId, entityId, &AzFramework::EntityIdContextQueries::GetOwningContextId);
+ AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusConnect({entityId, contextId});
//Buses must be connected before RegisterModel in case requests are made as a result of HandleModelChange
RegisterModel();
@@ -209,6 +214,7 @@ namespace AZ
// Buses must be disconnected after unregistering the model, otherwise they can't deliver the events during the process.
UnregisterModel();
+ AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusDisconnect();
AzFramework::BoundsRequestBus::Handler::BusDisconnect();
MeshComponentRequestBus::Handler::BusDisconnect();
TransformNotificationBus::Handler::BusDisconnect();
@@ -219,7 +225,7 @@ namespace AZ
m_meshFeatureProcessor = nullptr;
m_transformInterface = nullptr;
- m_entityId = AZ::EntityId(AZ::EntityId::InvalidEntityId);
+ m_entityComponentIdPair = AZ::EntityComponentIdPair(AZ::EntityId(), AZ::InvalidComponentId);
m_configuration.m_modelAsset.Release();
}
@@ -293,10 +299,11 @@ namespace AZ
Data::Asset modelAsset = m_meshFeatureProcessor->GetModelAsset(m_meshHandle);
if (model && modelAsset)
{
+ const AZ::EntityId entityId = m_entityComponentIdPair.GetEntityId();
m_configuration.m_modelAsset = modelAsset;
- MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelReady, m_configuration.m_modelAsset, model);
- MaterialReceiverNotificationBus::Event(m_entityId, &MaterialReceiverNotificationBus::Events::OnMaterialAssignmentsChanged);
- AZ::Interface::Get()->RefreshEntityLocalBoundsUnion(m_entityId);
+ MeshComponentNotificationBus::Event(entityId, &MeshComponentNotificationBus::Events::OnModelReady, m_configuration.m_modelAsset, model);
+ MaterialReceiverNotificationBus::Event(entityId, &MaterialReceiverNotificationBus::Events::OnMaterialAssignmentsChanged);
+ AZ::Interface::Get()->RefreshEntityLocalBoundsUnion(entityId);
}
}
@@ -304,8 +311,10 @@ namespace AZ
{
if (m_meshFeatureProcessor && m_configuration.m_modelAsset.GetId().IsValid())
{
+ const AZ::EntityId entityId = m_entityComponentIdPair.GetEntityId();
+
MaterialAssignmentMap materials;
- MaterialComponentRequestBus::EventResult(materials, m_entityId, &MaterialComponentRequests::GetMaterialOverrides);
+ MaterialComponentRequestBus::EventResult(materials, entityId, &MaterialComponentRequests::GetMaterialOverrides);
m_meshFeatureProcessor->ReleaseMesh(m_meshHandle);
m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials,
@@ -330,7 +339,8 @@ namespace AZ
{
if (m_meshFeatureProcessor && m_meshHandle.IsValid())
{
- MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelPreDestroy);
+ MeshComponentNotificationBus::Event(
+ m_entityComponentIdPair.GetEntityId(), &MeshComponentNotificationBus::Events::OnModelPreDestroy);
m_meshFeatureProcessor->ReleaseMesh(m_meshHandle);
}
}
@@ -462,5 +472,34 @@ namespace AZ
return Aabb::CreateNull();
}
}
+
+ AzFramework::RenderGeometry::RayResult MeshComponentController::RenderGeometryIntersect(
+ const AzFramework::RenderGeometry::RayRequest& ray)
+ {
+ AzFramework::RenderGeometry::RayResult result;
+ if (const Data::Instance model = GetModel())
+ {
+ float t;
+ AZ::Vector3 normal;
+ if (model->RayIntersection(
+ m_transformInterface->GetWorldTM(), m_cachedNonUniformScale, ray.m_startWorldPosition,
+ ray.m_endWorldPosition - ray.m_startWorldPosition, t, normal))
+ {
+ // note: this is a temporary workaround to handle cases where model->RayIntersection
+ // returns negative distances, follow-up ATOM-15673
+ const auto absT = AZStd::abs(t);
+
+ // fill in ray result structure after successful intersection
+ const auto intersectionLine = (ray.m_endWorldPosition - ray.m_startWorldPosition);
+ result.m_uv = AZ::Vector2::CreateZero();
+ result.m_worldPosition = ray.m_startWorldPosition + intersectionLine * absT;
+ result.m_worldNormal = normal;
+ result.m_distance = intersectionLine.GetLength() * absT;
+ result.m_entityAndComponent = m_entityComponentIdPair;
+ }
+ }
+
+ return result;
+ }
} // namespace Render
} // namespace AZ
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h
index 0cda34ea42..4d63e5e88d 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h
@@ -13,11 +13,13 @@
#pragma once
#include
+#include
#include
#include
#include
+#include