diff --git a/Assets/Editor/Materials/Stripes.tif.exportsettings b/Assets/Editor/Materials/Stripes.tif.exportsettings
deleted file mode 100644
index 0653bb85eb..0000000000
--- a/Assets/Editor/Materials/Stripes.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Diffuse_lowQ
\ No newline at end of file
diff --git a/Assets/Editor/Materials/voxel_editor.png.exportsettings b/Assets/Editor/Materials/voxel_editor.png.exportsettings
deleted file mode 100644
index d19ae00148..0000000000
--- a/Assets/Editor/Materials/voxel_editor.png.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /mipmaps=0 /preset=AlbedoWithGenericAlpha /reduce=-1
\ No newline at end of file
diff --git a/Assets/Engine/EngineAssets/Icons/AverageMemoryUsage.TIF.exportsettings b/Assets/Engine/EngineAssets/Icons/AverageMemoryUsage.TIF.exportsettings
deleted file mode 100644
index c48fb8632a..0000000000
--- a/Assets/Engine/EngineAssets/Icons/AverageMemoryUsage.TIF.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Uncompressed
\ No newline at end of file
diff --git a/Assets/Engine/EngineAssets/Icons/HighMemoryUsage.TIF.exportsettings b/Assets/Engine/EngineAssets/Icons/HighMemoryUsage.TIF.exportsettings
deleted file mode 100644
index c48fb8632a..0000000000
--- a/Assets/Engine/EngineAssets/Icons/HighMemoryUsage.TIF.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Uncompressed
\ No newline at end of file
diff --git a/Assets/Engine/EngineAssets/Icons/LevelShaderCacheMiss.tif.exportsettings b/Assets/Engine/EngineAssets/Icons/LevelShaderCacheMiss.tif.exportsettings
deleted file mode 100644
index c48fb8632a..0000000000
--- a/Assets/Engine/EngineAssets/Icons/LevelShaderCacheMiss.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Uncompressed
\ No newline at end of file
diff --git a/Assets/Engine/EngineAssets/Icons/LivePreview.TIF.exportsettings b/Assets/Engine/EngineAssets/Icons/LivePreview.TIF.exportsettings
deleted file mode 100644
index 8da27c31a4..0000000000
--- a/Assets/Engine/EngineAssets/Icons/LivePreview.TIF.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /dns=1 /preset=Uncompressed
\ No newline at end of file
diff --git a/Assets/Engine/EngineAssets/Icons/LowMemoryUsage.TIF.exportsettings b/Assets/Engine/EngineAssets/Icons/LowMemoryUsage.TIF.exportsettings
deleted file mode 100644
index c48fb8632a..0000000000
--- a/Assets/Engine/EngineAssets/Icons/LowMemoryUsage.TIF.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Uncompressed
\ No newline at end of file
diff --git a/Assets/Engine/EngineAssets/Icons/NavigationProcessing.tif.exportsettings b/Assets/Engine/EngineAssets/Icons/NavigationProcessing.tif.exportsettings
deleted file mode 100644
index 8da27c31a4..0000000000
--- a/Assets/Engine/EngineAssets/Icons/NavigationProcessing.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /dns=1 /preset=Uncompressed
\ No newline at end of file
diff --git a/Assets/Engine/EngineAssets/Icons/NullSoundSystem.tif.exportsettings b/Assets/Engine/EngineAssets/Icons/NullSoundSystem.tif.exportsettings
deleted file mode 100644
index 8da27c31a4..0000000000
--- a/Assets/Engine/EngineAssets/Icons/NullSoundSystem.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /dns=1 /preset=Uncompressed
\ No newline at end of file
diff --git a/Assets/Engine/EngineAssets/Icons/ShaderCompiling.tif.exportsettings b/Assets/Engine/EngineAssets/Icons/ShaderCompiling.tif.exportsettings
deleted file mode 100644
index 8da27c31a4..0000000000
--- a/Assets/Engine/EngineAssets/Icons/ShaderCompiling.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /dns=1 /preset=Uncompressed
\ No newline at end of file
diff --git a/Assets/Engine/EngineAssets/Icons/Streaming.tif.exportsettings b/Assets/Engine/EngineAssets/Icons/Streaming.tif.exportsettings
deleted file mode 100644
index 8da27c31a4..0000000000
--- a/Assets/Engine/EngineAssets/Icons/Streaming.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /dns=1 /preset=Uncompressed
\ No newline at end of file
diff --git a/Assets/Engine/EngineAssets/Icons/StreamingTerrain.tif.exportsettings b/Assets/Engine/EngineAssets/Icons/StreamingTerrain.tif.exportsettings
deleted file mode 100644
index 8da27c31a4..0000000000
--- a/Assets/Engine/EngineAssets/Icons/StreamingTerrain.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /dns=1 /preset=Uncompressed
\ No newline at end of file
diff --git a/Assets/Engine/exclude.filetag b/Assets/Engine/exclude.filetag
index 52534a87d8..3528454ec4 100644
--- a/Assets/Engine/exclude.filetag
+++ b/Assets/Engine/exclude.filetag
@@ -125,17 +125,6 @@
-
-
-
-
-
-
-
-
-
-
-
@@ -207,27 +196,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Assets/Engine/textures/default_icon.png.exportsettings b/Assets/Engine/textures/default_icon.png.exportsettings
deleted file mode 100644
index 89ea1ac93f..0000000000
--- a/Assets/Engine/textures/default_icon.png.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /mipmaps=0 /preset=Albedo /reduce=-1 /ser=1
\ No newline at end of file
diff --git a/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_diff.tif.exportsettings b/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_diff.tif.exportsettings
deleted file mode 100644
index b65133fbb0..0000000000
--- a/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_diff.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=AlbedoWithGenericAlpha /reduce="android:2,ios:2,mac:0,pc:0,provo:0"
\ No newline at end of file
diff --git a/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_sss.tif.exportsettings b/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_sss.tif.exportsettings
deleted file mode 100644
index e8da408b36..0000000000
--- a/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_sss.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Albedo /reduce="android:3,ios:3,mac:0,pc:0,provo:0"
\ No newline at end of file
diff --git a/AutomatedTesting/Config/shader_global_build_options.json b/AutomatedTesting/Config/shader_global_build_options.json
index 08e4d7f502..1aacb05575 100644
--- a/AutomatedTesting/Config/shader_global_build_options.json
+++ b/AutomatedTesting/Config/shader_global_build_options.json
@@ -3,9 +3,15 @@
"Version": 1,
"ClassName": "GlobalBuildOptions",
"ClassData": {
- "ShaderCompilerArguments" : {
- "DefaultMatrixOrder" : "Row",
- "AzslcAdditionalFreeArguments" : "--strip-unused-srgs"
+ "ShaderCompilerArguments": {
+ "DefaultMatrixOrder": "Row",
+ "AzslcAdditionalFreeArguments": "--strip-unused-srgs"
+ },
+ "PreprocessorOptions": {
+ "predefinedMacros": [ "AZSL=17" ],
+ "projectIncludePaths": [
+ "Gems/AtomTressFX/Assets/Shaders"
+ ]
}
}
}
\ No newline at end of file
diff --git a/AutomatedTesting/Editor/Scripts/scene_mesh_to_prefab.py b/AutomatedTesting/Editor/Scripts/scene_mesh_to_prefab.py
new file mode 100644
index 0000000000..d5a7acfe91
--- /dev/null
+++ b/AutomatedTesting/Editor/Scripts/scene_mesh_to_prefab.py
@@ -0,0 +1,162 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+import os, traceback, binascii, sys, json, pathlib
+import azlmbr.math
+import azlmbr.bus
+
+#
+# SceneAPI Processor
+#
+
+
+def log_exception_traceback():
+ exc_type, exc_value, exc_tb = sys.exc_info()
+ data = traceback.format_exception(exc_type, exc_value, exc_tb)
+ print(str(data))
+
+def get_mesh_node_names(sceneGraph):
+ import azlmbr.scene as sceneApi
+ import azlmbr.scene.graph
+ from scene_api import scene_data as sceneData
+
+ meshDataList = []
+ node = sceneGraph.get_root()
+ children = []
+ paths = []
+
+ while node.IsValid():
+ # store children to process after siblings
+ if sceneGraph.has_node_child(node):
+ children.append(sceneGraph.get_node_child(node))
+
+ nodeName = sceneData.SceneGraphName(sceneGraph.get_node_name(node))
+ paths.append(nodeName.get_path())
+
+ # store any node that has mesh data content
+ nodeContent = sceneGraph.get_node_content(node)
+ if nodeContent.CastWithTypeName('MeshData'):
+ if sceneGraph.is_node_end_point(node) is False:
+ if (len(nodeName.get_path())):
+ meshDataList.append(sceneData.SceneGraphName(sceneGraph.get_node_name(node)))
+
+ # advance to next node
+ if sceneGraph.has_node_sibling(node):
+ node = sceneGraph.get_node_sibling(node)
+ elif children:
+ node = children.pop()
+ else:
+ node = azlmbr.scene.graph.NodeIndex()
+
+ return meshDataList, paths
+
+def update_manifest(scene):
+ import json
+ import uuid, os
+ import azlmbr.scene as sceneApi
+ import azlmbr.scene.graph
+ from scene_api import scene_data as sceneData
+
+ graph = sceneData.SceneGraph(scene.graph)
+ # Get a list of all the mesh nodes, as well as all the nodes
+ mesh_name_list, all_node_paths = get_mesh_node_names(graph)
+ scene_manifest = sceneData.SceneManifest()
+
+ clean_filename = scene.sourceFilename.replace('.', '_')
+
+ # Compute the filename of the scene file
+ source_basepath = scene.watchFolder
+ source_relative_path = os.path.dirname(os.path.relpath(clean_filename, source_basepath))
+ source_filename_only = os.path.basename(clean_filename)
+
+ created_entities = []
+
+ # Loop every mesh node in the scene
+ for activeMeshIndex in range(len(mesh_name_list)):
+ mesh_name = mesh_name_list[activeMeshIndex]
+ mesh_path = mesh_name.get_path()
+ # Create a unique mesh group name using the filename + node name
+ mesh_group_name = '{}_{}'.format(source_filename_only, mesh_name.get_name())
+ # Remove forbidden filename characters from the name since this will become a file on disk later
+ mesh_group_name = "".join(char for char in mesh_group_name if char not in "|<>:\"/?*\\")
+ # Add the MeshGroup to the manifest and give it a unique ID
+ mesh_group = scene_manifest.add_mesh_group(mesh_group_name)
+ mesh_group['id'] = '{' + str(uuid.uuid5(uuid.NAMESPACE_DNS, source_filename_only + mesh_path)) + '}'
+ # Set our current node as the only node that is included in this MeshGroup
+ scene_manifest.mesh_group_select_node(mesh_group, mesh_path)
+
+ # Explicitly remove all other nodes to prevent implicit inclusions
+ for node in all_node_paths:
+ if node != mesh_path:
+ scene_manifest.mesh_group_unselect_node(mesh_group, node)
+
+ # Create an editor entity
+ entity_id = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "CreateEditorReadyEntity", mesh_group_name)
+ # Add an EditorMeshComponent to the entity
+ editor_mesh_component = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "GetOrAddComponentByTypeName", entity_id, "AZ::Render::EditorMeshComponent")
+ # Set the ModelAsset assetHint to the relative path of the input asset + the name of the MeshGroup we just created + the azmodel extension
+ # The MeshGroup we created will be output as a product in the asset's path named mesh_group_name.azmodel
+ # The assetHint will be converted to an AssetId later during prefab loading
+ json_update = json.dumps({
+ "Controller": { "Configuration": { "ModelAsset": {
+ "assetHint": os.path.join(source_relative_path, mesh_group_name) + ".azmodel" }}}
+ });
+ # Apply the JSON above to the component we created
+ result = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "UpdateComponentForEntity", entity_id, editor_mesh_component, json_update)
+
+ if not result:
+ raise RuntimeError("UpdateComponentForEntity failed")
+
+ # Keep track of the entity we set up, we'll add them all to the prefab we're creating later
+ created_entities.append(entity_id)
+
+ # Create a prefab with all our entities
+ prefab_filename = source_filename_only + ".prefab"
+ created_template_id = azlmbr.prefab.PrefabSystemScriptingBus(azlmbr.bus.Broadcast, "CreatePrefab", created_entities, prefab_filename)
+
+ if created_template_id == azlmbr.prefab.InvalidTemplateId:
+ raise RuntimeError("CreatePrefab {} failed".format(prefab_filename))
+
+ # Convert the prefab to a JSON string
+ output = azlmbr.prefab.PrefabLoaderScriptingBus(azlmbr.bus.Broadcast, "SaveTemplateToString", created_template_id)
+
+ if output.IsSuccess():
+ jsonString = output.GetValue()
+ uuid = azlmbr.math.Uuid_CreateRandom().ToString()
+ jsonResult = json.loads(jsonString)
+ # Add a PrefabGroup to the manifest and store the JSON on it
+ scene_manifest.add_prefab_group(source_filename_only, uuid, jsonResult)
+ else:
+ raise RuntimeError("SaveTemplateToString failed for template id {}, prefab {}".format(created_template_id, prefab_filename))
+
+ # Convert the manifest to a JSON string and return it
+ new_manifest = scene_manifest.export()
+
+ return new_manifest
+
+sceneJobHandler = None
+
+def on_update_manifest(args):
+ try:
+ scene = args[0]
+ return update_manifest(scene)
+ except RuntimeError as err:
+ print (f'ERROR - {err}')
+ log_exception_traceback()
+
+ global sceneJobHandler
+ sceneJobHandler = None
+
+# try to create SceneAPI handler for processing
+try:
+ import azlmbr.scene as sceneApi
+ if (sceneJobHandler == None):
+ sceneJobHandler = sceneApi.ScriptBuildingNotificationBusHandler()
+ sceneJobHandler.connect()
+ sceneJobHandler.add_callback('OnUpdateManifest', on_update_manifest)
+except:
+ sceneJobHandler = None
diff --git a/AutomatedTesting/Gem/Code/enabled_gems.cmake b/AutomatedTesting/Gem/Code/enabled_gems.cmake
index bae8afabb1..30740a489d 100644
--- a/AutomatedTesting/Gem/Code/enabled_gems.cmake
+++ b/AutomatedTesting/Gem/Code/enabled_gems.cmake
@@ -21,9 +21,9 @@ set(ENABLED_GEMS
QtForPython
PythonAssetBuilder
Metastream
-
Camera
EMotionFX
+ AtomTressFX
PhysX
CameraFramework
StartingPointMovement
@@ -52,9 +52,6 @@ set(ENABLED_GEMS
AWSCore
AWSClientAuth
AWSMetrics
-
-
-
-
+ PrefabBuilder
AudioSystem
)
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/Atom/CMakeLists.txt
index 02aaa42597..ff3cd5c465 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/Atom/CMakeLists.txt
@@ -6,12 +6,7 @@
#
#
-################################################################################
-# Atom Renderer: Automated Tests
-# Runs EditorPythonBindings (hydra) scripts inside the Editor to verify test results for the Atom renderer.
-################################################################################
-
-if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedTesting IN_LIST LY_PROJECTS)
+if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_add_pytest(
NAME AutomatedTesting::Atom_TestSuite_Main
TEST_SUITE main
@@ -65,4 +60,18 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT
COMPONENT
Atom
)
+ ly_add_pytest(
+ NAME AutomatedTesting::Atom_TestSuite_Main_GPU_Optimized
+ TEST_SUITE main
+ TEST_REQUIRES gpu
+ TEST_SERIAL
+ TIMEOUT 1200
+ PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main_GPU_Optimized.py
+ RUNTIME_DEPENDENCIES
+ AssetProcessor
+ AutomatedTesting.Assets
+ Editor
+ COMPONENT
+ Atom
+ )
endif()
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py
index 4c5716d365..e4a77ca4ec 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py
@@ -3,8 +3,6 @@ Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
-
-Main suite tests for the Atom renderer.
"""
import logging
import os
@@ -161,21 +159,6 @@ class TestAtomEditorComponentsMain(object):
"Display Mapper_test: Entity deleted: True",
"Display Mapper_test: UNDO entity deletion works: True",
"Display Mapper_test: REDO entity deletion works: True",
- # Reflection Probe Component
- "Reflection Probe Entity successfully created",
- "Reflection Probe_test: Component added to the entity: True",
- "Reflection Probe_test: Component removed after UNDO: True",
- "Reflection Probe_test: Component added after REDO: True",
- "Reflection Probe_test: Entered game mode: True",
- "Reflection Probe_test: Exit game mode: True",
- "Reflection Probe_test: Entity disabled initially: True",
- "Reflection Probe_test: Entity enabled after adding required components: True",
- "Reflection Probe_test: Cubemap is generated: True",
- "Reflection Probe_test: Entity is hidden: True",
- "Reflection Probe_test: Entity is shown: True",
- "Reflection Probe_test: Entity deleted: True",
- "Reflection Probe_test: UNDO entity deletion works: True",
- "Reflection Probe_test: REDO entity deletion works: True",
]
unexpected_lines = [
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py
index 3403d8e9b1..220623af8b 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py
@@ -220,20 +220,18 @@ class TestPerformanceBenchmarkSuite(object):
@pytest.mark.system
class TestMaterialEditor(object):
- @pytest.mark.parametrize("cfg_args", ["-rhi=dx12", "-rhi=Vulkan"])
+ @pytest.mark.parametrize("cfg_args,expected_lines", [
+ pytest.param("-rhi=dx12", ["Registering dx12 RHI"]),
+ pytest.param("-rhi=Vulkan", ["Registering vulkan RHI"])
+ ])
@pytest.mark.parametrize("exe_file_name", ["MaterialEditor"])
def test_MaterialEditorLaunch_AllRHIOptionsSucceed(
- self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name, cfg_args):
+ self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name, cfg_args,
+ expected_lines):
"""
Tests each valid RHI option (Null RHI excluded) can be launched with the MaterialEditor.
- Checks for the "Finished loading viewport configurations." success message post launch.
+ Checks for the specific expected_lines messaging for each RHI type.
"""
- expected_lines = ["Finished loading viewport configurations."]
- unexpected_lines = [
- # "Trace::Assert",
- # "Trace::Error",
- "Traceback (most recent call last):",
- ]
hydra.launch_and_validate_results(
request,
@@ -243,7 +241,7 @@ class TestMaterialEditor(object):
run_python="--runpython",
timeout=60,
expected_lines=expected_lines,
- unexpected_lines=unexpected_lines,
+ unexpected_lines=[],
halt_on_unexpected=False,
null_renderer=False,
cfg_args=[cfg_args],
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU_Optimized.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU_Optimized.py
new file mode 100644
index 0000000000..ef572d6e5c
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU_Optimized.py
@@ -0,0 +1,43 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+import os
+
+import pytest
+
+import ly_test_tools.environment.file_system as file_system
+from ly_test_tools.o3de.editor_test import EditorSharedTest, EditorTestSuite
+from ly_test_tools.image.screenshot_compare_qssim import qssim as compare_screenshots
+from .atom_utils.atom_component_helper import create_screenshots_archive, golden_images_directory
+
+DEFAULT_SUBFOLDER_PATH = 'user/PythonTests/Automated/Screenshots'
+
+
+@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.")
+@pytest.mark.parametrize("project", ["AutomatedTesting"])
+@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
+class TestAutomation(EditorTestSuite):
+ # Remove -autotest_mode from global_extra_cmdline_args since we need rendering for these tests.
+ global_extra_cmdline_args = ["-BatchMode"] # Default is ["-BatchMode", "-autotest_mode"]
+
+ class AtomGPU_BasicLevelSetup_SetsUpLevel(EditorSharedTest):
+ use_null_renderer = False # Default is True
+ screenshot_name = "AtomBasicLevelSetup.ppm"
+ test_screenshots = [] # Gets set by setup()
+ screenshot_directory = "" # Gets set by setup()
+
+ # Clear existing test screenshots before starting test.
+ def setup(self, workspace):
+ screenshot_directory = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH)
+ test_screenshots = [os.path.join(screenshot_directory, self.screenshot_name)]
+ file_system.delete(test_screenshots, True, True)
+
+ from Atom.tests import hydra_AtomGPU_BasicLevelSetup as test_module
+
+ golden_images = [os.path.join(golden_images_directory(), screenshot_name)]
+ for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images):
+ compare_screenshots(test_screenshot, golden_screenshot)
+ create_screenshots_archive(screenshot_directory)
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py
index 47b2204d56..ec3d76758c 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py
@@ -14,33 +14,54 @@ from ly_test_tools.o3de.editor_test import EditorSharedTest, EditorTestSuite
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
class TestAutomation(EditorTestSuite):
+ @pytest.mark.test_case_id("C32078118")
class AtomEditorComponents_DecalAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_DecalAdded as test_module
+ @pytest.mark.test_case_id("C32078119")
class AtomEditorComponents_DepthOfFieldAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_DepthOfFieldAdded as test_module
+ @pytest.mark.test_case_id("C32078120")
class AtomEditorComponents_DirectionalLightAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_DirectionalLightAdded as test_module
+ @pytest.mark.test_case_id("C32078121")
class AtomEditorComponents_ExposureControlAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_ExposureControlAdded as test_module
+ @pytest.mark.test_case_id("C32078115")
class AtomEditorComponents_GlobalSkylightIBLAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_GlobalSkylightIBLAdded as test_module
+ @pytest.mark.test_case_id("C32078125")
class AtomEditorComponents_PhysicalSkyAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_PhysicalSkyAdded as test_module
+ @pytest.mark.test_case_id("C32078131")
class AtomEditorComponents_PostFXRadiusWeightModifierAdded(EditorSharedTest):
from Atom.tests import (
hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded as test_module)
+ @pytest.mark.test_case_id("C32078117")
class AtomEditorComponents_LightAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_LightAdded as test_module
+ @pytest.mark.test_case_id("C36525660")
class AtomEditorComponents_DisplayMapperAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_DisplayMapperAdded as test_module
+ @pytest.mark.test_case_id("C32078128")
+ class AtomEditorComponents_ReflectionProbeAdded(EditorSharedTest):
+ from Atom.tests import hydra_AtomEditorComponents_ReflectionProbeAdded as test_module
+
+ @pytest.mark.test_case_id("C32078124")
+ class AtomEditorComponents_MeshAdded(EditorSharedTest):
+ from Atom.tests import hydra_AtomEditorComponents_MeshAdded as test_module
+
+ @pytest.mark.test_case_id("C32078123")
+ class AtomEditorComponents_MaterialAdded(EditorSharedTest):
+ from Atom.tests import hydra_AtomEditorComponents_MaterialAdded as test_module
+
class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest):
from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py
index 05401c0059..79caf26784 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py
@@ -3,12 +3,17 @@ Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
-
-Sandbox suite tests for the Atom renderer.
"""
+import logging
+import os
import pytest
+import editor_python_test_tools.hydra_test_utils as hydra
+
+logger = logging.getLogger(__name__)
+TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "tests")
+
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@@ -18,3 +23,49 @@ class TestAtomEditorComponentsSandbox(object):
# It requires at least one test
def test_Dummy(self, request, editor, level, workspace, project, launcher_platform):
pass
+
+ @pytest.mark.parametrize("project", ["AutomatedTesting"])
+ @pytest.mark.parametrize("launcher_platform", ['windows_editor'])
+ @pytest.mark.parametrize("level", ["auto_test"])
+ class TestAtomEditorComponentsMain(object):
+ """Holds tests for Atom components."""
+
+ def test_AtomEditorComponents_ReflectionProbeAddedToEntity(
+ self, request, editor, level, workspace, project, launcher_platform):
+ """
+ Please review the hydra script run by this test for more specific test info.
+ Tests the following Atom components and verifies all "expected_lines" appear in Editor.log:
+ 1. Reflection Probe
+ """
+ cfg_args = [level]
+
+ expected_lines = [
+ # Reflection Probe Component
+ "Reflection Probe Entity successfully created",
+ "Reflection Probe_test: Component added to the entity: True",
+ "Reflection Probe_test: Component removed after UNDO: True",
+ "Reflection Probe_test: Component added after REDO: True",
+ "Reflection Probe_test: Entered game mode: True",
+ "Reflection Probe_test: Exit game mode: True",
+ "Reflection Probe_test: Entity disabled initially: True",
+ "Reflection Probe_test: Entity enabled after adding required components: True",
+ "Reflection Probe_test: Cubemap is generated: True",
+ "Reflection Probe_test: Entity is hidden: True",
+ "Reflection Probe_test: Entity is shown: True",
+ "Reflection Probe_test: Entity deleted: True",
+ "Reflection Probe_test: UNDO entity deletion works: True",
+ "Reflection Probe_test: REDO entity deletion works: True",
+ ]
+
+ hydra.launch_and_validate_results(
+ request,
+ TEST_DIRECTORY,
+ editor,
+ "hydra_AtomEditorComponents_AddedToEntity.py",
+ timeout=120,
+ expected_lines=expected_lines,
+ unexpected_lines=[],
+ halt_on_unexpected=True,
+ null_renderer=True,
+ cfg_args=cfg_args,
+ )
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py
index 58b72ef01a..821e0acfdb 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py
@@ -3,13 +3,54 @@ Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright
SPDX-License-Identifier: Apache-2.0 OR MIT
-File to assist with common hydra component functions used across various Atom tests.
"""
+import datetime
import os
+import zipfile
-from editor_python_test_tools.editor_test_helper import EditorTestHelper
-helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper")
+def create_screenshots_archive(screenshot_path):
+ """
+ Creates a new zip file archive at archive_path containing all files listed within archive_path.
+ :param screenshot_path: location containing the files to archive, the zip archive file will also be saved here.
+ :return: None, but creates a new zip file archive inside path containing all of the files inside archive_path.
+ """
+ files_to_archive = []
+
+ # Search for .png and .ppm files to add to the zip archive file.
+ for (folder_name, sub_folders, file_names) in os.walk(screenshot_path):
+ for file_name in file_names:
+ if file_name.endswith(".png") or file_name.endswith(".ppm"):
+ file_path = os.path.join(folder_name, file_name)
+ files_to_archive.append(file_path)
+
+ # Setup variables for naming the zip archive file.
+ timestamp = datetime.datetime.now().timestamp()
+ formatted_timestamp = datetime.datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d_%H-%M-%S")
+ screenshots_file = os.path.join(screenshot_path, f'screenshots_{formatted_timestamp}.zip')
+
+ # Write all of the valid .png and .ppm files to the archive file.
+ with zipfile.ZipFile(screenshots_file, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zip_archive:
+ for file_path in files_to_archive:
+ file_name = os.path.basename(file_path)
+ zip_archive.write(file_path, file_name)
+
+
+def golden_images_directory():
+ """
+ Uses this file location to return the valid location for golden image files.
+ :return: The path to the golden_images directory, but raises an IOError if the golden_images directory is missing.
+ """
+ current_file_directory = os.path.join(os.path.dirname(__file__))
+ golden_images_dir = os.path.join(current_file_directory, '..', 'golden_images')
+
+ if not os.path.exists(golden_images_dir):
+ raise IOError(
+ f'golden_images" directory was not found at path "{golden_images_dir}"'
+ f'Please add a "golden_images" directory inside: "{current_file_directory}"'
+ )
+
+ return golden_images_dir
def create_basic_atom_level(level_name):
@@ -31,6 +72,9 @@ def create_basic_atom_level(level_name):
import azlmbr.object
import editor_python_test_tools.hydra_editor_utils as hydra
+ from editor_python_test_tools.editor_test_helper import EditorTestHelper
+
+ helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper")
# Create a new level.
new_level_name = level_name
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/material_editor_utils.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/material_editor_utils.py
index ef0a592df0..b21c74de19 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/material_editor_utils.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/material_editor_utils.py
@@ -211,7 +211,7 @@ class Timeout:
return time.time() > self.die_after
-screenshotsFolder = os.path.join(azlmbr.paths.devroot, "AtomTest", "Cache" "pc", "Screenshots")
+screenshotsFolder = os.path.join(azlmbr.paths.products, "Screenshots")
class ScreenshotHelper:
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_AddedToEntity.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_AddedToEntity.py
index 602e7564b3..bbc8463152 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_AddedToEntity.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_AddedToEntity.py
@@ -17,7 +17,7 @@ import azlmbr.legacy.general as general
import azlmbr.editor as editor
import azlmbr.render as render
-sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
+sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import TestHelper
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_LightComponent.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_LightComponent.py
index 751f425916..7ecdc6859b 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_LightComponent.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_LightComponent.py
@@ -14,7 +14,7 @@ import azlmbr.math as math
import azlmbr.paths
import azlmbr.legacy.general as general
-sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests"))
+sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
import editor_python_test_tools.hydra_editor_utils as hydra
from Atom.atom_utils.atom_constants import LIGHT_TYPES
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MaterialAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MaterialAdded.py
new file mode 100644
index 0000000000..32cd5471f2
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MaterialAdded.py
@@ -0,0 +1,205 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+class Tests:
+ creation_undo = (
+ "UNDO Entity creation success",
+ "UNDO Entity creation failed")
+ creation_redo = (
+ "REDO Entity creation success",
+ "REDO Entity creation failed")
+ material_creation = (
+ "Material Entity successfully created",
+ "Material Entity failed to be created")
+ material_component = (
+ "Entity has a Material component",
+ "Entity failed to find Material component")
+ material_disabled = (
+ "Material component disabled",
+ "Material component was not disabled.")
+ actor_component = (
+ "Entity has an Actor component",
+ "Entity did not have an Actor component")
+ actor_undo = (
+ "Entity Actor component gone",
+ "Entity Actor component add failed to undo")
+ mesh_component = (
+ "Entity has a Mesh component",
+ "Entity did not have a Mesh component")
+ material_enabled = (
+ "Material component enabled",
+ "Material component was not enabled.")
+ enter_game_mode = (
+ "Entered game mode",
+ "Failed to enter game mode")
+ exit_game_mode = (
+ "Exited game mode",
+ "Couldn't exit game mode")
+ is_visible = (
+ "Entity is visible",
+ "Entity was not visible")
+ is_hidden = (
+ "Entity is hidden",
+ "Entity was not hidden")
+ entity_deleted = (
+ "Entity deleted",
+ "Entity was not deleted")
+ deletion_undo = (
+ "UNDO deletion success",
+ "UNDO deletion failed")
+ deletion_redo = (
+ "REDO deletion success",
+ "REDO deletion failed")
+
+
+def AtomEditorComponents_Material_AddedToEntity():
+ """
+ Summary:
+ Tests the Material component can be added to an entity and has the expected functionality.
+
+ Test setup:
+ - Wait for Editor idle loop.
+ - Open the "Base" level.
+
+ Expected Behavior:
+ The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
+ Creation and deletion undo/redo should also work.
+
+ Test Steps:
+ 1) Create a Material entity with no components.
+ 2) Add a Material component to Material entity.
+ 3) UNDO the entity creation and component addition.
+ 4) REDO the entity creation and component addition.
+ 5) Verify Material component not enabled.
+ 6) Add Actor component since it is required by the Material component.
+ 7) Verify Material component is enabled.
+ 8) UNDO add Actor component
+ 9) Verify Material component not enabled.
+ 10) Add Mesh component since it is required by the Material component.
+ 11) Verify Material component is enabled.
+ 12) Enter/Exit game mode.
+ 13) Test IsHidden.
+ 14) Test IsVisible.
+ 15) Delete Material entity.
+ 16) UNDO deletion.
+ 17) REDO deletion.
+ 18) Look for errors.
+
+ :return: None
+ """
+
+ import azlmbr.legacy.general as general
+
+ from editor_python_test_tools.editor_entity_utils import EditorEntity
+ from editor_python_test_tools.utils import Report, Tracer, TestHelper
+
+ with Tracer() as error_tracer:
+ # Test setup begins.
+ # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
+ TestHelper.init_idle()
+ TestHelper.open_level("", "Base")
+
+ # Test steps begin.
+ # 1. Create a Material entity with no components.
+ material_name = "Material"
+ material_entity = EditorEntity.create_editor_entity(material_name)
+ Report.critical_result(Tests.material_creation, material_entity.exists())
+
+ # 2. Add a Material component to Material entity.
+ material_component = material_entity.add_component(material_name)
+ Report.critical_result(
+ Tests.material_component,
+ material_entity.has_component(material_name))
+
+ # 3. UNDO the entity creation and component addition.
+ # -> UNDO component addition.
+ general.undo()
+ # -> UNDO naming entity.
+ general.undo()
+ # -> UNDO selecting entity.
+ general.undo()
+ # -> UNDO entity creation.
+ general.undo()
+ general.idle_wait_frames(1)
+ Report.result(Tests.creation_undo, not material_entity.exists())
+
+ # 4. REDO the entity creation and component addition.
+ # -> REDO entity creation.
+ general.redo()
+ # -> REDO selecting entity.
+ general.redo()
+ # -> REDO naming entity.
+ general.redo()
+ # -> REDO component addition.
+ general.redo()
+ general.idle_wait_frames(1)
+ Report.result(Tests.creation_redo, material_entity.exists())
+
+ # 5. Verify Material component not enabled.
+ Report.result(Tests.material_disabled, not material_component.is_enabled())
+
+ # 6. Add Actor component since it is required by the Material component.
+ actor_name = "Actor"
+ material_entity.add_component(actor_name)
+ Report.result(Tests.actor_component, material_entity.has_component(actor_name))
+
+ # 7. Verify Material component is enabled.
+ Report.result(Tests.material_enabled, material_component.is_enabled())
+
+ # 8. UNDO component addition.
+ general.undo()
+ general.idle_wait_frames(1)
+ Report.result(Tests.actor_undo, not material_entity.has_component(actor_name))
+
+ # 9. Verify Material component not enabled.
+ Report.result(Tests.material_disabled, not material_component.is_enabled())
+
+ # 10. Add Mesh component since it is required by the Material component.
+ mesh_name = "Mesh"
+ material_entity.add_component(mesh_name)
+ Report.result(Tests.mesh_component, material_entity.has_component(mesh_name))
+
+ # 11. Verify Material component is enabled.
+ Report.result(Tests.material_enabled, material_component.is_enabled())
+
+ # 12. Enter/Exit game mode.
+ TestHelper.enter_game_mode(Tests.enter_game_mode)
+ general.idle_wait_frames(1)
+ TestHelper.exit_game_mode(Tests.exit_game_mode)
+
+ # 13. Test IsHidden.
+ material_entity.set_visibility_state(False)
+ Report.result(Tests.is_hidden, material_entity.is_hidden() is True)
+
+ # 14. Test IsVisible.
+ material_entity.set_visibility_state(True)
+ general.idle_wait_frames(1)
+ Report.result(Tests.is_visible, material_entity.is_visible() is True)
+
+ # 15. Delete Material entity.
+ material_entity.delete()
+ Report.result(Tests.entity_deleted, not material_entity.exists())
+
+ # 16. UNDO deletion.
+ general.undo()
+ Report.result(Tests.deletion_undo, material_entity.exists())
+
+ # 17. REDO deletion.
+ general.redo()
+ Report.result(Tests.deletion_redo, not material_entity.exists())
+
+ # 18. Look for errors or asserts.
+ TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
+ for error_info in error_tracer.errors:
+ Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
+ for assert_info in error_tracer.asserts:
+ Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
+
+
+if __name__ == "__main__":
+ from editor_python_test_tools.utils import Report
+ Report.start_test(AtomEditorComponents_Material_AddedToEntity)
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MeshAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MeshAdded.py
new file mode 100644
index 0000000000..fbf5c987d1
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MeshAdded.py
@@ -0,0 +1,171 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+class Tests:
+ creation_undo = (
+ "UNDO Entity creation success",
+ "UNDO Entity creation failed")
+ creation_redo = (
+ "REDO Entity creation success",
+ "REDO Entity creation failed")
+ mesh_entity_creation = (
+ "Mesh Entity successfully created",
+ "Mesh Entity failed to be created")
+ mesh_component_added = (
+ "Entity has a Mesh component",
+ "Entity failed to find Mesh component")
+ mesh_asset_specified = (
+ "Mesh asset set",
+ "Mesh asset not set")
+ enter_game_mode = (
+ "Entered game mode",
+ "Failed to enter game mode")
+ exit_game_mode = (
+ "Exited game mode",
+ "Couldn't exit game mode")
+ is_visible = (
+ "Entity is visible",
+ "Entity was not visible")
+ is_hidden = (
+ "Entity is hidden",
+ "Entity was not hidden")
+ entity_deleted = (
+ "Entity deleted",
+ "Entity was not deleted")
+ deletion_undo = (
+ "UNDO deletion success",
+ "UNDO deletion failed")
+ deletion_redo = (
+ "REDO deletion success",
+ "REDO deletion failed")
+
+
+def AtomEditorComponents_Mesh_AddedToEntity():
+ """
+ Summary:
+ Tests the Mesh component can be added to an entity and has the expected functionality.
+
+ Test setup:
+ - Wait for Editor idle loop.
+ - Open the "Base" level.
+
+ Expected Behavior:
+ The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
+ Creation and deletion undo/redo should also work.
+
+ Test Steps:
+ 1) Create a Mesh entity with no components.
+ 2) Add a Mesh component to Mesh entity.
+ 3) UNDO the entity creation and component addition.
+ 4) REDO the entity creation and component addition.
+ 5) Specify the Mesh component asset
+ 6) Enter/Exit game mode.
+ 7) Test IsHidden.
+ 8) Test IsVisible.
+ 9) Delete Mesh entity.
+ 10) UNDO deletion.
+ 11) REDO deletion.
+ 12) Look for errors.
+
+ :return: None
+ """
+
+ import os
+
+ import azlmbr.legacy.general as general
+
+ from editor_python_test_tools.asset_utils import Asset
+ from editor_python_test_tools.editor_entity_utils import EditorEntity
+ from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper
+
+ with Tracer() as error_tracer:
+ # Test setup begins.
+ # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
+ helper.init_idle()
+ helper.open_level("", "Base")
+
+ # Test steps begin.
+ # 1. Create a Mesh entity with no components.
+ mesh_name = "Mesh"
+ mesh_entity = EditorEntity.create_editor_entity(mesh_name)
+ Report.critical_result(Tests.mesh_entity_creation, mesh_entity.exists())
+
+ # 2. Add a Mesh component to Mesh entity.
+ mesh_component = mesh_entity.add_component(mesh_name)
+ Report.critical_result(
+ Tests.mesh_component_added,
+ mesh_entity.has_component(mesh_name))
+
+ # 3. UNDO the entity creation and component addition.
+ # -> UNDO component addition.
+ general.undo()
+ # -> UNDO naming entity.
+ general.undo()
+ # -> UNDO selecting entity.
+ general.undo()
+ # -> UNDO entity creation.
+ general.undo()
+ general.idle_wait_frames(1)
+ Report.result(Tests.creation_undo, not mesh_entity.exists())
+
+ # 4. REDO the entity creation and component addition.
+ # -> REDO entity creation.
+ general.redo()
+ # -> REDO selecting entity.
+ general.redo()
+ # -> REDO naming entity.
+ general.redo()
+ # -> REDO component addition.
+ general.redo()
+ general.idle_wait_frames(1)
+ Report.result(Tests.creation_redo, mesh_entity.exists())
+
+ # 5. Set Mesh component asset property
+ mesh_property_asset = 'Controller|Configuration|Mesh Asset'
+ model_path = os.path.join('Objects', 'shaderball', 'shaderball_default_1m.azmodel')
+ model = Asset.find_asset_by_path(model_path)
+ mesh_component.set_component_property_value(mesh_property_asset, model.id)
+ Report.result(Tests.mesh_asset_specified,
+ mesh_component.get_component_property_value(mesh_property_asset) == model.id)
+
+ # 6. Enter/Exit game mode.
+ helper.enter_game_mode(Tests.enter_game_mode)
+ general.idle_wait_frames(1)
+ helper.exit_game_mode(Tests.exit_game_mode)
+
+ # 7. Test IsHidden.
+ mesh_entity.set_visibility_state(False)
+ Report.result(Tests.is_hidden, mesh_entity.is_hidden() is True)
+
+ # 8. Test IsVisible.
+ mesh_entity.set_visibility_state(True)
+ general.idle_wait_frames(1)
+ Report.result(Tests.is_visible, mesh_entity.is_visible() is True)
+
+ # 9. Delete Mesh entity.
+ mesh_entity.delete()
+ Report.result(Tests.entity_deleted, not mesh_entity.exists())
+
+ # 10. UNDO deletion.
+ general.undo()
+ Report.result(Tests.deletion_undo, mesh_entity.exists())
+
+ # 11. REDO deletion.
+ general.redo()
+ Report.result(Tests.deletion_redo, not mesh_entity.exists())
+
+ # 12. Look for errors or asserts.
+ helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
+ for error_info in error_tracer.errors:
+ Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
+ for assert_info in error_tracer.asserts:
+ Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
+
+
+if __name__ == "__main__":
+ from editor_python_test_tools.utils import Report
+ Report.start_test(AtomEditorComponents_Mesh_AddedToEntity)
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_ReflectionProbeAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_ReflectionProbeAdded.py
new file mode 100644
index 0000000000..9b13eb2c7e
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_ReflectionProbeAdded.py
@@ -0,0 +1,194 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+class Tests:
+ creation_undo = (
+ "UNDO Entity creation success",
+ "UNDO Entity creation failed")
+ creation_redo = (
+ "REDO Entity creation success",
+ "REDO Entity creation failed")
+ reflection_probe_creation = (
+ "Reflection Probe Entity successfully created",
+ "Reflection Probe Entity failed to be created")
+ reflection_probe_component = (
+ "Entity has a Reflection Probe component",
+ "Entity failed to find Reflection Probe component")
+ reflection_probe_disabled = (
+ "Reflection Probe component disabled",
+ "Reflection Probe component was not disabled.")
+ reflection_map_generated = (
+ "Reflection Probe cubemap generated",
+ "Reflection Probe cubemap not generated")
+ box_shape_component = (
+ "Entity has a Box Shape component",
+ "Entity did not have a Box Shape component")
+ reflection_probe_enabled = (
+ "Reflection Probe component enabled",
+ "Reflection Probe component was not enabled.")
+ enter_game_mode = (
+ "Entered game mode",
+ "Failed to enter game mode")
+ exit_game_mode = (
+ "Exited game mode",
+ "Couldn't exit game mode")
+ is_visible = (
+ "Entity is visible",
+ "Entity was not visible")
+ is_hidden = (
+ "Entity is hidden",
+ "Entity was not hidden")
+ entity_deleted = (
+ "Entity deleted",
+ "Entity was not deleted")
+ deletion_undo = (
+ "UNDO deletion success",
+ "UNDO deletion failed")
+ deletion_redo = (
+ "REDO deletion success",
+ "REDO deletion failed")
+
+
+def AtomEditorComponents_ReflectionProbe_AddedToEntity():
+ """
+ Summary:
+ Tests the Reflection Probe component can be added to an entity and has the expected functionality.
+
+ Test setup:
+ - Wait for Editor idle loop.
+ - Open the "Base" level.
+
+ Expected Behavior:
+ The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
+ Creation and deletion undo/redo should also work.
+
+ Test Steps:
+ 1) Create a Reflection Probe entity with no components.
+ 2) Add a Reflection Probe component to Reflection Probe entity.
+ 3) UNDO the entity creation and component addition.
+ 4) REDO the entity creation and component addition.
+ 5) Verify Reflection Probe component not enabled.
+ 6) Add Shape component since it is required by the Reflection Probe component.
+ 7) Verify Reflection Probe component is enabled.
+ 8) Enter/Exit game mode.
+ 9) Test IsHidden.
+ 10) Test IsVisible.
+ 11) Verify cubemap generation
+ 12) Delete Reflection Probe entity.
+ 13) UNDO deletion.
+ 14) REDO deletion.
+ 15) Look for errors.
+
+ :return: None
+ """
+
+ import azlmbr.legacy.general as general
+ import azlmbr.math as math
+ import azlmbr.render as render
+
+ from editor_python_test_tools.editor_entity_utils import EditorEntity
+ from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper
+
+ with Tracer() as error_tracer:
+ # Test setup begins.
+ # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
+ helper.init_idle()
+ helper.open_level("", "Base")
+
+ # Test steps begin.
+ # 1. Create a Reflection Probe entity with no components.
+ reflection_probe_name = "Reflection Probe"
+ reflection_probe_entity = EditorEntity.create_editor_entity_at(
+ math.Vector3(512.0, 512.0, 34.0), reflection_probe_name)
+ Report.critical_result(Tests.reflection_probe_creation, reflection_probe_entity.exists())
+
+ # 2. Add a Reflection Probe component to Reflection Probe entity.
+ reflection_probe_component = reflection_probe_entity.add_component(reflection_probe_name)
+ Report.critical_result(
+ Tests.reflection_probe_component,
+ reflection_probe_entity.has_component(reflection_probe_name))
+
+ # 3. UNDO the entity creation and component addition.
+ # -> UNDO component addition.
+ general.undo()
+ # -> UNDO naming entity.
+ general.undo()
+ # -> UNDO selecting entity.
+ general.undo()
+ # -> UNDO entity creation.
+ general.undo()
+ general.idle_wait_frames(1)
+ Report.result(Tests.creation_undo, not reflection_probe_entity.exists())
+
+ # 4. REDO the entity creation and component addition.
+ # -> REDO entity creation.
+ general.redo()
+ # -> REDO selecting entity.
+ general.redo()
+ # -> REDO naming entity.
+ general.redo()
+ # -> REDO component addition.
+ general.redo()
+ general.idle_wait_frames(1)
+ Report.result(Tests.creation_redo, reflection_probe_entity.exists())
+
+ # 5. Verify Reflection Probe component not enabled.
+ Report.result(Tests.reflection_probe_disabled, not reflection_probe_component.is_enabled())
+
+ # 6. Add Box Shape component since it is required by the Reflection Probe component.
+ box_shape = "Box Shape"
+ reflection_probe_entity.add_component(box_shape)
+ Report.result(Tests.box_shape_component, reflection_probe_entity.has_component(box_shape))
+
+ # 7. Verify Reflection Probe component is enabled.
+ Report.result(Tests.reflection_probe_enabled, reflection_probe_component.is_enabled())
+
+ # 8. Enter/Exit game mode.
+ helper.enter_game_mode(Tests.enter_game_mode)
+ general.idle_wait_frames(1)
+ helper.exit_game_mode(Tests.exit_game_mode)
+
+ # 9. Test IsHidden.
+ reflection_probe_entity.set_visibility_state(False)
+ Report.result(Tests.is_hidden, reflection_probe_entity.is_hidden() is True)
+
+ # 10. Test IsVisible.
+ reflection_probe_entity.set_visibility_state(True)
+ general.idle_wait_frames(1)
+ Report.result(Tests.is_visible, reflection_probe_entity.is_visible() is True)
+
+ # 11. Verify cubemap generation
+ render.EditorReflectionProbeBus(azlmbr.bus.Event, "BakeReflectionProbe", reflection_probe_entity.id)
+ Report.result(
+ Tests.reflection_map_generated,
+ helper.wait_for_condition(
+ lambda: reflection_probe_component.get_component_property_value("Cubemap|Baked Cubemap Path") != "",
+ 20.0))
+
+ # 12. Delete Reflection Probe entity.
+ reflection_probe_entity.delete()
+ Report.result(Tests.entity_deleted, not reflection_probe_entity.exists())
+
+ # 13. UNDO deletion.
+ general.undo()
+ Report.result(Tests.deletion_undo, reflection_probe_entity.exists())
+
+ # 14. REDO deletion.
+ general.redo()
+ Report.result(Tests.deletion_redo, not reflection_probe_entity.exists())
+
+ # 15. Look for errors or asserts.
+ helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
+ for error_info in error_tracer.errors:
+ Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
+ for assert_info in error_tracer.asserts:
+ Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
+
+
+if __name__ == "__main__":
+ from editor_python_test_tools.utils import Report
+ Report.start_test(AtomEditorComponents_ReflectionProbe_AddedToEntity)
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomGPU_BasicLevelSetup.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomGPU_BasicLevelSetup.py
new file mode 100644
index 0000000000..92c555127a
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomGPU_BasicLevelSetup.py
@@ -0,0 +1,292 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+
+# fmt: off
+class Tests :
+ camera_component_added = ("Camera component was added", "Camera component wasn't added")
+ camera_fov_set = ("Camera component FOV property set", "Camera component FOV property wasn't set")
+ directional_light_component_added = ("Directional Light component added", "Directional Light component wasn't added")
+ enter_game_mode = ("Entered game mode", "Failed to enter game mode")
+ exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
+ global_skylight_component_added = ("Global Skylight (IBL) component added", "Global Skylight (IBL) component wasn't added")
+ global_skylight_diffuse_image_set = ("Global Skylight Diffuse Image property set", "Global Skylight Diffuse Image property wasn't set")
+ global_skylight_specular_image_set = ("Global Skylight Specular Image property set", "Global Skylight Specular Image property wasn't set")
+ ground_plane_material_asset_set = ("Ground Plane Material Asset was set", "Ground Plane Material Asset wasn't set")
+ ground_plane_material_component_added = ("Ground Plane Material component added", "Ground Plane Material component wasn't added")
+ ground_plane_mesh_asset_set = ("Ground Plane Mesh Asset property was set", "Ground Plane Mesh Asset property wasn't set")
+ hdri_skybox_component_added = ("HDRi Skybox component added", "HDRi Skybox component wasn't added")
+ hdri_skybox_cubemap_texture_set = ("HDRi Skybox Cubemap Texture property set", "HDRi Skybox Cubemap Texture property wasn't set")
+ mesh_component_added = ("Mesh component added", "Mesh component wasn't added")
+ no_assert_occurred = ("No asserts detected", "Asserts were detected")
+ no_error_occurred = ("No errors detected", "Errors were detected")
+ secondary_grid_spacing = ("Secondary Grid Spacing set", "Secondary Grid Spacing not set")
+ sphere_material_component_added = ("Sphere Material component added", "Sphere Material component wasn't added")
+ sphere_material_set = ("Sphere Material Asset was set", "Sphere Material Asset wasn't set")
+ sphere_mesh_asset_set = ("Sphere Mesh Asset was set", "Sphere Mesh Asset wasn't set")
+ viewport_set = ("Viewport set to correct size", "Viewport not set to correct size")
+# fmt: on
+
+
+def AtomGPU_BasicLevelSetup_SetsUpLevel():
+ """
+ Summary:
+ Sets up a level to match the AtomBasicLevelSetup.ppm golden image then takes a screenshot to verify the setup.
+
+ Test setup:
+ - Wait for Editor idle loop.
+ - Open the "Base" level.
+
+ Expected Behavior:
+ The scene can be setup for a basic level.
+ The test screenshot matches the appearance of the AtomBasicLevelSetup.ppm golden image.
+
+ Test Steps:
+ 1. Close error windows and display helpers then update the viewport size.
+ 2. Create Default Level Entity.
+ 3. Create Grid Entity as a child entity of the Default Level Entity.
+ 4. Add Grid component to Grid Entity and set Secondary Grid Spacing.
+ 5. Create Global Skylight (IBL) Entity as a child entity of the Default Level Entity.
+ 6. Add HDRi Skybox component to the Global Skylight (IBL) Entity.
+ 7. Add Global Skylight (IBL) component to the Global Skylight (IBL) Entity.
+ 8. Set the Cubemap Texture property of the HDRi Skybox component.
+ 9. Set the Diffuse Image property of the Global Skylight (IBL) component.
+ 10. Set the Specular Image property of the Global Skylight (IBL) component.
+ 11. Create a Ground Plane Entity with a Material component that is a child entity of the Default Level Entity.
+ 12. Set the Material Asset property of the Material component for the Ground Plane Entity.
+ 13. Add the Mesh component to the Ground Plane Entity and set the Mesh component Mesh Asset property.
+ 14. Create a Directional Light Entity as a child entity of the Default Level Entity.
+ 15. Add Directional Light component to Directional Light Entity and set entity rotation.
+ 16. Create a Sphere Entity as a child entity of the Default Level Entity then add a Material component.
+ 17. Set the Material Asset property of the Material component for the Sphere Entity.
+ 18. Add Mesh component to Sphere Entity and set the Mesh Asset property for the Mesh component.
+ 19. Create a Camera Entity as a child entity of the Default Level Entity then add a Camera component.
+ 20. Set the Camera Entity rotation value and set the Camera component Field of View value.
+ 21. Enter game mode.
+ 22. Take screenshot.
+ 23. Exit game mode.
+ 24. Look for errors.
+
+ :return: None
+ """
+
+ import os
+ from math import isclose
+
+ import azlmbr.asset as asset
+ import azlmbr.bus as bus
+ import azlmbr.legacy.general as general
+ import azlmbr.math as math
+ import azlmbr.paths
+
+ from editor_python_test_tools.editor_entity_utils import EditorEntity
+ from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper
+
+ from Atom.atom_utils.screenshot_utils import ScreenshotHelper
+
+ MATERIAL_COMPONENT_NAME = "Material"
+ MESH_COMPONENT_NAME = "Mesh"
+ SCREENSHOT_NAME = "AtomBasicLevelSetup"
+ SCREEN_WIDTH = 1280
+ SCREEN_HEIGHT = 720
+ DEGREE_RADIAN_FACTOR = 0.0174533
+
+ def initial_viewport_setup(screen_width, screen_height):
+ general.set_viewport_size(screen_width, screen_height)
+ general.update_viewport()
+ result = isclose(
+ a=general.get_viewport_size().x, b=SCREEN_WIDTH, rel_tol=0.1) and isclose(
+ a=general.get_viewport_size().y, b=SCREEN_HEIGHT, rel_tol=0.1)
+
+ return result
+
+ with Tracer() as error_tracer:
+ # Test setup begins.
+ # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
+ helper.init_idle()
+ helper.open_level("", "Base")
+
+ # Test steps begin.
+ # 1. Close error windows and display helpers then update the viewport size.
+ helper.close_error_windows()
+ helper.close_display_helpers()
+ general.update_viewport()
+ Report.critical_result(Tests.viewport_set, initial_viewport_setup(SCREEN_WIDTH, SCREEN_HEIGHT))
+
+ # 2. Create Default Level Entity.
+ default_level_entity_name = "Default Level"
+ default_level_entity = EditorEntity.create_editor_entity_at(
+ math.Vector3(0.0, 0.0, 0.0), default_level_entity_name)
+
+ # 3. Create Grid Entity as a child entity of the Default Level Entity.
+ grid_name = "Grid"
+ grid_entity = EditorEntity.create_editor_entity(grid_name, default_level_entity.id)
+
+ # 4. Add Grid component to Grid Entity and set Secondary Grid Spacing.
+ grid_component = grid_entity.add_component(grid_name)
+ secondary_grid_spacing_property = "Controller|Configuration|Secondary Grid Spacing"
+ secondary_grid_spacing_value = 1.0
+ grid_component.set_component_property_value(secondary_grid_spacing_property, secondary_grid_spacing_value)
+ secondary_grid_spacing_set = grid_component.get_component_property_value(
+ secondary_grid_spacing_property) == secondary_grid_spacing_value
+ Report.result(Tests.secondary_grid_spacing, secondary_grid_spacing_set)
+
+ # 5. Create Global Skylight (IBL) Entity as a child entity of the Default Level Entity.
+ global_skylight_name = "Global Skylight (IBL)"
+ global_skylight_entity = EditorEntity.create_editor_entity(global_skylight_name, default_level_entity.id)
+
+ # 6. Add HDRi Skybox component to the Global Skylight (IBL) Entity.
+ hdri_skybox_name = "HDRi Skybox"
+ hdri_skybox_component = global_skylight_entity.add_component(hdri_skybox_name)
+ Report.result(Tests.hdri_skybox_component_added, global_skylight_entity.has_component(hdri_skybox_name))
+
+ # 7. Add Global Skylight (IBL) component to the Global Skylight (IBL) Entity.
+ global_skylight_component = global_skylight_entity.add_component(global_skylight_name)
+ Report.result(Tests.global_skylight_component_added, global_skylight_entity.has_component(global_skylight_name))
+
+ # 8. Set the Cubemap Texture property of the HDRi Skybox component.
+ global_skylight_image_asset_path = os.path.join(
+ "LightingPresets", "greenwich_park_02_4k_iblskyboxcm_iblspecular.exr.streamingimage")
+ global_skylight_image_asset = asset.AssetCatalogRequestBus(
+ bus.Broadcast, "GetAssetIdByPath", global_skylight_image_asset_path, math.Uuid(), False)
+ hdri_skybox_cubemap_texture_property = "Controller|Configuration|Cubemap Texture"
+ hdri_skybox_component.set_component_property_value(
+ hdri_skybox_cubemap_texture_property, global_skylight_image_asset)
+ Report.result(
+ Tests.hdri_skybox_cubemap_texture_set,
+ hdri_skybox_component.get_component_property_value(
+ hdri_skybox_cubemap_texture_property) == global_skylight_image_asset)
+
+ # 9. Set the Diffuse Image property of the Global Skylight (IBL) component.
+ # Re-use the same image that was used in the previous test step.
+ global_skylight_diffuse_image_property = "Controller|Configuration|Diffuse Image"
+ global_skylight_component.set_component_property_value(
+ global_skylight_diffuse_image_property, global_skylight_image_asset)
+ Report.result(
+ Tests.global_skylight_diffuse_image_set,
+ global_skylight_component.get_component_property_value(
+ global_skylight_diffuse_image_property) == global_skylight_image_asset)
+
+ # 10. Set the Specular Image property of the Global Skylight (IBL) component.
+ # Re-use the same image that was used in the previous test step.
+ global_skylight_specular_image_property = "Controller|Configuration|Specular Image"
+ global_skylight_component.set_component_property_value(
+ global_skylight_specular_image_property, global_skylight_image_asset)
+ global_skylight_specular_image_set = global_skylight_component.get_component_property_value(
+ global_skylight_specular_image_property)
+ Report.result(
+ Tests.global_skylight_specular_image_set, global_skylight_specular_image_set == global_skylight_image_asset)
+
+ # 11. Create a Ground Plane Entity with a Material component that is a child entity of the Default Level Entity.
+ ground_plane_name = "Ground Plane"
+ ground_plane_entity = EditorEntity.create_editor_entity(ground_plane_name, default_level_entity.id)
+ ground_plane_material_component = ground_plane_entity.add_component(MATERIAL_COMPONENT_NAME)
+ Report.result(
+ Tests.ground_plane_material_component_added, ground_plane_entity.has_component(MATERIAL_COMPONENT_NAME))
+
+ # 12. Set the Material Asset property of the Material component for the Ground Plane Entity.
+ ground_plane_entity.set_local_uniform_scale(32.0)
+ ground_plane_material_asset_path = os.path.join("Materials", "Presets", "PBR", "metal_chrome.azmaterial")
+ ground_plane_material_asset = asset.AssetCatalogRequestBus(
+ bus.Broadcast, "GetAssetIdByPath", ground_plane_material_asset_path, math.Uuid(), False)
+ ground_plane_material_asset_property = "Default Material|Material Asset"
+ ground_plane_material_component.set_component_property_value(
+ ground_plane_material_asset_property, ground_plane_material_asset)
+ Report.result(
+ Tests.ground_plane_material_asset_set,
+ ground_plane_material_component.get_component_property_value(
+ ground_plane_material_asset_property) == ground_plane_material_asset)
+
+ # 13. Add the Mesh component to the Ground Plane Entity and set the Mesh component Mesh Asset property.
+ ground_plane_mesh_component = ground_plane_entity.add_component(MESH_COMPONENT_NAME)
+ Report.result(Tests.mesh_component_added, ground_plane_entity.has_component(MESH_COMPONENT_NAME))
+ ground_plane_mesh_asset_path = os.path.join("Objects", "plane.azmodel")
+ ground_plane_mesh_asset = asset.AssetCatalogRequestBus(
+ bus.Broadcast, "GetAssetIdByPath", ground_plane_mesh_asset_path, math.Uuid(), False)
+ ground_plane_mesh_asset_property = "Controller|Configuration|Mesh Asset"
+ ground_plane_mesh_component.set_component_property_value(
+ ground_plane_mesh_asset_property, ground_plane_mesh_asset)
+ Report.result(
+ Tests.ground_plane_mesh_asset_set,
+ ground_plane_mesh_component.get_component_property_value(
+ ground_plane_mesh_asset_property) == ground_plane_mesh_asset)
+
+ # 14. Create a Directional Light Entity as a child entity of the Default Level Entity.
+ directional_light_name = "Directional Light"
+ directional_light_entity = EditorEntity.create_editor_entity_at(
+ math.Vector3(0.0, 0.0, 10.0), directional_light_name, default_level_entity.id)
+
+ # 15. Add Directional Light component to Directional Light Entity and set entity rotation.
+ directional_light_entity.add_component(directional_light_name)
+ directional_light_entity_rotation = math.Vector3(DEGREE_RADIAN_FACTOR * -90.0, 0.0, 0.0)
+ directional_light_entity.set_local_rotation(directional_light_entity_rotation)
+ Report.result(
+ Tests.directional_light_component_added, directional_light_entity.has_component(directional_light_name))
+
+ # 16. Create a Sphere Entity as a child entity of the Default Level Entity then add a Material component.
+ sphere_entity = EditorEntity.create_editor_entity_at(
+ math.Vector3(0.0, 0.0, 1.0), "Sphere", default_level_entity.id)
+ sphere_material_component = sphere_entity.add_component(MATERIAL_COMPONENT_NAME)
+ Report.result(Tests.sphere_material_component_added, sphere_entity.has_component(MATERIAL_COMPONENT_NAME))
+
+ # 17. Set the Material Asset property of the Material component for the Sphere Entity.
+ sphere_material_asset_path = os.path.join("Materials", "Presets", "PBR", "metal_brass_polished.azmaterial")
+ sphere_material_asset = asset.AssetCatalogRequestBus(
+ bus.Broadcast, "GetAssetIdByPath", sphere_material_asset_path, math.Uuid(), False)
+ sphere_material_asset_property = "Default Material|Material Asset"
+ sphere_material_component.set_component_property_value(sphere_material_asset_property, sphere_material_asset)
+ Report.result(Tests.sphere_material_set, sphere_material_component.get_component_property_value(
+ sphere_material_asset_property) == sphere_material_asset)
+
+ # 18. Add Mesh component to Sphere Entity and set the Mesh Asset property for the Mesh component.
+ sphere_mesh_component = sphere_entity.add_component(MESH_COMPONENT_NAME)
+ sphere_mesh_asset_path = os.path.join("Models", "sphere.azmodel")
+ sphere_mesh_asset = asset.AssetCatalogRequestBus(
+ bus.Broadcast, "GetAssetIdByPath", sphere_mesh_asset_path, math.Uuid(), False)
+ sphere_mesh_asset_property = "Controller|Configuration|Mesh Asset"
+ sphere_mesh_component.set_component_property_value(sphere_mesh_asset_property, sphere_mesh_asset)
+ Report.result(Tests.sphere_mesh_asset_set, sphere_mesh_component.get_component_property_value(
+ sphere_mesh_asset_property) == sphere_mesh_asset)
+
+ # 19. Create a Camera Entity as a child entity of the Default Level Entity then add a Camera component.
+ camera_name = "Camera"
+ camera_entity = EditorEntity.create_editor_entity_at(
+ math.Vector3(5.5, -12.0, 9.0), camera_name, default_level_entity.id)
+ camera_component = camera_entity.add_component(camera_name)
+ Report.result(Tests.camera_component_added, camera_entity.has_component(camera_name))
+
+ # 20. Set the Camera Entity rotation value and set the Camera component Field of View value.
+ camera_entity_rotation = math.Vector3(
+ DEGREE_RADIAN_FACTOR * -27.0, DEGREE_RADIAN_FACTOR * -12.0, DEGREE_RADIAN_FACTOR * 25.0)
+ camera_entity.set_local_rotation(camera_entity_rotation)
+ camera_fov_property = "Controller|Configuration|Field of view"
+ camera_fov_value = 60.0
+ camera_component.set_component_property_value(camera_fov_property, camera_fov_value)
+ azlmbr.camera.EditorCameraViewRequestBus(azlmbr.bus.Event, "ToggleCameraAsActiveView", camera_entity.id)
+ Report.result(Tests.camera_fov_set, camera_component.get_component_property_value(
+ camera_fov_property) == camera_fov_value)
+
+ # 21. Enter game mode.
+ helper.enter_game_mode(Tests.enter_game_mode)
+ helper.wait_for_condition(function=lambda: general.is_in_game_mode(), timeout_in_seconds=4.0)
+
+ # 22. Take screenshot.
+ ScreenshotHelper(general.idle_wait_frames).capture_screenshot_blocking(f"{SCREENSHOT_NAME}.ppm")
+
+ # 23. Exit game mode.
+ helper.exit_game_mode(Tests.exit_game_mode)
+ helper.wait_for_condition(function=lambda: not general.is_in_game_mode(), timeout_in_seconds=4.0)
+
+ # 24. Look for errors.
+ helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
+ Report.result(Tests.no_assert_occurred, not error_tracer.has_asserts)
+ Report.result(Tests.no_error_occurred, not error_tracer.has_errors)
+
+
+if __name__ == "__main__":
+ from editor_python_test_tools.utils import Report
+ Report.start_test(AtomGPU_BasicLevelSetup_SetsUpLevel)
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py
index 88a1ef4c7b..9f8f6c44b2 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py
@@ -16,7 +16,7 @@ import time
import azlmbr.math as math
import azlmbr.paths
-sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests"))
+sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
import Atom.atom_utils.material_editor_utils as material_editor
@@ -27,10 +27,10 @@ TEST_MATERIAL_1 = "001_DefaultWhite.material"
TEST_MATERIAL_2 = "002_BaseColorLerp.material"
TEST_MATERIAL_3 = "003_MetalMatte.material"
TEST_DATA_PATH = os.path.join(
- azlmbr.paths.devroot, "Gems", "Atom", "TestData", "TestData", "Materials", "StandardPbrTestCases"
+ azlmbr.paths.engroot, "Gems", "Atom", "TestData", "TestData", "Materials", "StandardPbrTestCases"
)
MATERIAL_TYPE_PATH = os.path.join(
- azlmbr.paths.devroot, "Gems", "Atom", "Feature", "Common", "Assets",
+ azlmbr.paths.engroot, "Gems", "Atom", "Feature", "Common", "Assets",
"Materials", "Types", "StandardPBR.materialtype",
)
CACHE_FILE_EXTENSION = ".azmaterial"
@@ -61,7 +61,7 @@ def run():
print(f"Material opened: {material_editor.is_open(document_id)}")
# Verify if the test material exists initially
- target_path = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL)
+ target_path = os.path.join(azlmbr.paths.projectroot, "Materials", NEW_MATERIAL)
print(f"Test asset doesn't exist initially: {not os.path.exists(target_path)}")
# 2) Test Case: Creating a New Material Using Existing One
@@ -109,10 +109,10 @@ def run():
# Assign new color to the material file and save the document as copy
expected_color_1 = math.Color(0.5, 0.5, 0.5, 1.0)
material_editor.set_property(document_id, property_name, expected_color_1)
- target_path_1 = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL_1)
+ target_path_1 = os.path.join(azlmbr.paths.projectroot, "Materials", NEW_MATERIAL_1)
cache_file_name_1 = os.path.splitext(NEW_MATERIAL_1) # Example output: ('test_material_1', '.material')
cache_file_1 = f"{cache_file_name_1[0]}{CACHE_FILE_EXTENSION}"
- target_path_1_cache = os.path.join(azlmbr.paths.devassets, "Cache", "pc", "materials", cache_file_1)
+ target_path_1_cache = os.path.join(azlmbr.paths.products, "materials", cache_file_1)
material_editor.save_document_as_copy(document_id, target_path_1)
material_editor.wait_for_condition(lambda: os.path.exists(target_path_1_cache), 4.0)
@@ -120,10 +120,10 @@ def run():
# Assign new color to the material file save the document as child
expected_color_2 = math.Color(0.75, 0.75, 0.75, 1.0)
material_editor.set_property(document_id, property_name, expected_color_2)
- target_path_2 = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL_2)
+ target_path_2 = os.path.join(azlmbr.paths.projectroot, "Materials", NEW_MATERIAL_2)
cache_file_name_2 = os.path.splitext(NEW_MATERIAL_1) # Example output: ('test_material_2', '.material')
cache_file_2 = f"{cache_file_name_2[0]}{CACHE_FILE_EXTENSION}"
- target_path_2_cache = os.path.join(azlmbr.paths.devassets, "Cache", "pc", "materials", cache_file_2)
+ target_path_2_cache = os.path.join(azlmbr.paths.products, "materials", cache_file_2)
material_editor.save_document_as_child(document_id, target_path_2)
material_editor.wait_for_condition(lambda: os.path.exists(target_path_2_cache), 4.0)
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py
index 4f7edeba75..92199bf196 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py
@@ -10,7 +10,7 @@ import sys
import azlmbr.legacy.general as general
-sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
+sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.editor_test_helper import EditorTestHelper
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py
index 62a122a723..ac28e67fa1 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py
@@ -17,7 +17,7 @@ import azlmbr.math as math
import azlmbr.paths
import azlmbr.editor as editor
-sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
+sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.editor_test_helper import EditorTestHelper
diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_LightComponent.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_LightComponent.py
index 4a3ae8c85d..1c3e6226c1 100644
--- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_LightComponent.py
+++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_LightComponent.py
@@ -14,7 +14,7 @@ import azlmbr.math as math
import azlmbr.paths
import azlmbr.legacy.general as general
-sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
+sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
import editor_python_test_tools.hydra_editor_utils as hydra
from Atom.atom_utils import atom_component_helper, atom_constants, screenshot_utils
diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorCommandLine_test.py b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorCommandLine_test.py
index 1d3ca11618..fcce6eab37 100755
--- a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorCommandLine_test.py
+++ b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorCommandLine_test.py
@@ -42,7 +42,6 @@ class TestEditorAutomation(object):
"editor command line arg bar",
"editor command line arg baz",
"editor engroot set",
- "editor devroot set",
"path resolved worked"
]
diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorCommandLine_test_case.py b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorCommandLine_test_case.py
index bd8791fad6..c6ae65612f 100755
--- a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorCommandLine_test_case.py
+++ b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorCommandLine_test_case.py
@@ -20,12 +20,6 @@ if (engroot is not None and len(engroot) is not 0):
print ('engroot is {}'.format(engroot))
print ('editor engroot set')
-# make sure the @devroot@ exists as a azlmbr.paths property
-devroot = azlmbr.paths.devroot
-if (devroot is not None and len(devroot) != 0):
- print ('devroot is {}'.format(devroot))
- print ('editor devroot set')
-
# resolving a basic path
path = azlmbr.paths.resolve_path('@engroot@/engineassets/texturemsg/defaultsolids.mtl')
if (len(path) != 0 and path.find('@engroot@') == -1):
diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorScripts/ComponentUpdateListProperty_test_case.py b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorScripts/ComponentUpdateListProperty_test_case.py
index 5b7f2f42c1..c5ca4de603 100644
--- a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorScripts/ComponentUpdateListProperty_test_case.py
+++ b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorScripts/ComponentUpdateListProperty_test_case.py
@@ -16,7 +16,7 @@ import azlmbr.entity as entity
import azlmbr.math as math
import azlmbr.paths
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
+sys.path.append(os.path.join(azlmbr.paths.projectroot, 'Gem', 'PythonTests'))
from automatedtesting_shared.editor_test_helper import EditorTestHelper
diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/LevelComponentCommands.cfg b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/LevelComponentCommands.cfg
index 3adc32d20a..ccc605cec9 100644
--- a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/LevelComponentCommands.cfg
+++ b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/LevelComponentCommands.cfg
@@ -1,2 +1,2 @@
# this file is copied to $/dev/editor_autoexec.cfg so the the Editor automation runs for this Hydra test
-pyRunFile @devroot@/Tests/hydra/LevelComponentCommands_test_case.py exit_when_done
\ No newline at end of file
+pyRunFile @engroot@/Tests/hydra/LevelComponentCommands_test_case.py exit_when_done
\ No newline at end of file
diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/ViewportTitleDlgCommands.cfg b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/ViewportTitleDlgCommands.cfg
index 6230dfe0fa..3cbd84c1b5 100644
--- a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/ViewportTitleDlgCommands.cfg
+++ b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/ViewportTitleDlgCommands.cfg
@@ -1,2 +1,2 @@
# this file is copied to $/dev/editor_autoexec.cfg so the the Editor automation runs for this Hydra test
-pyRunFile @devroot@/Tests/hydra/ViewportTitleDlgCommands_test_case.py
\ No newline at end of file
+pyRunFile @engroot@/Tests/hydra/ViewportTitleDlgCommands_test_case.py
\ No newline at end of file
diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py
index 154b5730d7..783f71e06c 100644
--- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py
+++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py
@@ -361,3 +361,19 @@ class EditorEntity:
:return: True if "isVisible" is enabled, False otherwise.
"""
return editor.EditorEntityInfoRequestBus(bus.Event, "IsVisible", self.id)
+
+ def set_local_uniform_scale(self, scale_float) -> None:
+ """
+ Sets the "SetLocalUniformScale" value on the entity.
+ :param scale_float: value for "SetLocalUniformScale" to set to.
+ :return: None
+ """
+ azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalUniformScale", self.id, scale_float)
+
+ def set_local_rotation(self, vector3_rotation) -> None:
+ """
+ Sets the "SetLocalRotation" value on the entity.
+ :param vector3_rotation: The math.Vector3 value to use for rotation on the entity (uses radians).
+ :return: None
+ """
+ azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", self.id, vector3_rotation)
diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py
index cc217f81da..ef3048d8d4 100644
--- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py
+++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py
@@ -4,18 +4,18 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
+
+import json
+import math
import os
import time
-import math
+import traceback
+from typing import Callable, Tuple
import azlmbr
import azlmbr.legacy.general as general
import azlmbr.debug
-import json
-import traceback
-
-from typing import Callable, Tuple
class FailFast(Exception):
"""
@@ -127,6 +127,31 @@ class TestHelper:
if ret:
return True
+ @staticmethod
+ def close_error_windows():
+ """
+ Closes Error Report and Error Log windows that block focus if they are visible.
+ :return: None
+ """
+ if general.is_pane_visible("Error Report"):
+ general.close_pane("Error Report")
+ if general.is_pane_visible("Error Log"):
+ general.close_pane("Error Log")
+
+ @staticmethod
+ def close_display_helpers():
+ """
+ Closes helper gizmos, anti-aliasing, and FPS meters.
+ :return: None
+ """
+ if general.is_helpers_shown():
+ general.toggle_helpers()
+ general.idle_wait(1.0)
+ general.idle_wait(1.0)
+ general.run_console("r_displayInfo=0")
+ general.run_console("r_antialiasingmode=0")
+ general.idle_wait(1.0)
+
class Timeout:
# type: (float) -> None
@@ -149,6 +174,7 @@ class Timeout:
def timed_out(self):
return time.time() > self.die_after
+
class Report:
_results = []
_exception = None
@@ -290,8 +316,8 @@ class Report:
Report.info(" x: {:.2f}, y: {:.2f}, z: {:.2f}".format(vector3.x, vector3.y, vector3.z))
if magnitude is not None:
Report.info(" magnitude: {:.2f}".format(magnitude))
-
-
+
+
'''
Utility for scope tracing errors and warnings.
Usage:
@@ -303,7 +329,7 @@ Usage:
Report.result(Tests.warnings_not_found_in_section, not section_tracer.has_warnings)
-'''
+'''
class Tracer:
def __init__(self):
self.warnings = []
@@ -349,10 +375,10 @@ class Tracer:
self.line = args[1]
self.function = args[2]
self.message = args[3]
-
+
def __str__(self):
return f"Assert: [{self.filename}:{self.function}:{self.line}]: {self.message}"
-
+
def __repr__(self):
return f"[Assert: {self.message}]"
@@ -360,21 +386,21 @@ class Tracer:
def __init__(self, args):
self.window = args[0]
self.message = args[1]
-
+
def _on_warning(self, args):
warningInfo = Tracer.WarningInfo(args)
self.warnings.append(warningInfo)
Report.info("Tracer caught Warning: %s" % warningInfo.message)
self.has_warnings = True
return False
-
+
def _on_error(self, args):
errorInfo = Tracer.ErrorInfo(args)
self.errors.append(errorInfo)
Report.info("Tracer caught Error: %s" % errorInfo.message)
self.has_errors = True
return False
-
+
def _on_assert(self, args):
assertInfo = Tracer.AssertInfo(args)
self.asserts.append(assertInfo)
@@ -436,6 +462,7 @@ class AngleHelper:
def vector3_str(vector3):
return "(x: {:.2f}, y: {:.2f}, z: {:.2f})".format(vector3.x, vector3.y, vector3.z)
-
+
+
def aabb_str(aabb):
return "[Min: %s, Max: %s]" % (vector3_str(aabb.min), vector3_str(aabb.max))
diff --git a/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py
index da89316993..e5dd9adbb9 100755
--- a/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py
+++ b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py
@@ -525,10 +525,6 @@ class TestAutomation(TestAutomationBase):
from .tests.joints import Joints_BallNoLimitsConstrained as test_module
self._run_test(request, workspace, editor, test_module)
- def test_Joints_FixedLeadFollowerCollide(self, request, workspace, editor, launcher_platform):
- from .tests.joints import Joints_FixedLeadFollowerCollide as test_module
- self._run_test(request, workspace, editor, test_module)
-
def test_Joints_GlobalFrameConstrained(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_GlobalFrameConstrained as test_module
self._run_test(request, workspace, editor, test_module)
diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py
index abc58779a2..e949d2d8f9 100644
--- a/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py
+++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py
@@ -82,7 +82,7 @@ def ForceRegion_SplineRegionWithModifiedTransform():
import azlmbr.bus as bus
# region Constants
- TIMEOUT = 5.0
+ TIMEOUT = 10.0
MIN_TRIGGER_DISTANCE = 2.0
# endregion
diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py
index 91190f83e5..6582628ff9 100644
--- a/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py
+++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py
@@ -77,7 +77,7 @@ def ForceRegion_ZeroPointForceDoesNothing():
helper.init_idle()
- TIMEOUT_SECONDS = 3.0
+ TIMEOUT_SECONDS = 5.0
X_Y_Z_TOLERANCE = 1.5
REGION_HEIGHT = 3.0
TERRAIN_HEIGHT = 32.0
diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/JointsHelper.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/JointsHelper.py
index 6226f42534..a85e460659 100644
--- a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/JointsHelper.py
+++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/JointsHelper.py
@@ -45,8 +45,13 @@ class JointEntity:
# Entity class that sets a flag when an instance receives collision events.
class JointEntityCollisionAware(JointEntity):
def on_collision_begin(self, args):
- if not self.collided:
- self.collided = True
+ self.collided = True
+
+ def on_collision_persist(self, args):
+ self.collided = True
+
+ def on_collision_end(self, args):
+ self.collided = True
def __init__(self, name):
self.id = general.find_game_entity(name)
@@ -58,3 +63,5 @@ class JointEntityCollisionAware(JointEntity):
self.handler = azlmbr.physics.CollisionNotificationBusHandler()
self.handler.connect(self.id)
self.handler.add_callback("OnCollisionBegin", self.on_collision_begin)
+ self.handler.add_callback("OnCollisionPresist", self.on_collision_persist)
+ self.handler.add_callback("OnCollisionEnd", self.on_collision_end)
diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_FixedLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_FixedLeadFollowerCollide.py
deleted file mode 100644
index e142941c5a..0000000000
--- a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_FixedLeadFollowerCollide.py
+++ /dev/null
@@ -1,92 +0,0 @@
-"""
-Copyright (c) Contributors to the Open 3D Engine Project.
-For complete copyright and license terms please see the LICENSE at the root of this distribution.
-
-SPDX-License-Identifier: Apache-2.0 OR MIT
-"""
-
-# Test case ID : C18243582
-# Test Case Title : Check that fixed joint allows lead-follower collision
-
-
-# fmt: off
-class Tests:
- enter_game_mode = ("Entered game mode", "Failed to enter game mode")
- exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
- lead_found = ("Found lead", "Did not find lead")
- follower_found = ("Found follower", "Did not find follower")
- check_collision_happened = ("Lead and follower collided", "Lead and follower did not collide")
-# fmt: on
-
-
-def Joints_FixedLeadFollowerCollide():
- """
- Summary: Check that fixed joint allows lead-follower collision
-
- Level Description:
- lead - Starts above follower entity
- follower - Starts below lead entity. Constrained to lead entity with fixed joint. Starts with initial velocity of (5, 0, 0) in positive X direction.
-
- Expected Behavior:
- The follower entity moves in the positive X direction and the lead entity is dragged along towards the positive X direction.
- The x position of the lead entity is incremented from its original.
- The lead and follower entities are kept apart at a distance of approximately 1.0 due to collision.
-
- Test Steps:
- 1) Open Level
- 2) Enter Game Mode
- 3) Create and Validate Entities
- 4) Wait for several seconds
- 5) Check to see if lead and follower behaved as expected.
- 6) Exit Game Mode
- 7) Close 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
- import sys
- from editor_python_test_tools.utils import Report
- from editor_python_test_tools.utils import TestHelper as helper
-
- import azlmbr.legacy.general as general
- import azlmbr.bus
-
- from JointsHelper import JointEntityCollisionAware
-
- # Helper Entity class - self.collided flag is set when instance receives collision event.
- class Entity(JointEntityCollisionAware):
- def criticalEntityFound(self): # Override function to use local Test dictionary
- Report.critical_result(Tests.__dict__[self.name + "_found"], self.id.isValid())
-
- # Main Script
- helper.init_idle()
-
- # 1) Open Level
- helper.open_level("Physics", "Joints_FixedLeadFollowerCollide")
-
- # 2) Enter Game Mode
- helper.enter_game_mode(Tests.enter_game_mode)
-
- # 3) Create and Validate Entities
- lead = Entity("lead")
- follower = Entity("follower")
-
- # 4) Wait for several seconds
- general.idle_wait(2.0) # wait for lead and follower to move
-
- # 5) Check to see if lead entity and follower collided
- Report.critical_result(Tests.check_collision_happened, lead.collided and follower.collided)
-
- # 6) Exit Game Mode
- helper.exit_game_mode(Tests.exit_game_mode)
-
-
-
-if __name__ == "__main__":
- from editor_python_test_tools.utils import Report
- Report.start_test(Joints_FixedLeadFollowerCollide)
diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_KinematicModeWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_KinematicModeWorks.py
index 1c53854bab..05671389c2 100644
--- a/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_KinematicModeWorks.py
+++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_KinematicModeWorks.py
@@ -80,6 +80,20 @@ def RigidBody_KinematicModeWorks():
ramp_id = general.find_game_entity("Ramp")
Report.result(Tests.find_ramp, ramp_id.IsValid())
+ # 2.1) setup collision handler
+ class RampTouched:
+ value = False
+
+ def on_collision_begin(args):
+ other_id = args[0]
+ if other_id.Equal(ramp_id):
+ Report.info("Box touched ramp")
+ RampTouched.value = True
+
+ handler = azlmbr.physics.CollisionNotificationBusHandler()
+ handler.connect(box_id)
+ handler.add_callback("OnCollisionBegin", on_collision_begin)
+
# 3) Check for kinematic ramp and not kinematic box
box_kinematic = azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "IsKinematic", box_id)
Report.result(Tests.box_is_not_kinematic, not box_kinematic)
@@ -98,21 +112,7 @@ def RigidBody_KinematicModeWorks():
ramp_pos_start = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", ramp_id)
Report.info("Ramp's initial position: {}".format(ramp_pos_start))
- # 6) Check to see that the box hits the ramp
- class RampTouched:
- value = False
-
- def on_collision_begin(args):
- other_id = args[0]
- if other_id.Equal(ramp_id):
- Report.info("Box touched ramp")
- RampTouched.value = True
-
- handler = azlmbr.physics.CollisionNotificationBusHandler()
- handler.connect(box_id)
- handler.add_callback("OnCollisionBegin", on_collision_begin)
-
- # 6.5) Wait for the box to touch the ramp or timeout
+ # 6) Wait for the box to touch the ramp or timeout
helper.wait_for_condition(lambda: RampTouched.value, TIME_OUT)
Report.result(Tests.box_touched_ramp, RampTouched.value)
diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/C30936451/test_texture_sequence000.png.exportsettings b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/C30936451/test_texture_sequence000.png.exportsettings
deleted file mode 100644
index a8fbf72992..0000000000
--- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/C30936451/test_texture_sequence000.png.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Terrain_Albedo_HighPassed /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt
index 59ccdffdca..c2123d683c 100644
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt
@@ -70,19 +70,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
## GradientSignal ##
- ly_add_pytest(
- NAME AutomatedTesting::GradientSignalTests_Periodic
- TEST_SERIAL
- TEST_SUITE periodic
- PATH ${CMAKE_CURRENT_LIST_DIR}/gradient_signal/TestSuite_Periodic.py
- RUNTIME_DEPENDENCIES
- AZ::AssetProcessor
- Legacy::Editor
- AutomatedTesting.Assets
- COMPONENT
- LargeWorlds
- )
-
ly_add_pytest(
NAME AutomatedTesting::GradientSignalTests_Periodic_Optimized
TEST_SERIAL
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py
index e51be58ec6..84c661873c 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py
@@ -109,7 +109,7 @@ def DynamicSliceInstanceSpawner_Embedded_E2E():
# 6) Save and export to engine
general.save_level()
general.export_to_engine()
- pak_path = os.path.join(paths.devroot, "AutomatedTesting", "cache", "pc", "levels", lvl_name, "level.pak")
+ pak_path = os.path.join(paths.products, "levels", lvl_name, "level.pak")
Report.result(Tests.saved_and_exported, os.path.exists(pak_path))
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py
index 7a0abdd969..de2554034f 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py
@@ -131,7 +131,7 @@ def DynamicSliceInstanceSpawner_External_E2E():
# 6) Save and export to engine
general.save_level()
general.export_to_engine()
- pak_path = os.path.join(paths.devroot, "AutomatedTesting", "cache", "pc", "levels", lvl_name, "level.pak")
+ pak_path = os.path.join(paths.products, "levels", lvl_name, "level.pak")
Report.result(Tests.saved_and_exported, os.path.exists(pak_path))
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlender_E2E_Editor.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlender_E2E_Editor.py
index f56c0b836e..bf6501f469 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlender_E2E_Editor.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlender_E2E_Editor.py
@@ -155,7 +155,7 @@ def LayerBlender_E2E_Editor():
# 6) Save and export to engine
general.save_level()
general.export_to_engine()
- pak_path = os.path.join(paths.devroot, "AutomatedTesting", "cache", "pc", "levels", lvl_name, "level.pak")
+ pak_path = os.path.join(paths.products, "levels", lvl_name, "level.pak")
Report.result(Tests.saved_and_exported, os.path.exists(pak_path))
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/TestSuite_Periodic_Optimized.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/TestSuite_Periodic_Optimized.py
index f996a1f8c3..514504d324 100644
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/TestSuite_Periodic_Optimized.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/TestSuite_Periodic_Optimized.py
@@ -10,7 +10,6 @@ import pytest
from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorParallelTest, EditorTestSuite
-@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.")
@pytest.mark.SUITE_periodic
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/large_worlds_utils/editor_dynveg_test_helper.py b/AutomatedTesting/Gem/PythonTests/largeworlds/large_worlds_utils/editor_dynveg_test_helper.py
index 65ebf8e59e..957536fffb 100755
--- a/AutomatedTesting/Gem/PythonTests/largeworlds/large_worlds_utils/editor_dynveg_test_helper.py
+++ b/AutomatedTesting/Gem/PythonTests/largeworlds/large_worlds_utils/editor_dynveg_test_helper.py
@@ -17,7 +17,7 @@ import azlmbr.vegetation as vegetation
import azlmbr.areasystem as areasystem
import azlmbr.paths
-sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
+sys.path.append(os.path.join(azlmbr.paths.projectroot, 'Gem', 'PythonTests'))
import editor_python_test_tools.hydra_editor_utils as hydra
@@ -25,7 +25,7 @@ def create_surface_entity(name, center_point, box_size_x, box_size_y, box_size_z
# Create a "flat surface" entity to use as a plantable vegetation surface
surface_entity = hydra.Entity(name)
surface_entity.create_entity(
- center_point,
+ center_point,
["Box Shape", "Shape Surface Tag Emitter"]
)
if surface_entity.id.IsValid():
@@ -56,7 +56,7 @@ def create_vegetation_area(name, center_point, box_size_x, box_size_y, box_size_
# Create a vegetation area entity to use as our test vegetation spawner
spawner_entity = hydra.Entity(name)
spawner_entity.create_entity(
- center_point,
+ center_point,
["Vegetation Layer Spawner", "Box Shape", "Vegetation Asset List"]
)
if spawner_entity.id.IsValid():
diff --git a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py
index 0862e03a79..b2001e6825 100755
--- a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py
+++ b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py
@@ -122,6 +122,7 @@ class TestAutomation(TestAutomationBase):
from . import Debugger_HappyPath_TargetMultipleEntities as test_module
self._run_test(request, workspace, editor, test_module)
+ @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
def test_EditMenu_Default_UndoRedo(self, request, workspace, editor, launcher_platform, project):
from . import EditMenu_Default_UndoRedo as test_module
self._run_test(request, workspace, editor, test_module)
@@ -181,6 +182,7 @@ class TestAutomation(TestAutomationBase):
from . import NodePalette_SearchText_Deletion as test_module
self._run_test(request, workspace, editor, test_module)
+ @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
def test_VariableManager_UnpinVariableType_Works(self, request, workspace, editor, launcher_platform):
from . import VariableManager_UnpinVariableType_Works as test_module
self._run_test(request, workspace, editor, test_module)
diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/Joints_FixedLeadFollowerCollide.ly b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/Joints_FixedLeadFollowerCollide.ly
deleted file mode 100644
index 0c3ac9e668..0000000000
--- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/Joints_FixedLeadFollowerCollide.ly
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:3093fee5317ba6fb353a435c09f43f13c5e722421aae62a297f699c202d6129e
-size 6699
diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/filelist.xml b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/filelist.xml
deleted file mode 100644
index d0960f8154..0000000000
--- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/filelist.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/level.pak b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/level.pak
deleted file mode 100644
index 532be2c1bd..0000000000
--- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/level.pak
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:b1daa050e732ff0594601bbfca8ac9ed05972c2f9fa3e43dbc8645e802ed2730
-size 7959
diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/Environment.xml b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/Environment.xml
deleted file mode 100644
index 4ba36f66ae..0000000000
--- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/Environment.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TerrainTexture.xml b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TerrainTexture.xml
deleted file mode 100644
index f43df05b22..0000000000
--- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TerrainTexture.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TimeOfDay.xml b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TimeOfDay.xml
deleted file mode 100644
index 456d609b8a..0000000000
--- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TimeOfDay.xml
+++ /dev/null
@@ -1,356 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/VegetationMap.dat b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/VegetationMap.dat
deleted file mode 100644
index dce5631cd0..0000000000
--- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/VegetationMap.dat
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:0e6a5435c928079b27796f6b202bbc2623e7e454244ddc099a3cadf33b7cb9e9
-size 63
diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/tags.txt b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/tags.txt
deleted file mode 100644
index 0d6c1880e7..0000000000
--- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/tags.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-0,0,0,0,0,0
-0,0,0,0,0,0
-0,0,0,0,0,0
-0,0,0,0,0,0
-0,0,0,0,0,0
-0,0,0,0,0,0
-0,0,0,0,0,0
-0,0,0,0,0,0
-0,0,0,0,0,0
-0,0,0,0,0,0
-0,0,0,0,0,0
-0,0,0,0,0,0
diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/terraintexture.pak b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/terraintexture.pak
deleted file mode 100644
index fe3604a050..0000000000
--- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/terraintexture.pak
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8739c76e681f900923b900c9df0ef75cf421d39cabb54650c4b9ad19b6a76d85
-size 22
diff --git a/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly b/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly
index 3d17ae7ccc..86dd941423 100644
--- a/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly
+++ b/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:012caffa9354f6253d2e626ba183b44eb02a74eba286fde0430227ef024411e2
-size 8961
+oid sha256:817bd8dd22e185136418b60fba5b3552993687515d3d5ae96791f2c3be907b92
+size 7233
diff --git a/AutomatedTesting/Levels/Physics/Material_DefaultLibraryConsistentOnAllFeatures/cowboy.emfxworkspace b/AutomatedTesting/Levels/Physics/Material_DefaultLibraryConsistentOnAllFeatures/cowboy.emfxworkspace
index 188fee9f05..05140f340b 100644
--- a/AutomatedTesting/Levels/Physics/Material_DefaultLibraryConsistentOnAllFeatures/cowboy.emfxworkspace
+++ b/AutomatedTesting/Levels/Physics/Material_DefaultLibraryConsistentOnAllFeatures/cowboy.emfxworkspace
@@ -1,3 +1,3 @@
[General]
version=1
-startScript="ImportActor -filename \"@assets@/characters/cowboy/actor/cowboy_01.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 0.000000 -yPos 0.000000 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.00000000,1.00000000\n"
+startScript="ImportActor -filename \"@products@/characters/cowboy/actor/cowboy_01.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 0.000000 -yPos 0.000000 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.00000000,1.00000000\n"
diff --git a/AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/ws.emfxworkspace b/AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/ws.emfxworkspace
index e429d74a57..870b9a8579 100644
--- a/AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/ws.emfxworkspace
+++ b/AutomatedTesting/Levels/Physics/Material_DefaultMaterialLibraryChangesWork/ws.emfxworkspace
@@ -1,3 +1,3 @@
[General]
version=1
-startScript="ImportActor -filename \"@assets@/levels/physics/c15096734_physxmaterials_defaultmateriallibrary/rin_skeleton_newgeo.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 0.000000 -yPos 0.000000 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.00000000,1.00000000\nLoadMotionSet -filename \"@assets@/Levels/Physics/C15096734_PhysxMaterials_DefaultMaterialLibrary/custom_motionset.motionset\"\nLoadAnimGraph -filename \"@assets@/Levels/Physics/C15096734_PhysxMaterials_DefaultMaterialLibrary/rin_physics.animgraph\"\n"
+startScript="ImportActor -filename \"@products@/levels/physics/c15096734_physxmaterials_defaultmateriallibrary/rin_skeleton_newgeo.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 0.000000 -yPos 0.000000 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.00000000,1.00000000\nLoadMotionSet -filename \"@products@/levels/physics/c15096734_physxmaterials_defaultmateriallibrary/custom_motionset.motionset\"\nLoadAnimGraph -filename \"@products@/levels/physics/c15096734_physxmaterials_defaultmateriallibrary/rin_physics.animgraph\"\n"
diff --git a/AutomatedTesting/Levels/Physics/RigidBody_KinematicModeWorks/RigidBody_KinematicModeWorks.ly b/AutomatedTesting/Levels/Physics/RigidBody_KinematicModeWorks/RigidBody_KinematicModeWorks.ly
index 92e6788bf0..d6052ffa7c 100644
--- a/AutomatedTesting/Levels/Physics/RigidBody_KinematicModeWorks/RigidBody_KinematicModeWorks.ly
+++ b/AutomatedTesting/Levels/Physics/RigidBody_KinematicModeWorks/RigidBody_KinematicModeWorks.ly
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:619bcf0c2a2b08f4ffe05e60858c479828fe39d5530f4e488b9c0ec8a585ccb7
-size 7735
+oid sha256:cb97ada674d123c67d7a32eb65e81fa66472cf51f748054c4a4297649f2a0f40
+size 5568
diff --git a/AutomatedTesting/Objects/LumberTank/ProxyGray_ddna.tif.exportsettings b/AutomatedTesting/Objects/LumberTank/ProxyGray_ddna.tif.exportsettings
deleted file mode 100644
index a4e1a9a3c5..0000000000
--- a/AutomatedTesting/Objects/LumberTank/ProxyGray_ddna.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:0,pc:0,provo:0"
\ No newline at end of file
diff --git a/AutomatedTesting/Registry/assets_scan_folders.setreg b/AutomatedTesting/Registry/assets_scan_folders.setreg
index 91061f3337..c74ba6703e 100644
--- a/AutomatedTesting/Registry/assets_scan_folders.setreg
+++ b/AutomatedTesting/Registry/assets_scan_folders.setreg
@@ -51,6 +51,14 @@
[
"Gems/UiBasics"
]
+ },
+ "Hair":
+ {
+ "SourcePaths":
+ [
+ "Gems/AtomTressFX/Assets",
+ "Gems/AtomTressFX/Assets/Passes"
+ ]
}
}
}
diff --git a/AutomatedTesting/Registry/physx_overrides/Collider_AddingNewGroupWorks.setreg_override b/AutomatedTesting/Registry/physx_overrides/Collider_AddingNewGroupWorks.setreg_override
index 7065f0dfeb..209e9a9feb 100644
--- a/AutomatedTesting/Registry/physx_overrides/Collider_AddingNewGroupWorks.setreg_override
+++ b/AutomatedTesting/Registry/physx_overrides/Collider_AddingNewGroupWorks.setreg_override
@@ -109,7 +109,7 @@
},
"MaterialLibrary": {
"assetId": {
- "guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
+ "guid": "{7CDF49C3-91A2-5C4E-B642-6D1AEC80E70E}"
},
"loadBehavior": "QueueLoad",
"assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"
diff --git a/AutomatedTesting/Registry/physx_overrides/Collider_CollisionGroupsWorkflow.setreg_override b/AutomatedTesting/Registry/physx_overrides/Collider_CollisionGroupsWorkflow.setreg_override
index b82acaf0ae..65f15f8554 100644
--- a/AutomatedTesting/Registry/physx_overrides/Collider_CollisionGroupsWorkflow.setreg_override
+++ b/AutomatedTesting/Registry/physx_overrides/Collider_CollisionGroupsWorkflow.setreg_override
@@ -121,7 +121,7 @@
},
"MaterialLibrary": {
"assetId": {
- "guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
+ "guid": "{7CDF49C3-91A2-5C4E-B642-6D1AEC80E70E}"
},
"loadBehavior": "QueueLoad",
"assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"
diff --git a/AutomatedTesting/Registry/physx_overrides/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.setreg_override b/AutomatedTesting/Registry/physx_overrides/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.setreg_override
index b82acaf0ae..65f15f8554 100644
--- a/AutomatedTesting/Registry/physx_overrides/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.setreg_override
+++ b/AutomatedTesting/Registry/physx_overrides/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.setreg_override
@@ -121,7 +121,7 @@
},
"MaterialLibrary": {
"assetId": {
- "guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
+ "guid": "{7CDF49C3-91A2-5C4E-B642-6D1AEC80E70E}"
},
"loadBehavior": "QueueLoad",
"assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"
diff --git a/AutomatedTesting/Registry/physx_overrides/Collider_NoneCollisionGroupSameLayerNotCollide.setreg_override b/AutomatedTesting/Registry/physx_overrides/Collider_NoneCollisionGroupSameLayerNotCollide.setreg_override
index b82acaf0ae..65f15f8554 100644
--- a/AutomatedTesting/Registry/physx_overrides/Collider_NoneCollisionGroupSameLayerNotCollide.setreg_override
+++ b/AutomatedTesting/Registry/physx_overrides/Collider_NoneCollisionGroupSameLayerNotCollide.setreg_override
@@ -121,7 +121,7 @@
},
"MaterialLibrary": {
"assetId": {
- "guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
+ "guid": "{7CDF49C3-91A2-5C4E-B642-6D1AEC80E70E}"
},
"loadBehavior": "QueueLoad",
"assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"
diff --git a/AutomatedTesting/Registry/physx_overrides/Collider_SameCollisionGroupSameCustomLayerCollide.setreg_override b/AutomatedTesting/Registry/physx_overrides/Collider_SameCollisionGroupSameCustomLayerCollide.setreg_override
index b82acaf0ae..65f15f8554 100644
--- a/AutomatedTesting/Registry/physx_overrides/Collider_SameCollisionGroupSameCustomLayerCollide.setreg_override
+++ b/AutomatedTesting/Registry/physx_overrides/Collider_SameCollisionGroupSameCustomLayerCollide.setreg_override
@@ -121,7 +121,7 @@
},
"MaterialLibrary": {
"assetId": {
- "guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
+ "guid": "{7CDF49C3-91A2-5C4E-B642-6D1AEC80E70E}"
},
"loadBehavior": "QueueLoad",
"assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"
diff --git a/AutomatedTesting/Registry/physxsystemconfiguration.setreg b/AutomatedTesting/Registry/physxsystemconfiguration.setreg
index 83aad307a6..2ade83d769 100644
--- a/AutomatedTesting/Registry/physxsystemconfiguration.setreg
+++ b/AutomatedTesting/Registry/physxsystemconfiguration.setreg
@@ -103,7 +103,7 @@
},
"MaterialLibrary": {
"assetId": {
- "guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
+ "guid": "{7CDF49C3-91A2-5C4E-B642-6D1AEC80E70E}"
},
"loadBehavior": "QueueLoad",
"assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"
diff --git a/AutomatedTesting/multiple_mesh_one_material/FBXTestTexture.png b/AutomatedTesting/multiple_mesh_one_material/FBXTestTexture.png
new file mode 100644
index 0000000000..4f52364cb3
--- /dev/null
+++ b/AutomatedTesting/multiple_mesh_one_material/FBXTestTexture.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:827a63985273229050bf4f63030bcc666f045091fe81cf8157a9ca23b40074b6
+size 3214
diff --git a/AutomatedTesting/multiple_mesh_one_material/multiple_mesh_one_material.fbx b/AutomatedTesting/multiple_mesh_one_material/multiple_mesh_one_material.fbx
new file mode 100644
index 0000000000..d9deb899f0
--- /dev/null
+++ b/AutomatedTesting/multiple_mesh_one_material/multiple_mesh_one_material.fbx
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d8d24963e6e8765205bc79cbe2304fc39f1245ee75249e2834a71c96c3cab824
+size 22700
diff --git a/AutomatedTesting/multiple_mesh_one_material/multiple_mesh_one_material.fbx.assetinfo b/AutomatedTesting/multiple_mesh_one_material/multiple_mesh_one_material.fbx.assetinfo
new file mode 100644
index 0000000000..fe18a16cb5
--- /dev/null
+++ b/AutomatedTesting/multiple_mesh_one_material/multiple_mesh_one_material.fbx.assetinfo
@@ -0,0 +1,8 @@
+{
+ "values": [
+ {
+ "$type": "ScriptProcessorRule",
+ "scriptFilename": "Editor/Scripts/scene_mesh_to_prefab.py"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/AutomatedTesting/textures/lights/flare01.tif.exportsettings b/AutomatedTesting/textures/lights/flare01.tif.exportsettings
deleted file mode 100644
index 4fee4cfc4b..0000000000
--- a/AutomatedTesting/textures/lights/flare01.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=LensOptics /reduce=-1
\ No newline at end of file
diff --git a/AutomatedTesting/textures/milestone2/AMA_Grey_01.tif.exportsettings b/AutomatedTesting/textures/milestone2/AMA_Grey_01.tif.exportsettings
deleted file mode 100644
index 2d1dccbf99..0000000000
--- a/AutomatedTesting/textures/milestone2/AMA_Grey_01.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Albedo /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/textures/milestone2/AMA_Grey_02.tif.exportsettings b/AutomatedTesting/textures/milestone2/AMA_Grey_02.tif.exportsettings
deleted file mode 100644
index a8fbf72992..0000000000
--- a/AutomatedTesting/textures/milestone2/AMA_Grey_02.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Terrain_Albedo_HighPassed /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/textures/milestone2/AMA_Grey_03.tif.exportsettings b/AutomatedTesting/textures/milestone2/AMA_Grey_03.tif.exportsettings
deleted file mode 100644
index a8fbf72992..0000000000
--- a/AutomatedTesting/textures/milestone2/AMA_Grey_03.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=Terrain_Albedo_HighPassed /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleFront_01.tif.exportsettings b/AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleFront_01.tif.exportsettings
deleted file mode 100644
index be29bd9bc0..0000000000
--- a/AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleFront_01.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=AlbedoWithOpacity /reduce=0
\ No newline at end of file
diff --git a/AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleRing_01.tif.exportsettings b/AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleRing_01.tif.exportsettings
deleted file mode 100644
index be29bd9bc0..0000000000
--- a/AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleRing_01.tif.exportsettings
+++ /dev/null
@@ -1 +0,0 @@
-/autooptimizefile=0 /preset=AlbedoWithOpacity /reduce=0
\ No newline at end of file
diff --git a/Code/Editor/CMakeLists.txt b/Code/Editor/CMakeLists.txt
index 5884795413..2ea0aa1a74 100644
--- a/Code/Editor/CMakeLists.txt
+++ b/Code/Editor/CMakeLists.txt
@@ -33,7 +33,6 @@ ly_add_target(
BUILD_DEPENDENCIES
PRIVATE
Legacy::CryCommon
- 3rdParty::zlib
PUBLIC
3rdParty::Qt::Core
3rdParty::Qt::Gui
@@ -105,7 +104,6 @@ ly_add_target(
3rdParty::Qt::Concurrent
3rdParty::tiff
3rdParty::squish-ccr
- 3rdParty::zlib
3rdParty::AWSNativeSDK::STS
Legacy::CryCommon
Legacy::EditorCommon
diff --git a/Code/Editor/Controls/FolderTreeCtrl.cpp b/Code/Editor/Controls/FolderTreeCtrl.cpp
index b1cbb9414e..4088ab976f 100644
--- a/Code/Editor/Controls/FolderTreeCtrl.cpp
+++ b/Code/Editor/Controls/FolderTreeCtrl.cpp
@@ -278,17 +278,16 @@ void CFolderTreeCtrl::LoadTreeRec(const QString& currentFolder)
void CFolderTreeCtrl::AddItem(const QString& path)
{
- QString folder;
- QString fileNameWithoutExtension;
- QString ext;
-
- Path::Split(path, folder, fileNameWithoutExtension, ext);
+ AZ::IO::FixedMaxPath folder{ AZ::IO::PathView(path.toUtf8().constData()) };
+ AZ::IO::FixedMaxPath fileNameWithoutExtension = folder.Extension();
+ folder = folder.ParentPath();
auto regex = QRegExp(m_fileNameSpec, Qt::CaseInsensitive, QRegExp::Wildcard);
if (regex.exactMatch(path))
{
- CTreeItem* folderTreeItem = CreateFolderItems(folder);
- folderTreeItem->AddChild(fileNameWithoutExtension, path, eTreeImage_File);
+ CTreeItem* folderTreeItem = CreateFolderItems(QString::fromUtf8(folder.c_str(), static_cast(folder.Native().size())));
+ folderTreeItem->AddChild(QString::fromUtf8(fileNameWithoutExtension.c_str(),
+ static_cast(fileNameWithoutExtension.Native().size())), path, eTreeImage_File);
}
}
diff --git a/Code/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Editor/Core/LevelEditorMenuHandler.cpp
index e568f05167..fdde1ac305 100644
--- a/Code/Editor/Core/LevelEditorMenuHandler.cpp
+++ b/Code/Editor/Core/LevelEditorMenuHandler.cpp
@@ -32,6 +32,7 @@
#include
// AzToolsFramework
+#include
#include
// AzQtComponents
@@ -166,15 +167,14 @@ LevelEditorMenuHandler::LevelEditorMenuHandler(MainWindow* mainWindow, QtViewPan
m_mainWindow->menuBar()->setNativeMenuBar(true);
#endif
- ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
- AzToolsFramework::GetEntityContextId());
+ ViewportEditorModeNotificationsBus::Handler::BusConnect(GetEntityContextId());
EditorMenuRequestBus::Handler::BusConnect();
}
LevelEditorMenuHandler::~LevelEditorMenuHandler()
{
EditorMenuRequestBus::Handler::BusDisconnect();
- ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
+ ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
}
void LevelEditorMenuHandler::Initialize()
@@ -487,8 +487,6 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
editMenu.AddAction(AzToolsFramework::EditPivot);
editMenu.AddAction(AzToolsFramework::EditReset);
editMenu.AddAction(AzToolsFramework::EditResetManipulator);
- editMenu.AddAction(AzToolsFramework::EditResetLocal);
- editMenu.AddAction(AzToolsFramework::EditResetWorld);
// Hide Selection
editMenu.AddAction(AzToolsFramework::HideSelection);
@@ -1186,36 +1184,44 @@ void LevelEditorMenuHandler::AddDisableActionInSimModeListener(QAction* action)
}));
}
-void LevelEditorMenuHandler::EnteredComponentMode(const AZStd::vector& /*componentModeTypes*/)
+void LevelEditorMenuHandler::OnEditorModeActivated(
+ [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
{
- auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
- if (!menuWrapper.isNull())
+ if (mode == ViewportEditorMode::Component)
{
- // copy of menu actions
- auto actions = menuWrapper.Get()->actions();
- // remove all non-reserved edit menu options
- actions.erase(
- std::remove_if(actions.begin(), actions.end(), [](QAction* action)
- {
- return !action->property("Reserved").toBool();
- }),
- actions.end());
+ if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
+ !menuWrapper.isNull())
+ {
+ // copy of menu actions
+ auto actions = menuWrapper.Get()->actions();
+ // remove all non-reserved edit menu options
+ actions.erase(
+ std::remove_if(actions.begin(), actions.end(), [](QAction* action)
+ {
+ return !action->property("Reserved").toBool();
+ }),
+ actions.end());
- // clear and update the menu with new actions
- menuWrapper.Get()->clear();
- menuWrapper.Get()->addActions(actions);
+ // clear and update the menu with new actions
+ menuWrapper.Get()->clear();
+ menuWrapper.Get()->addActions(actions);
+ }
}
}
-void LevelEditorMenuHandler::LeftComponentMode(const AZStd::vector& /*componentModeTypes*/)
+void LevelEditorMenuHandler::OnEditorModeDeactivated(
+ [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
{
- RestoreEditMenuToDefault();
+ if (mode == ViewportEditorMode::Component)
+ {
+ RestoreEditMenuToDefault();
+ }
}
void LevelEditorMenuHandler::AddEditMenuAction(QAction* action)
{
- auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
- if (!menuWrapper.isNull())
+ if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
+ !menuWrapper.isNull())
{
menuWrapper.Get()->addAction(action);
}
@@ -1239,8 +1245,8 @@ void LevelEditorMenuHandler::AddMenuAction(AZStd::string_view categoryId, QActio
void LevelEditorMenuHandler::RestoreEditMenuToDefault()
{
- auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
- if (!menuWrapper.isNull())
+ if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
+ !menuWrapper.isNull())
{
menuWrapper.Get()->clear();
PopulateEditMenu(menuWrapper);
diff --git a/Code/Editor/Core/LevelEditorMenuHandler.h b/Code/Editor/Core/LevelEditorMenuHandler.h
index 5ac8e63786..ff03c7748c 100644
--- a/Code/Editor/Core/LevelEditorMenuHandler.h
+++ b/Code/Editor/Core/LevelEditorMenuHandler.h
@@ -18,7 +18,7 @@
#include
#include "ActionManager.h"
#include "QtViewPaneManager.h"
-#include
+#include
#endif
class MainWindow;
@@ -28,7 +28,7 @@ struct QtViewPane;
class LevelEditorMenuHandler
: public QObject
- , private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
+ , private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler
, private AzToolsFramework::EditorMenuRequestBus::Handler
{
Q_OBJECT
@@ -88,9 +88,11 @@ private:
void AddDisableActionInSimModeListener(QAction* action);
- // EditorComponentModeNotificationBus
- void EnteredComponentMode(const AZStd::vector& componentModeTypes) override;
- void LeftComponentMode(const AZStd::vector& componentModeTypes) override;
+ // ViewportEditorModeNotificationsBus overrides ...
+ void OnEditorModeActivated(
+ const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
+ void OnEditorModeDeactivated(
+ const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
// EditorMenuRequestBus
void AddEditMenuAction(QAction* action) override;
diff --git a/Code/Editor/Core/Tests/test_Main.cpp b/Code/Editor/Core/Tests/test_Main.cpp
index 3d3e286f18..16b0aa92cf 100644
--- a/Code/Editor/Core/Tests/test_Main.cpp
+++ b/Code/Editor/Core/Tests/test_Main.cpp
@@ -33,6 +33,7 @@ public:
protected:
void SetupEnvironment() override
{
+ AttachEditorCoreAZEnvironment(AZ::Environment::GetInstance());
m_allocatorScope.ActivateAllocators();
m_cryPak = new NiceMock();
@@ -49,6 +50,7 @@ protected:
{
delete m_cryPak;
m_allocatorScope.DeactivateAllocators();
+ DetachEditorCoreAZEnvironment();
}
private:
diff --git a/Code/Editor/Core/Tests/test_PathUtil.cpp b/Code/Editor/Core/Tests/test_PathUtil.cpp
index 83e50a5947..cade19eb81 100644
--- a/Code/Editor/Core/Tests/test_PathUtil.cpp
+++ b/Code/Editor/Core/Tests/test_PathUtil.cpp
@@ -5,22 +5,29 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
-#include "EditorDefs.h"
-#include
-#include "Util/PathUtil.h"
-#include
-
-TEST(PathUtil, GamePathToFullPath_DoesNotBufferOverflow)
+#include
+#include
+namespace UnitTest
{
- // There are no test assertions in this test because the purpose is just to verify that the test runs without crashing
- QString pngExtension(".png");
+ class PathUtil
+ : public ScopedAllocatorSetupFixture
+ {
+ };
+
+ TEST_F(PathUtil, GamePathToFullPath_DoesNotBufferOverflow)
+ {
+ // There are no test assertions in this test because the purpose is just to verify that the test runs without crashing
+ QString pngExtension(".png");
- // Create a string of lenth AZ_MAX_PATH_LEN that ends in .png
- QString longStringMaxPath(AZ_MAX_PATH_LEN, 'x');
- longStringMaxPath.replace(longStringMaxPath.length() - pngExtension.length(), longStringMaxPath.length(), pngExtension);
- Path::GamePathToFullPath(longStringMaxPath);
+ // Create a string of length AZ_MAX_PATH_LEN that ends in .png
+ QString longStringMaxPath(AZ_MAX_PATH_LEN, 'x');
+ longStringMaxPath.replace(longStringMaxPath.length() - pngExtension.length(), longStringMaxPath.length(), pngExtension);
+ AZ_TEST_START_TRACE_SUPPRESSION;
+ Path::GamePathToFullPath(longStringMaxPath);
+ AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
- QString longStringMaxPathPlusOne(AZ_MAX_PATH_LEN + 1, 'x');
- longStringMaxPathPlusOne.replace(longStringMaxPathPlusOne.length() - pngExtension.length(), longStringMaxPathPlusOne.length(), pngExtension);
- Path::GamePathToFullPath(longStringMaxPathPlusOne);
+ QString longStringMaxPathPlusOne(AZ_MAX_PATH_LEN + 1, 'x');
+ longStringMaxPathPlusOne.replace(longStringMaxPathPlusOne.length() - pngExtension.length(), longStringMaxPathPlusOne.length(), pngExtension);
+ Path::GamePathToFullPath(longStringMaxPathPlusOne);
+ }
}
diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp
index b5eb4229df..abba2bb9c6 100644
--- a/Code/Editor/CryEdit.cpp
+++ b/Code/Editor/CryEdit.cpp
@@ -2124,6 +2124,8 @@ bool CCryEditApp::FixDanglingSharedMemory(const QString& sharedMemName) const
int CCryEditApp::ExitInstance(int exitCode)
{
+ AZ_TracePrintf("Exit", "Called ExitInstance() with exit code: 0x%x", exitCode);
+
if (m_pEditor)
{
m_pEditor->OnBeginShutdownSequence();
@@ -2642,7 +2644,7 @@ void CCryEditApp::OnFileResaveSlices()
sliceAssetInfos.reserve(5000);
AZ::Data::AssetCatalogRequests::AssetEnumerationCB sliceCountCb = [&sliceAssetInfos]([[maybe_unused]] const AZ::Data::AssetId id, const AZ::Data::AssetInfo& info)
{
- // Only add slices and nothing that has been temporarily added to the catalog with a macro in it (ie @devroot@)
+ // Only add slices and nothing that has been temporarily added to the catalog with a macro in it (ie @engroot@)
if (info.m_assetType == azrtti_typeid() && info.m_relativePath[0] != '@')
{
sliceAssetInfos.push_back(info);
diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp
index 07d946c609..75bd0ad270 100644
--- a/Code/Editor/CryEditDoc.cpp
+++ b/Code/Editor/CryEditDoc.cpp
@@ -1108,7 +1108,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename)
if (QFileInfo(filename).isRelative())
{
// Resolving the path through resolvepath would normalize and lowcase it, and in this case, we don't want that.
- fullPathName = Path::ToUnixPath(QDir(QString::fromUtf8(gEnv->pFileIO->GetAlias("@devassets@"))).absoluteFilePath(fullPathName));
+ fullPathName = Path::ToUnixPath(QDir(QString::fromUtf8(gEnv->pFileIO->GetAlias("@projectroot@"))).absoluteFilePath(fullPathName));
}
if (!CFileUtil::OverwriteFile(fullPathName))
@@ -2159,7 +2159,7 @@ bool CCryEditDoc::LoadXmlArchiveArray(TDocMultiArchive& arrXmlAr, const QString&
xmlAr.bLoading = true;
// bound to the level folder, as if it were the assets folder.
- // this mounts (whateverlevelname.ly) as @assets@/Levels/whateverlevelname/ and thus it works...
+ // this mounts (whateverlevelname.ly) as @products@/Levels/whateverlevelname/ and thus it works...
bool openLevelPakFileSuccess = pIPak->OpenPack(levelPath.toUtf8().data(), absoluteLevelPath.toUtf8().data());
if (!openLevelPakFileSuccess)
{
diff --git a/Code/Editor/Dialogs/PythonScriptsDialog.cpp b/Code/Editor/Dialogs/PythonScriptsDialog.cpp
index e95fb90c0a..35047947ac 100644
--- a/Code/Editor/Dialogs/PythonScriptsDialog.cpp
+++ b/Code/Editor/Dialogs/PythonScriptsDialog.cpp
@@ -91,7 +91,7 @@ CPythonScriptsDialog::CPythonScriptsDialog(QWidget* parent)
{
AZ::IO::Path newSourcePath = jsonSourcePathPointer;
// Resolve any file aliases first - Do not use ResolvePath() as that assumes
- // any relative path is underneath the @assets@ alias
+ // any relative path is underneath the @products@ alias
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
{
AZ::IO::FixedMaxPath replacedAliasPath;
diff --git a/Code/Editor/EditorFileMonitor.cpp b/Code/Editor/EditorFileMonitor.cpp
index 7feb9d32a8..311c42befa 100644
--- a/Code/Editor/EditorFileMonitor.cpp
+++ b/Code/Editor/EditorFileMonitor.cpp
@@ -14,6 +14,8 @@
// Editor
#include "CryEdit.h"
+#include
+
//////////////////////////////////////////////////////////////////////////
CEditorFileMonitor::CEditorFileMonitor()
{
@@ -177,26 +179,14 @@ void CEditorFileMonitor::OnFileMonitorChange(const SFileChangeInfo& rChange)
// Make file relative to PrimaryCD folder.
QString filename = rChange.filename;
- // Remove game directory if present in path.
- const QString rootPath =
- QDir::fromNativeSeparators(QString::fromLatin1(Path::GetEditingRootFolder().c_str()));
- if (filename.startsWith(rootPath, Qt::CaseInsensitive))
- {
- filename = filename.right(filename.length() - rootPath.length());
- }
-
- // Make sure there is no leading slash
- if (!filename.isEmpty() && (filename[0] == '\\' || filename[0] == '/'))
- {
- filename = filename.mid(1);
- }
+ // Make path relative to the the project directory
+ AZ::IO::Path projectPath{ AZ::Utils::GetProjectPath() };
+ AZ::IO::FixedMaxPath projectRelativeFilePath = AZ::IO::PathView(filename.toUtf8().constData()).LexicallyProximate(
+ projectPath);
- if (!filename.isEmpty())
+ if (!projectRelativeFilePath.empty())
{
- //remove game name. Make it relative to the game folder
- const QString filenameRelGame = RemoveGameName(filename);
- const int extIndex = filename.lastIndexOf('.');
- const QString ext = filename.right(filename.length() - 1 - extIndex);
+ AZ::IO::PathView ext = projectRelativeFilePath.Extension();
// Check for File Monitor callback
std::vector::iterator iter;
@@ -207,15 +197,11 @@ void CEditorFileMonitor::OnFileMonitorChange(const SFileChangeInfo& rChange)
// We compare against length of callback string, so we get directory matches as well as full filenames
if (sCallback.pListener)
{
- if (sCallback.extension == "*" || ext.compare(sCallback.extension, Qt::CaseInsensitive) == 0)
+ if (sCallback.extension == "*" || AZ::IO::PathView(sCallback.extension.toUtf8().constData()) == ext)
{
- if (filenameRelGame.compare(sCallback.item, Qt::CaseInsensitive) == 0)
- {
- sCallback.pListener->OnFileChange(qPrintable(filenameRelGame), IFileChangeListener::EChangeType(rChange.changeType));
- }
- else if (filename.compare(sCallback.item, Qt::CaseInsensitive) == 0)
+ if (AZ::IO::PathView(sCallback.item.toUtf8().constData()) == projectRelativeFilePath)
{
- sCallback.pListener->OnFileChange(qPrintable(filename), IFileChangeListener::EChangeType(rChange.changeType));
+ sCallback.pListener->OnFileChange(qPrintable(projectRelativeFilePath.c_str()), IFileChangeListener::EChangeType(rChange.changeType));
}
}
}
diff --git a/Code/Editor/EditorModularViewportCameraComposer.cpp b/Code/Editor/EditorModularViewportCameraComposer.cpp
index 29cf348ab5..ce4a0a2e33 100644
--- a/Code/Editor/EditorModularViewportCameraComposer.cpp
+++ b/Code/Editor/EditorModularViewportCameraComposer.cpp
@@ -95,7 +95,8 @@ namespace SandboxEditor
cameras.AddCamera(m_firstPersonPanCamera);
cameras.AddCamera(m_firstPersonTranslateCamera);
cameras.AddCamera(m_firstPersonScrollCamera);
- cameras.AddCamera(m_pivotCamera);
+ cameras.AddCamera(m_firstPersonFocusCamera);
+ cameras.AddCamera(m_orbitCamera);
});
return controller;
@@ -111,6 +112,7 @@ namespace SandboxEditor
viewportId, &AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::BeginCursorCapture);
}
};
+
const auto showCursor = [viewportId = m_viewportId]
{
if (SandboxEditor::CameraCaptureCursorForLook())
@@ -133,7 +135,7 @@ namespace SandboxEditor
m_firstPersonRotateCamera->SetActivationEndedFn(showCursor);
m_firstPersonPanCamera = AZStd::make_shared(
- SandboxEditor::CameraFreePanChannelId(), AzFramework::LookPan, AzFramework::TranslatePivot);
+ SandboxEditor::CameraFreePanChannelId(), AzFramework::LookPan, AzFramework::TranslatePivotLook);
m_firstPersonPanCamera->m_panSpeedFn = []
{
@@ -153,7 +155,7 @@ namespace SandboxEditor
const auto translateCameraInputChannelIds = BuildTranslateCameraInputChannelIds();
m_firstPersonTranslateCamera = AZStd::make_shared(
- translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivot);
+ translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivotLook);
m_firstPersonTranslateCamera->m_translateSpeedFn = []
{
@@ -165,90 +167,111 @@ namespace SandboxEditor
return SandboxEditor::CameraBoostMultiplier();
};
- m_firstPersonScrollCamera = AZStd::make_shared();
+ m_firstPersonScrollCamera = AZStd::make_shared();
m_firstPersonScrollCamera->m_scrollSpeedFn = []
{
return SandboxEditor::CameraScrollSpeed();
};
- m_pivotCamera = AZStd::make_shared(SandboxEditor::CameraPivotChannelId());
+ const auto pivotFn = []
+ {
+ // use the manipulator transform as the pivot point
+ AZStd::optional entityPivot;
+ AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
+ entityPivot, AzToolsFramework::GetEntityContextId(),
+ &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
- m_pivotCamera->SetPivotFn(
- []([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction)
+ if (entityPivot.has_value())
{
- // use the manipulator transform as the pivot point
- AZStd::optional entityPivot;
- AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
- entityPivot, AzToolsFramework::GetEntityContextId(),
- &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
-
- // otherwise just use the identity
- return entityPivot.value_or(AZ::Transform::CreateIdentity()).GetTranslation();
+ return entityPivot->GetTranslation();
+ }
+
+ // otherwise just use the identity
+ return AZ::Vector3::CreateZero();
+ };
+
+ m_firstPersonFocusCamera =
+ AZStd::make_shared(SandboxEditor::CameraFocusChannelId(), AzFramework::FocusLook);
+
+ m_firstPersonFocusCamera->SetPivotFn(pivotFn);
+
+ m_orbitCamera = AZStd::make_shared(SandboxEditor::CameraOrbitChannelId());
+
+ m_orbitCamera->SetPivotFn(
+ [pivotFn]([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction)
+ {
+ return pivotFn();
});
- m_pivotRotateCamera = AZStd::make_shared(SandboxEditor::CameraPivotLookChannelId());
+ m_orbitRotateCamera = AZStd::make_shared(SandboxEditor::CameraOrbitLookChannelId());
- m_pivotRotateCamera->m_rotateSpeedFn = []
+ m_orbitRotateCamera->m_rotateSpeedFn = []
{
return SandboxEditor::CameraRotateSpeed();
};
- m_pivotRotateCamera->m_invertYawFn = []
+ m_orbitRotateCamera->m_invertYawFn = []
{
- return SandboxEditor::CameraPivotYawRotationInverted();
+ return SandboxEditor::CameraOrbitYawRotationInverted();
};
- m_pivotTranslateCamera = AZStd::make_shared(
- translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslateOffset);
+ m_orbitTranslateCamera = AZStd::make_shared(
+ translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslateOffsetOrbit);
- m_pivotTranslateCamera->m_translateSpeedFn = []
+ m_orbitTranslateCamera->m_translateSpeedFn = []
{
return SandboxEditor::CameraTranslateSpeed();
};
- m_pivotTranslateCamera->m_boostMultiplierFn = []
+ m_orbitTranslateCamera->m_boostMultiplierFn = []
{
return SandboxEditor::CameraBoostMultiplier();
};
- m_pivotDollyScrollCamera = AZStd::make_shared();
+ m_orbitDollyScrollCamera = AZStd::make_shared();
- m_pivotDollyScrollCamera->m_scrollSpeedFn = []
+ m_orbitDollyScrollCamera->m_scrollSpeedFn = []
{
return SandboxEditor::CameraScrollSpeed();
};
- m_pivotDollyMoveCamera = AZStd::make_shared(SandboxEditor::CameraPivotDollyChannelId());
+ m_orbitDollyMoveCamera = AZStd::make_shared(SandboxEditor::CameraOrbitDollyChannelId());
- m_pivotDollyMoveCamera->m_motionSpeedFn = []
+ m_orbitDollyMoveCamera->m_motionSpeedFn = []
{
return SandboxEditor::CameraDollyMotionSpeed();
};
- m_pivotPanCamera = AZStd::make_shared(
- SandboxEditor::CameraPivotPanChannelId(), AzFramework::LookPan, AzFramework::TranslateOffset);
+ m_orbitPanCamera = AZStd::make_shared(
+ SandboxEditor::CameraOrbitPanChannelId(), AzFramework::LookPan, AzFramework::TranslateOffsetOrbit);
- m_pivotPanCamera->m_panSpeedFn = []
+ m_orbitPanCamera->m_panSpeedFn = []
{
return SandboxEditor::CameraPanSpeed();
};
- m_pivotPanCamera->m_invertPanXFn = []
+ m_orbitPanCamera->m_invertPanXFn = []
{
return SandboxEditor::CameraPanInvertedX();
};
- m_pivotPanCamera->m_invertPanYFn = []
+ m_orbitPanCamera->m_invertPanYFn = []
{
return SandboxEditor::CameraPanInvertedY();
};
- m_pivotCamera->m_pivotCameras.AddCamera(m_pivotRotateCamera);
- m_pivotCamera->m_pivotCameras.AddCamera(m_pivotTranslateCamera);
- m_pivotCamera->m_pivotCameras.AddCamera(m_pivotDollyScrollCamera);
- m_pivotCamera->m_pivotCameras.AddCamera(m_pivotDollyMoveCamera);
- m_pivotCamera->m_pivotCameras.AddCamera(m_pivotPanCamera);
+ m_orbitFocusCamera =
+ AZStd::make_shared(SandboxEditor::CameraFocusChannelId(), AzFramework::FocusOrbit);
+
+ m_orbitFocusCamera->SetPivotFn(pivotFn);
+
+ m_orbitCamera->m_orbitCameras.AddCamera(m_orbitRotateCamera);
+ m_orbitCamera->m_orbitCameras.AddCamera(m_orbitTranslateCamera);
+ m_orbitCamera->m_orbitCameras.AddCamera(m_orbitDollyScrollCamera);
+ m_orbitCamera->m_orbitCameras.AddCamera(m_orbitDollyMoveCamera);
+ m_orbitCamera->m_orbitCameras.AddCamera(m_orbitPanCamera);
+ m_orbitCamera->m_orbitCameras.AddCamera(m_orbitFocusCamera);
}
void EditorModularViewportCameraComposer::OnEditorModularViewportCameraComposerSettingsChanged()
@@ -257,12 +280,14 @@ namespace SandboxEditor
m_firstPersonTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds);
m_firstPersonPanCamera->SetPanInputChannelId(SandboxEditor::CameraFreePanChannelId());
m_firstPersonRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraFreeLookChannelId());
-
- m_pivotCamera->SetPivotInputChannelId(SandboxEditor::CameraPivotChannelId());
- m_pivotTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds);
- m_pivotPanCamera->SetPanInputChannelId(SandboxEditor::CameraPivotPanChannelId());
- m_pivotRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraPivotLookChannelId());
- m_pivotDollyMoveCamera->SetDollyInputChannelId(SandboxEditor::CameraPivotDollyChannelId());
+ m_firstPersonFocusCamera->SetFocusInputChannelId(SandboxEditor::CameraFocusChannelId());
+
+ m_orbitCamera->SetOrbitInputChannelId(SandboxEditor::CameraOrbitChannelId());
+ m_orbitTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds);
+ m_orbitPanCamera->SetPanInputChannelId(SandboxEditor::CameraOrbitPanChannelId());
+ m_orbitRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraOrbitLookChannelId());
+ m_orbitDollyMoveCamera->SetDollyInputChannelId(SandboxEditor::CameraOrbitDollyChannelId());
+ m_orbitFocusCamera->SetFocusInputChannelId(SandboxEditor::CameraFocusChannelId());
}
void EditorModularViewportCameraComposer::OnViewportViewEntityChanged(const AZ::EntityId& viewEntityId)
diff --git a/Code/Editor/EditorModularViewportCameraComposer.h b/Code/Editor/EditorModularViewportCameraComposer.h
index e691ca1c89..9cfd6f3554 100644
--- a/Code/Editor/EditorModularViewportCameraComposer.h
+++ b/Code/Editor/EditorModularViewportCameraComposer.h
@@ -41,13 +41,15 @@ namespace SandboxEditor
AZStd::shared_ptr m_firstPersonRotateCamera;
AZStd::shared_ptr m_firstPersonPanCamera;
AZStd::shared_ptr m_firstPersonTranslateCamera;
- AZStd::shared_ptr m_firstPersonScrollCamera;
- AZStd::shared_ptr m_pivotCamera;
- AZStd::shared_ptr m_pivotRotateCamera;
- AZStd::shared_ptr m_pivotTranslateCamera;
- AZStd::shared_ptr m_pivotDollyScrollCamera;
- AZStd::shared_ptr m_pivotDollyMoveCamera;
- AZStd::shared_ptr m_pivotPanCamera;
+ AZStd::shared_ptr m_firstPersonScrollCamera;
+ AZStd::shared_ptr m_firstPersonFocusCamera;
+ AZStd::shared_ptr m_orbitCamera;
+ AZStd::shared_ptr m_orbitRotateCamera;
+ AZStd::shared_ptr m_orbitTranslateCamera;
+ AZStd::shared_ptr m_orbitDollyScrollCamera;
+ AZStd::shared_ptr m_orbitDollyMoveCamera;
+ AZStd::shared_ptr m_orbitPanCamera;
+ AZStd::shared_ptr m_orbitFocusCamera;
AzFramework::ViewportId m_viewportId;
};
diff --git a/Code/Editor/EditorPreferencesPageViewportCamera.cpp b/Code/Editor/EditorPreferencesPageViewportCamera.cpp
index 55b631e1f6..16176bc241 100644
--- a/Code/Editor/EditorPreferencesPageViewportCamera.cpp
+++ b/Code/Editor/EditorPreferencesPageViewportCamera.cpp
@@ -73,7 +73,7 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial
->Field("TranslateSmoothing", &CameraMovementSettings::m_translateSmoothing)
->Field("TranslateSmoothness", &CameraMovementSettings::m_translateSmoothness)
->Field("CaptureCursorLook", &CameraMovementSettings::m_captureCursorLook)
- ->Field("PivotYawRotationInverted", &CameraMovementSettings::m_pivotYawRotationInverted)
+ ->Field("OrbitYawRotationInverted", &CameraMovementSettings::m_orbitYawRotationInverted)
->Field("PanInvertedX", &CameraMovementSettings::m_panInvertedX)
->Field("PanInvertedY", &CameraMovementSettings::m_panInvertedY);
@@ -86,12 +86,13 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial
->Field("TranslateUp", &CameraInputSettings::m_translateUpChannelId)
->Field("TranslateDown", &CameraInputSettings::m_translateDownChannelId)
->Field("Boost", &CameraInputSettings::m_boostChannelId)
- ->Field("Pivot", &CameraInputSettings::m_pivotChannelId)
+ ->Field("Orbit", &CameraInputSettings::m_orbitChannelId)
->Field("FreeLook", &CameraInputSettings::m_freeLookChannelId)
->Field("FreePan", &CameraInputSettings::m_freePanChannelId)
- ->Field("PivotLook", &CameraInputSettings::m_pivotLookChannelId)
- ->Field("PivotDolly", &CameraInputSettings::m_pivotDollyChannelId)
- ->Field("PivotPan", &CameraInputSettings::m_pivotPanChannelId);
+ ->Field("OrbitLook", &CameraInputSettings::m_orbitLookChannelId)
+ ->Field("OrbitDolly", &CameraInputSettings::m_orbitDollyChannelId)
+ ->Field("OrbitPan", &CameraInputSettings::m_orbitPanChannelId)
+ ->Field("Focus", &CameraInputSettings::m_focusChannelId);
serialize.Class()
->Version(1)
@@ -143,8 +144,8 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial
->Attribute(AZ::Edit::Attributes::Min, minValue)
->Attribute(AZ::Edit::Attributes::Visibility, &CameraMovementSettings::TranslateSmoothingVisibility)
->DataElement(
- AZ::Edit::UIHandlers::CheckBox, &CameraMovementSettings::m_pivotYawRotationInverted, "Camera Pivot Yaw Inverted",
- "Inverted yaw rotation while pivoting")
+ AZ::Edit::UIHandlers::CheckBox, &CameraMovementSettings::m_orbitYawRotationInverted, "Camera Orbit Yaw Inverted",
+ "Inverted yaw rotation while orbiting")
->DataElement(
AZ::Edit::UIHandlers::CheckBox, &CameraMovementSettings::m_panInvertedX, "Invert Pan X",
"Invert direction of pan in local X axis")
@@ -185,8 +186,8 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial
"Key/button to move the camera more quickly")
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames)
->DataElement(
- AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_pivotChannelId, "Pivot",
- "Key/button to begin the camera pivot behavior")
+ AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitChannelId, "Orbit",
+ "Key/button to begin the camera orbit behavior")
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames)
->DataElement(
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_freeLookChannelId, "Free Look",
@@ -196,24 +197,27 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_freePanChannelId, "Free Pan", "Key/button to begin camera free pan")
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames)
->DataElement(
- AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_pivotLookChannelId, "Pivot Look",
- "Key/button to begin camera pivot look")
+ AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitLookChannelId, "Orbit Look",
+ "Key/button to begin camera orbit look")
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames)
->DataElement(
- AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_pivotDollyChannelId, "Pivot Dolly",
- "Key/button to begin camera pivot dolly")
+ AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitDollyChannelId, "Orbit Dolly",
+ "Key/button to begin camera orbit dolly")
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames)
->DataElement(
- AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_pivotPanChannelId, "Pivot Pan",
- "Key/button to begin camera pivot pan")
+ AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitPanChannelId, "Orbit Pan",
+ "Key/button to begin camera orbit pan")
+ ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames)
+ ->DataElement(
+ AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_focusChannelId, "Focus", "Key/button to focus camera orbit")
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames);
editContext->Class("Viewport Preferences", "Viewport Preferences")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20))
->DataElement(
- AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportCamera::m_cameraMovementSettings,
- "Camera Movement Settings", "Camera Movement Settings")
+ AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportCamera::m_cameraMovementSettings, "Camera Movement Settings",
+ "Camera Movement Settings")
->DataElement(
AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportCamera::m_cameraInputSettings, "Camera Input Settings",
"Camera Input Settings");
@@ -264,7 +268,7 @@ void CEditorPreferencesPage_ViewportCamera::OnApply()
SandboxEditor::SetCameraTranslateSmoothness(m_cameraMovementSettings.m_translateSmoothness);
SandboxEditor::SetCameraTranslateSmoothingEnabled(m_cameraMovementSettings.m_translateSmoothing);
SandboxEditor::SetCameraCaptureCursorForLook(m_cameraMovementSettings.m_captureCursorLook);
- SandboxEditor::SetCameraPivotYawRotationInverted(m_cameraMovementSettings.m_pivotYawRotationInverted);
+ SandboxEditor::SetCameraOrbitYawRotationInverted(m_cameraMovementSettings.m_orbitYawRotationInverted);
SandboxEditor::SetCameraPanInvertedX(m_cameraMovementSettings.m_panInvertedX);
SandboxEditor::SetCameraPanInvertedY(m_cameraMovementSettings.m_panInvertedY);
@@ -275,12 +279,13 @@ void CEditorPreferencesPage_ViewportCamera::OnApply()
SandboxEditor::SetCameraTranslateUpChannelId(m_cameraInputSettings.m_translateUpChannelId);
SandboxEditor::SetCameraTranslateDownChannelId(m_cameraInputSettings.m_translateDownChannelId);
SandboxEditor::SetCameraTranslateBoostChannelId(m_cameraInputSettings.m_boostChannelId);
- SandboxEditor::SetCameraPivotChannelId(m_cameraInputSettings.m_pivotChannelId);
+ SandboxEditor::SetCameraOrbitChannelId(m_cameraInputSettings.m_orbitChannelId);
SandboxEditor::SetCameraFreeLookChannelId(m_cameraInputSettings.m_freeLookChannelId);
SandboxEditor::SetCameraFreePanChannelId(m_cameraInputSettings.m_freePanChannelId);
- SandboxEditor::SetCameraPivotLookChannelId(m_cameraInputSettings.m_pivotLookChannelId);
- SandboxEditor::SetCameraPivotDollyChannelId(m_cameraInputSettings.m_pivotDollyChannelId);
- SandboxEditor::SetCameraPivotPanChannelId(m_cameraInputSettings.m_pivotPanChannelId);
+ SandboxEditor::SetCameraOrbitLookChannelId(m_cameraInputSettings.m_orbitLookChannelId);
+ SandboxEditor::SetCameraOrbitDollyChannelId(m_cameraInputSettings.m_orbitDollyChannelId);
+ SandboxEditor::SetCameraOrbitPanChannelId(m_cameraInputSettings.m_orbitPanChannelId);
+ SandboxEditor::SetCameraFocusChannelId(m_cameraInputSettings.m_focusChannelId);
SandboxEditor::EditorModularViewportCameraComposerNotificationBus::Broadcast(
&SandboxEditor::EditorModularViewportCameraComposerNotificationBus::Events::OnEditorModularViewportCameraComposerSettingsChanged);
@@ -299,7 +304,7 @@ void CEditorPreferencesPage_ViewportCamera::InitializeSettings()
m_cameraMovementSettings.m_translateSmoothness = SandboxEditor::CameraTranslateSmoothness();
m_cameraMovementSettings.m_translateSmoothing = SandboxEditor::CameraTranslateSmoothingEnabled();
m_cameraMovementSettings.m_captureCursorLook = SandboxEditor::CameraCaptureCursorForLook();
- m_cameraMovementSettings.m_pivotYawRotationInverted = SandboxEditor::CameraPivotYawRotationInverted();
+ m_cameraMovementSettings.m_orbitYawRotationInverted = SandboxEditor::CameraOrbitYawRotationInverted();
m_cameraMovementSettings.m_panInvertedX = SandboxEditor::CameraPanInvertedX();
m_cameraMovementSettings.m_panInvertedY = SandboxEditor::CameraPanInvertedY();
@@ -310,10 +315,11 @@ void CEditorPreferencesPage_ViewportCamera::InitializeSettings()
m_cameraInputSettings.m_translateUpChannelId = SandboxEditor::CameraTranslateUpChannelId().GetName();
m_cameraInputSettings.m_translateDownChannelId = SandboxEditor::CameraTranslateDownChannelId().GetName();
m_cameraInputSettings.m_boostChannelId = SandboxEditor::CameraTranslateBoostChannelId().GetName();
- m_cameraInputSettings.m_pivotChannelId = SandboxEditor::CameraPivotChannelId().GetName();
+ m_cameraInputSettings.m_orbitChannelId = SandboxEditor::CameraOrbitChannelId().GetName();
m_cameraInputSettings.m_freeLookChannelId = SandboxEditor::CameraFreeLookChannelId().GetName();
m_cameraInputSettings.m_freePanChannelId = SandboxEditor::CameraFreePanChannelId().GetName();
- m_cameraInputSettings.m_pivotLookChannelId = SandboxEditor::CameraPivotLookChannelId().GetName();
- m_cameraInputSettings.m_pivotDollyChannelId = SandboxEditor::CameraPivotDollyChannelId().GetName();
- m_cameraInputSettings.m_pivotPanChannelId = SandboxEditor::CameraPivotPanChannelId().GetName();
+ m_cameraInputSettings.m_orbitLookChannelId = SandboxEditor::CameraOrbitLookChannelId().GetName();
+ m_cameraInputSettings.m_orbitDollyChannelId = SandboxEditor::CameraOrbitDollyChannelId().GetName();
+ m_cameraInputSettings.m_orbitPanChannelId = SandboxEditor::CameraOrbitPanChannelId().GetName();
+ m_cameraInputSettings.m_focusChannelId = SandboxEditor::CameraFocusChannelId().GetName();
}
diff --git a/Code/Editor/EditorPreferencesPageViewportCamera.h b/Code/Editor/EditorPreferencesPageViewportCamera.h
index 01dc4664f6..fdc86b0f89 100644
--- a/Code/Editor/EditorPreferencesPageViewportCamera.h
+++ b/Code/Editor/EditorPreferencesPageViewportCamera.h
@@ -54,7 +54,7 @@ private:
float m_translateSmoothness;
bool m_translateSmoothing;
bool m_captureCursorLook;
- bool m_pivotYawRotationInverted;
+ bool m_orbitYawRotationInverted;
bool m_panInvertedX;
bool m_panInvertedY;
@@ -80,12 +80,13 @@ private:
AZStd::string m_translateUpChannelId;
AZStd::string m_translateDownChannelId;
AZStd::string m_boostChannelId;
- AZStd::string m_pivotChannelId;
+ AZStd::string m_orbitChannelId;
AZStd::string m_freeLookChannelId;
AZStd::string m_freePanChannelId;
- AZStd::string m_pivotLookChannelId;
- AZStd::string m_pivotDollyChannelId;
- AZStd::string m_pivotPanChannelId;
+ AZStd::string m_orbitLookChannelId;
+ AZStd::string m_orbitDollyChannelId;
+ AZStd::string m_orbitPanChannelId;
+ AZStd::string m_focusChannelId;
};
CameraMovementSettings m_cameraMovementSettings;
diff --git a/Code/Editor/EditorViewportSettings.cpp b/Code/Editor/EditorViewportSettings.cpp
index fe8efecd17..2354c6d63a 100644
--- a/Code/Editor/EditorViewportSettings.cpp
+++ b/Code/Editor/EditorViewportSettings.cpp
@@ -28,7 +28,7 @@ namespace SandboxEditor
constexpr AZStd::string_view CameraRotateSpeedSetting = "/Amazon/Preferences/Editor/Camera/RotateSpeed";
constexpr AZStd::string_view CameraScrollSpeedSetting = "/Amazon/Preferences/Editor/Camera/DollyScrollSpeed";
constexpr AZStd::string_view CameraDollyMotionSpeedSetting = "/Amazon/Preferences/Editor/Camera/DollyMotionSpeed";
- constexpr AZStd::string_view CameraPivotYawRotationInvertedSetting = "/Amazon/Preferences/Editor/Camera/YawRotationInverted";
+ constexpr AZStd::string_view CameraOrbitYawRotationInvertedSetting = "/Amazon/Preferences/Editor/Camera/YawRotationInverted";
constexpr AZStd::string_view CameraPanInvertedXSetting = "/Amazon/Preferences/Editor/Camera/PanInvertedX";
constexpr AZStd::string_view CameraPanInvertedYSetting = "/Amazon/Preferences/Editor/Camera/PanInvertedY";
constexpr AZStd::string_view CameraPanSpeedSetting = "/Amazon/Preferences/Editor/Camera/PanSpeed";
@@ -44,12 +44,13 @@ namespace SandboxEditor
constexpr AZStd::string_view CameraTranslateUpIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpId";
constexpr AZStd::string_view CameraTranslateDownIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpDownId";
constexpr AZStd::string_view CameraTranslateBoostIdSetting = "/Amazon/Preferences/Editor/Camera/TranslateBoostId";
- constexpr AZStd::string_view CameraPivotIdSetting = "/Amazon/Preferences/Editor/Camera/PivotId";
+ constexpr AZStd::string_view CameraOrbitIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitId";
constexpr AZStd::string_view CameraFreeLookIdSetting = "/Amazon/Preferences/Editor/Camera/FreeLookId";
constexpr AZStd::string_view CameraFreePanIdSetting = "/Amazon/Preferences/Editor/Camera/FreePanId";
- constexpr AZStd::string_view CameraPivotLookIdSetting = "/Amazon/Preferences/Editor/Camera/PivotLookId";
- constexpr AZStd::string_view CameraPivotDollyIdSetting = "/Amazon/Preferences/Editor/Camera/PivotDollyId";
- constexpr AZStd::string_view CameraPivotPanIdSetting = "/Amazon/Preferences/Editor/Camera/PivotPanId";
+ constexpr AZStd::string_view CameraOrbitLookIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitLookId";
+ constexpr AZStd::string_view CameraOrbitDollyIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitDollyId";
+ constexpr AZStd::string_view CameraOrbitPanIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitPanId";
+ constexpr AZStd::string_view CameraFocusIdSetting = "/Amazon/Preferences/Editor/Camera/FocusId";
template
void SetRegistry(const AZStd::string_view setting, T&& value)
@@ -239,14 +240,14 @@ namespace SandboxEditor
SetRegistry(CameraDollyMotionSpeedSetting, speed);
}
- bool CameraPivotYawRotationInverted()
+ bool CameraOrbitYawRotationInverted()
{
- return GetRegistry(CameraPivotYawRotationInvertedSetting, false);
+ return GetRegistry(CameraOrbitYawRotationInvertedSetting, false);
}
- void SetCameraPivotYawRotationInverted(const bool inverted)
+ void SetCameraOrbitYawRotationInverted(const bool inverted)
{
- SetRegistry(CameraPivotYawRotationInvertedSetting, inverted);
+ SetRegistry(CameraOrbitYawRotationInvertedSetting, inverted);
}
bool CameraPanInvertedX()
@@ -403,14 +404,14 @@ namespace SandboxEditor
SetRegistry(CameraTranslateBoostIdSetting, cameraTranslateBoostId);
}
- AzFramework::InputChannelId CameraPivotChannelId()
+ AzFramework::InputChannelId CameraOrbitChannelId()
{
- return AzFramework::InputChannelId(GetRegistry(CameraPivotIdSetting, AZStd::string("keyboard_key_modifier_alt_l")).c_str());
+ return AzFramework::InputChannelId(GetRegistry(CameraOrbitIdSetting, AZStd::string("keyboard_key_modifier_alt_l")).c_str());
}
- void SetCameraPivotChannelId(AZStd::string_view cameraPivotId)
+ void SetCameraOrbitChannelId(AZStd::string_view cameraOrbitId)
{
- SetRegistry(CameraPivotIdSetting, cameraPivotId);
+ SetRegistry(CameraOrbitIdSetting, cameraOrbitId);
}
AzFramework::InputChannelId CameraFreeLookChannelId()
@@ -433,33 +434,43 @@ namespace SandboxEditor
SetRegistry(CameraFreePanIdSetting, cameraFreePanId);
}
- AzFramework::InputChannelId CameraPivotLookChannelId()
+ AzFramework::InputChannelId CameraOrbitLookChannelId()
{
- return AzFramework::InputChannelId(GetRegistry(CameraPivotLookIdSetting, AZStd::string("mouse_button_left")).c_str());
+ return AzFramework::InputChannelId(GetRegistry(CameraOrbitLookIdSetting, AZStd::string("mouse_button_left")).c_str());
}
- void SetCameraPivotLookChannelId(AZStd::string_view cameraPivotLookId)
+ void SetCameraOrbitLookChannelId(AZStd::string_view cameraOrbitLookId)
{
- SetRegistry(CameraPivotLookIdSetting, cameraPivotLookId);
+ SetRegistry(CameraOrbitLookIdSetting, cameraOrbitLookId);
}
- AzFramework::InputChannelId CameraPivotDollyChannelId()
+ AzFramework::InputChannelId CameraOrbitDollyChannelId()
{
- return AzFramework::InputChannelId(GetRegistry(CameraPivotDollyIdSetting, AZStd::string("mouse_button_right")).c_str());
+ return AzFramework::InputChannelId(GetRegistry(CameraOrbitDollyIdSetting, AZStd::string("mouse_button_right")).c_str());
}
- void SetCameraPivotDollyChannelId(AZStd::string_view cameraPivotDollyId)
+ void SetCameraOrbitDollyChannelId(AZStd::string_view cameraOrbitDollyId)
{
- SetRegistry(CameraPivotDollyIdSetting, cameraPivotDollyId);
+ SetRegistry(CameraOrbitDollyIdSetting, cameraOrbitDollyId);
}
- AzFramework::InputChannelId CameraPivotPanChannelId()
+ AzFramework::InputChannelId CameraOrbitPanChannelId()
{
- return AzFramework::InputChannelId(GetRegistry(CameraPivotPanIdSetting, AZStd::string("mouse_button_middle")).c_str());
+ return AzFramework::InputChannelId(GetRegistry(CameraOrbitPanIdSetting, AZStd::string("mouse_button_middle")).c_str());
}
- void SetCameraPivotPanChannelId(AZStd::string_view cameraPivotPanId)
+ void SetCameraOrbitPanChannelId(AZStd::string_view cameraOrbitPanId)
{
- SetRegistry(CameraPivotPanIdSetting, cameraPivotPanId);
+ SetRegistry(CameraOrbitPanIdSetting, cameraOrbitPanId);
+ }
+
+ AzFramework::InputChannelId CameraFocusChannelId()
+ {
+ return AzFramework::InputChannelId(GetRegistry(CameraFocusIdSetting, AZStd::string("keyboard_key_alphanumeric_X")).c_str());
+ }
+
+ void SetCameraFocusChannelId(AZStd::string_view cameraFocusId)
+ {
+ SetRegistry(CameraFocusIdSetting, cameraFocusId);
}
} // namespace SandboxEditor
diff --git a/Code/Editor/EditorViewportSettings.h b/Code/Editor/EditorViewportSettings.h
index d1271017c6..c1394f7404 100644
--- a/Code/Editor/EditorViewportSettings.h
+++ b/Code/Editor/EditorViewportSettings.h
@@ -71,8 +71,8 @@ namespace SandboxEditor
SANDBOX_API float CameraDollyMotionSpeed();
SANDBOX_API void SetCameraDollyMotionSpeed(float speed);
- SANDBOX_API bool CameraPivotYawRotationInverted();
- SANDBOX_API void SetCameraPivotYawRotationInverted(bool inverted);
+ SANDBOX_API bool CameraOrbitYawRotationInverted();
+ SANDBOX_API void SetCameraOrbitYawRotationInverted(bool inverted);
SANDBOX_API bool CameraPanInvertedX();
SANDBOX_API void SetCameraPanInvertedX(bool inverted);
@@ -119,8 +119,8 @@ namespace SandboxEditor
SANDBOX_API AzFramework::InputChannelId CameraTranslateBoostChannelId();
SANDBOX_API void SetCameraTranslateBoostChannelId(AZStd::string_view cameraTranslateBoostId);
- SANDBOX_API AzFramework::InputChannelId CameraPivotChannelId();
- SANDBOX_API void SetCameraPivotChannelId(AZStd::string_view cameraPivotId);
+ SANDBOX_API AzFramework::InputChannelId CameraOrbitChannelId();
+ SANDBOX_API void SetCameraOrbitChannelId(AZStd::string_view cameraOrbitId);
SANDBOX_API AzFramework::InputChannelId CameraFreeLookChannelId();
SANDBOX_API void SetCameraFreeLookChannelId(AZStd::string_view cameraFreeLookId);
@@ -128,12 +128,15 @@ namespace SandboxEditor
SANDBOX_API AzFramework::InputChannelId CameraFreePanChannelId();
SANDBOX_API void SetCameraFreePanChannelId(AZStd::string_view cameraFreePanId);
- SANDBOX_API AzFramework::InputChannelId CameraPivotLookChannelId();
- SANDBOX_API void SetCameraPivotLookChannelId(AZStd::string_view cameraPivotLookId);
+ SANDBOX_API AzFramework::InputChannelId CameraOrbitLookChannelId();
+ SANDBOX_API void SetCameraOrbitLookChannelId(AZStd::string_view cameraOrbitLookId);
- SANDBOX_API AzFramework::InputChannelId CameraPivotDollyChannelId();
- SANDBOX_API void SetCameraPivotDollyChannelId(AZStd::string_view cameraPivotDollyId);
+ SANDBOX_API AzFramework::InputChannelId CameraOrbitDollyChannelId();
+ SANDBOX_API void SetCameraOrbitDollyChannelId(AZStd::string_view cameraOrbitDollyId);
- SANDBOX_API AzFramework::InputChannelId CameraPivotPanChannelId();
- SANDBOX_API void SetCameraPivotPanChannelId(AZStd::string_view cameraPivotPanId);
+ SANDBOX_API AzFramework::InputChannelId CameraOrbitPanChannelId();
+ SANDBOX_API void SetCameraOrbitPanChannelId(AZStd::string_view cameraOrbitPanId);
+
+ SANDBOX_API AzFramework::InputChannelId CameraFocusChannelId();
+ SANDBOX_API void SetCameraFocusChannelId(AZStd::string_view cameraFocusId);
} // namespace SandboxEditor
diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp
index 9315505e08..0324629877 100644
--- a/Code/Editor/GameExporter.cpp
+++ b/Code/Editor/GameExporter.cpp
@@ -28,6 +28,7 @@
#include "Objects/EntityObject.h"
#include
+#include
//////////////////////////////////////////////////////////////////////////
#define MUSIC_LEVEL_LIBRARY_FILE "Music.xml"
diff --git a/Code/Editor/Include/IDisplayViewport.h b/Code/Editor/Include/IDisplayViewport.h
index 813c54355b..c7dff33e50 100644
--- a/Code/Editor/Include/IDisplayViewport.h
+++ b/Code/Editor/Include/IDisplayViewport.h
@@ -35,8 +35,6 @@ struct IDisplayViewport
*/
virtual float GetDistanceToLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& point) const = 0;
- virtual CBaseObjectsCache* GetVisibleObjectsCache() = 0;
-
enum EAxis
{
AXIS_NONE,
diff --git a/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp b/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp
index 157291cfc2..ea3653f663 100644
--- a/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp
+++ b/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp
@@ -69,6 +69,7 @@ namespace UnitTest
m_rootWidget = AZStd::make_unique();
m_rootWidget->setFixedSize(WidgetSize);
+ m_rootWidget->move(0, 0); // explicitly set the widget to be in the upper left corner
m_controllerList = AZStd::make_shared();
m_controllerList->RegisterViewportContext(TestViewportId);
@@ -344,4 +345,51 @@ namespace UnitTest
// Clean-up
HaltCollaborators();
}
+
+ // test to verify deltas and cursor positions are handled correctly when the widget is moved
+ TEST_F(ModularViewportCameraControllerFixture, CameraDoesNotStutterAfterWidgetIsMoved)
+ {
+ // Given
+ PrepareCollaborators();
+ SandboxEditor::SetCameraCaptureCursorForLook(true);
+
+ const float deltaTime = 1.0f / 60.0f;
+
+ // When
+ // move cursor to the center of the screen
+ auto start = QPoint(WidgetSize.width() / 2, WidgetSize.height() / 2);
+ MouseMove(m_rootWidget.get(), start, QPoint(0, 0));
+ m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() });
+
+ // move camera right
+ const auto mouseDelta = QPoint(200, 0);
+ MousePressAndMove(m_rootWidget.get(), start, mouseDelta, Qt::MouseButton::RightButton);
+ m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() });
+
+ QTest::mouseRelease(m_rootWidget.get(), Qt::MouseButton::RightButton, Qt::NoModifier, start + mouseDelta);
+
+ // update the position of the widget
+ const auto offset = QPoint(500, 500);
+ m_rootWidget->move(offset);
+
+ // move cursor back to widget center
+ MouseMove(m_rootWidget.get(), start, QPoint(0, 0));
+ m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() });
+
+ // move camera left
+ MousePressAndMove(m_rootWidget.get(), start, -mouseDelta, Qt::MouseButton::RightButton);
+ m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() });
+
+ // Then
+ // ensure the camera rotation has returned to the identity
+ const AZ::Quaternion cameraRotation = m_cameraViewportContextView->GetCameraTransform().GetRotation();
+ const auto eulerAngles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromQuaternion(cameraRotation));
+
+ using ::testing::FloatNear;
+ EXPECT_THAT(eulerAngles.GetX(), FloatNear(0.0f, 0.001f));
+ EXPECT_THAT(eulerAngles.GetZ(), FloatNear(0.0f, 0.001f));
+
+ // Clean-up
+ HaltCollaborators();
+ }
} // namespace UnitTest
diff --git a/Code/Editor/MainWindow.cpp b/Code/Editor/MainWindow.cpp
index 05477bb0c7..ed72cd9170 100644
--- a/Code/Editor/MainWindow.cpp
+++ b/Code/Editor/MainWindow.cpp
@@ -98,6 +98,7 @@ AZ_POP_DISABLE_WARNING
#include "ActionManager.h"
#include
+#include
#include
using namespace AZ;
diff --git a/Code/Editor/Objects/ObjectManager.cpp b/Code/Editor/Objects/ObjectManager.cpp
index 06aa8866b3..7057cc5b7b 100644
--- a/Code/Editor/Objects/ObjectManager.cpp
+++ b/Code/Editor/Objects/ObjectManager.cpp
@@ -30,13 +30,11 @@
#include "Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h"
#include
+#include
+#include
AZ_CVAR_EXTERNED(bool, ed_visibility_logTiming);
-AZ_CVAR(
- bool, ed_visibility_use, true, nullptr, AZ::ConsoleFunctorFlags::Null,
- "Enable/disable using the new IVisibilitySystem for Entity visibility determination");
-
/*!
* Class Description used for object templates.
* This description filled from Xml template files.
@@ -76,17 +74,6 @@ public:
int GameCreationOrder() override { return superType->GameCreationOrder(); };
};
-void CBaseObjectsCache::AddObject(CBaseObject* object)
-{
- m_objects.push_back(object);
- if (object->GetType() == OBJTYPE_AZENTITY)
- {
- auto componentEntityObject = static_cast(object);
- m_entityIds.push_back(componentEntityObject->GetAssociatedEntityId());
- }
-}
-
-
//////////////////////////////////////////////////////////////////////////
// CObjectManager implementation.
//////////////////////////////////////////////////////////////////////////
@@ -122,14 +109,13 @@ CObjectManager::CObjectManager()
m_objectsByName.reserve(1024);
LoadRegistry();
- AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
- AzToolsFramework::GetEntityContextId());
+ AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId());
}
//////////////////////////////////////////////////////////////////////////
CObjectManager::~CObjectManager()
{
- AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
+ AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
m_bExiting = true;
SaveRegistry();
@@ -1267,25 +1253,8 @@ void CObjectManager::Display(DisplayContext& dc)
UpdateVisibilityList();
}
- bool viewIsDirty = dc.settings->IsDisplayHelpers(); // displaying helpers require computing all the bound boxes and things anyway.
-
- if (!viewIsDirty)
+ if (dc.settings->IsDisplayHelpers())
{
- if (CBaseObjectsCache* cache = dc.view->GetVisibleObjectsCache())
- {
- // if the current rendering viewport has an out-of-date cache serial number, it needs to be refreshed too.
- // views set their cache empty when they indicate they need to force a refresh.
- if ((cache->GetObjectCount() == 0) || (cache->GetSerialNumber() != m_visibilitySerialNumber))
- {
- viewIsDirty = true;
- }
- }
- }
-
- if (viewIsDirty)
- {
- FindDisplayableObjects(dc, true); // this also actually draws the helpers.
-
// Also broadcast for anyone else that needs to draw global debug to do so now
AzFramework::DebugDisplayEventBus::Broadcast(&AzFramework::DebugDisplayEvents::DrawGlobalDebugInfo);
}
@@ -1296,94 +1265,14 @@ void CObjectManager::Display(DisplayContext& dc)
}
}
-void CObjectManager::ForceUpdateVisibleObjectCache(DisplayContext& dc)
+void CObjectManager::ForceUpdateVisibleObjectCache([[maybe_unused]] DisplayContext& dc)
{
- FindDisplayableObjects(dc, false);
+ AZ_Assert(false, "CObjectManager::ForceUpdateVisibleObjectCache is legacy/deprecated and should not be used.");
}
-void CObjectManager::FindDisplayableObjects(DisplayContext& dc, [[maybe_unused]] bool bDisplay)
+void CObjectManager::FindDisplayableObjects([[maybe_unused]] DisplayContext& dc, [[maybe_unused]] bool bDisplay)
{
- // if the new IVisibilitySystem is being used, do not run this logic
- if (ed_visibility_use)
- {
- return;
- }
-
- AZ_PROFILE_FUNCTION(Editor);
-
- auto start = std::chrono::steady_clock::now();
- CBaseObjectsCache* pDispayedViewObjects = dc.view->GetVisibleObjectsCache();
- if (!pDispayedViewObjects)
- {
- return;
- }
-
- pDispayedViewObjects->SetSerialNumber(m_visibilitySerialNumber); // update viewport to be latest serial number
-
- AABB bbox;
- bbox.min.zero();
- bbox.max.zero();
-
- pDispayedViewObjects->ClearObjects();
- pDispayedViewObjects->Reserve(static_cast(m_visibleObjects.size()));
-
- if (dc.flags & DISPLAY_2D)
- {
- int numVis = static_cast(m_visibleObjects.size());
- for (int i = 0; i < numVis; i++)
- {
- CBaseObject* obj = m_visibleObjects[i];
-
- obj->GetBoundBox(bbox);
- if (dc.box.IsIntersectBox(bbox))
- {
- pDispayedViewObjects->AddObject(obj);
- }
- }
- }
- else
- {
- CSelectionGroup* pSelection = GetSelection();
- if (pSelection && pSelection->GetCount() > 1)
- {
- AABB mergedAABB;
- mergedAABB.Reset();
- for (int i = 0, iCount(pSelection->GetCount()); i < iCount; ++i)
- {
- CBaseObject* pObj(pSelection->GetObject(i));
- if (pObj == nullptr)
- {
- continue;
- }
- AABB aabb;
- pObj->GetBoundBox(aabb);
- mergedAABB.Add(aabb);
- }
-
- pSelection->GetObject(0)->CBaseObject::DrawDimensions(dc, &mergedAABB);
- }
-
- int numVis = static_cast(m_visibleObjects.size());
- for (int i = 0; i < numVis; i++)
- {
- CBaseObject* obj = m_visibleObjects[i];
-
- if (obj)
- {
- if ((dc.flags & DISPLAY_SELECTION_HELPERS) || obj->IsSelected())
- {
- pDispayedViewObjects->AddObject(obj);
- }
- }
- }
- }
-
- if (ed_visibility_logTiming && !ed_visibility_use)
- {
- auto stop = std::chrono::steady_clock::now();
- std::chrono::duration diff = stop - start;
- AZ_Printf("Visibility", "FindDisplayableObjects (old) - Duration: %f", diff);
- }
+ AZ_Assert(false, "CObjectManager::FindDisplayableObjects is legacy/deprecated and should not be used.");
}
void CObjectManager::BeginEditParams(CBaseObject* obj, int flags)
@@ -1630,214 +1519,24 @@ bool CObjectManager::HitTestObject(CBaseObject* obj, HitContext& hc)
return (bSelectionHelperHit || obj->HitTest(hc));
}
-
//////////////////////////////////////////////////////////////////////////
-bool CObjectManager::HitTest(HitContext& hitInfo)
+bool CObjectManager::HitTest([[maybe_unused]] HitContext& hitInfo)
{
- AZ_PROFILE_FUNCTION(Editor);
-
- hitInfo.object = nullptr;
- hitInfo.dist = FLT_MAX;
- hitInfo.axis = 0;
- hitInfo.manipulatorMode = 0;
-
- HitContext hcOrg = hitInfo;
- if (hcOrg.view)
- {
- hcOrg.view->GetPerpendicularAxis(nullptr, &hcOrg.b2DViewport);
- }
- hcOrg.rayDir = hcOrg.rayDir.GetNormalized();
-
- HitContext hc = hcOrg;
-
- float mindist = FLT_MAX;
-
- if (!hitInfo.bIgnoreAxis && !hc.bUseSelectionHelpers)
- {
- // Test gizmos.
- if (m_gizmoManager->HitTest(hc))
- {
- if (hc.axis != 0)
- {
- hitInfo.object = hc.object;
- hitInfo.gizmo = hc.gizmo;
- hitInfo.axis = hc.axis;
- hitInfo.manipulatorMode = hc.manipulatorMode;
- hitInfo.dist = hc.dist;
- return true;
- }
- }
- }
-
- if (hitInfo.bOnlyGizmo)
- {
- return false;
- }
-
- // Only HitTest objects, that where previously Displayed.
- CBaseObjectsCache* pDispayedViewObjects = hitInfo.view->GetVisibleObjectsCache();
-
- const bool iconsPrioritized = true; // Force icons to always be prioritized over other things you hit. Can change to be a configurable option in the future.
-
- CBaseObject* selected = nullptr;
- const char* name = nullptr;
- bool iconHit = false;
- int numVis = pDispayedViewObjects->GetObjectCount();
- for (int i = 0; i < numVis; i++)
- {
- CBaseObject* obj = pDispayedViewObjects->GetObject(i);
-
- if (obj == hitInfo.pExcludedObject)
- {
- continue;
- }
-
- if (HitTestObject(obj, hc))
- {
- if (m_selectCallback && !m_selectCallback->CanSelectObject(obj))
- {
- continue;
- }
-
- // Check if this object is nearest.
- if (hc.axis != 0)
- {
- hitInfo.object = obj;
- hitInfo.axis = hc.axis;
- hitInfo.dist = hc.dist;
- return true;
- }
-
- // When prioritizing icons, we don't allow non-icon hits to beat icon hits
- if (iconsPrioritized && iconHit && !hc.iconHit)
- {
- continue;
- }
-
- if (hc.dist < mindist || (!iconHit && hc.iconHit))
- {
- if (hc.iconHit)
- {
- iconHit = true;
- }
-
- mindist = hc.dist;
- name = hc.name;
- selected = obj;
- }
-
- // Clear the object pointer if an object was hit, not just if the collision
- // was closer than any previous. Not all paths from HitTestObject set the object pointer and so you could get
- // an object from a previous (rejected) result but with collision information about a closer hit.
- hc.object = nullptr;
- hc.iconHit = false;
-
- // If use deep selection
- if (hitInfo.pDeepSelection)
- {
- hitInfo.pDeepSelection->AddObject(hc.dist, obj);
- }
- }
- }
-
- if (selected)
- {
- hitInfo.object = selected;
- hitInfo.dist = mindist;
- hitInfo.name = name;
- hitInfo.iconHit = iconHit;
- return true;
- }
+ AZ_Assert(false, "CObjectManager::HitTest is legacy/deprecated and should not be used.");
return false;
}
-void CObjectManager::FindObjectsInRect(CViewport* view, const QRect& rect, std::vector& guids)
-{
- AZ_PROFILE_FUNCTION(Editor);
-
- if (rect.width() < 1 || rect.height() < 1)
- {
- return;
- }
-
- HitContext hc;
- hc.view = view;
- hc.b2DViewport = view->GetType() != ET_ViewportCamera;
- hc.rect = rect;
- hc.bUseSelectionHelpers = view->GetAdvancedSelectModeFlag();
-
- guids.clear();
-
- CBaseObjectsCache* pDispayedViewObjects = view->GetVisibleObjectsCache();
-
- int numVis = pDispayedViewObjects->GetObjectCount();
- for (int i = 0; i < numVis; ++i)
- {
- CBaseObject* pObj = pDispayedViewObjects->GetObject(i);
- HitTestObjectAgainstRect(pObj, view, hc, guids);
- }
+void CObjectManager::FindObjectsInRect(
+ [[maybe_unused]] CViewport* view, [[maybe_unused]] const QRect& rect, [[maybe_unused]] std::vector& guids)
+{
+ AZ_Assert(false, "CObjectManager::FindObjectsInRect is legacy/deprecated and should not be used.");
}
//////////////////////////////////////////////////////////////////////////
-void CObjectManager::SelectObjectsInRect(CViewport* view, const QRect& rect, bool bSelect)
+void CObjectManager::SelectObjectsInRect(
+ [[maybe_unused]] CViewport* view, [[maybe_unused]] const QRect& rect, [[maybe_unused]] bool bSelect)
{
- AZ_PROFILE_FUNCTION(Editor);
-
- // Ignore too small rectangles.
- if (rect.width() < 1 || rect.height() < 1)
- {
- return;
- }
-
- CUndo undo("Select Object(s)");
-
- HitContext hc;
- hc.view = view;
- hc.b2DViewport = view->GetType() != ET_ViewportCamera;
- hc.rect = rect;
- hc.bUseSelectionHelpers = view->GetAdvancedSelectModeFlag();
-
- bool isUndoRecording = GetIEditor()->IsUndoRecording();
- if (isUndoRecording)
- {
- m_processingBulkSelect = true;
- }
-
- CBaseObjectsCache* displayedViewObjects = view->GetVisibleObjectsCache();
- int numVis = displayedViewObjects->GetObjectCount();
-
- // Tracking the previous selection allows proper undo/redo functionality of additional
- // selections (CTRL + drag select)
- AZStd::unordered_set previousSelection;
-
- for (int i = 0; i < numVis; ++i)
- {
- CBaseObject* object = displayedViewObjects->GetObject(i);
-
- if (object->IsSelected())
- {
- previousSelection.insert(object);
- }
- else
- {
- // This will update m_currSelection
- SelectObjectInRect(object, view, hc, bSelect);
-
- // Legacy undo/redo does not go through the Ebus system and must be done individually
- if (isUndoRecording && object->GetType() != OBJTYPE_AZENTITY)
- {
- GetIEditor()->RecordUndo(new CUndoBaseObjectSelect(object, true));
- }
- }
- }
-
- if (isUndoRecording && m_currSelection)
- {
- // Component Entities can handle undo/redo in bulk due to Ebuses
- GetIEditor()->RecordUndo(new CUndoBaseObjectBulkSelect(previousSelection, *m_currSelection));
- }
-
- m_processingBulkSelect = false;
+ AZ_Assert(false, "CObjectManager::SelectObjectsInRect is legacy/deprecated and should not be used.");
}
//////////////////////////////////////////////////////////////////////////
@@ -2608,25 +2307,33 @@ void CObjectManager::SelectObjectInRect(CBaseObject* pObj, CViewport* view, HitC
}
}
-void CObjectManager::EnteredComponentMode(const AZStd::vector& /*componentModeTypes*/)
+void CObjectManager::OnEditorModeActivated(
+ [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
{
- // hide current gizmo for entity (translate/rotate/scale)
- IGizmoManager* gizmoManager = GetGizmoManager();
- const size_t gizmoCount = static_cast(gizmoManager->GetGizmoCount());
- for (size_t i = 0; i < gizmoCount; ++i)
+ if (mode == AzToolsFramework::ViewportEditorMode::Component)
{
- gizmoManager->RemoveGizmo(gizmoManager->GetGizmoByIndex(static_cast(i)));
+ // hide current gizmo for entity (translate/rotate/scale)
+ IGizmoManager* gizmoManager = GetGizmoManager();
+ const size_t gizmoCount = static_cast(gizmoManager->GetGizmoCount());
+ for (size_t i = 0; i < gizmoCount; ++i)
+ {
+ gizmoManager->RemoveGizmo(gizmoManager->GetGizmoByIndex(static_cast(i)));
+ }
}
}
-void CObjectManager::LeftComponentMode(const AZStd::vector& /*componentModeTypes*/)
+void CObjectManager::OnEditorModeDeactivated(
+ [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
{
- // show translate/rotate/scale gizmo again
- if (IGizmoManager* gizmoManager = GetGizmoManager())
+ if (mode == AzToolsFramework::ViewportEditorMode::Component)
{
- if (CBaseObject* selectedObject = GetIEditor()->GetSelectedObject())
+ // show translate/rotate/scale gizmo again
+ if (IGizmoManager* gizmoManager = GetGizmoManager())
{
- gizmoManager->AddGizmo(new CAxisGizmo(selectedObject));
+ if (CBaseObject* selectedObject = GetIEditor()->GetSelectedObject())
+ {
+ gizmoManager->AddGizmo(new CAxisGizmo(selectedObject));
+ }
}
}
}
@@ -3011,6 +2718,4 @@ namespace AzToolsFramework
}
}
-}
-
-
+} // namespace AzToolsFramework
diff --git a/Code/Editor/Objects/ObjectManager.h b/Code/Editor/Objects/ObjectManager.h
index 4ffa5e9a07..7fb2342e40 100644
--- a/Code/Editor/Objects/ObjectManager.h
+++ b/Code/Editor/Objects/ObjectManager.h
@@ -20,8 +20,9 @@
#include "ObjectManagerEventBus.h"
#include
-#include
+#include
#include
+#include
#include
// forward declarations.
@@ -52,47 +53,13 @@ public:
}
};
-//////////////////////////////////////////////////////////////////////////
-// Array of editor objects.
-//////////////////////////////////////////////////////////////////////////
-class CBaseObjectsCache
-{
-public:
- int GetObjectCount() const { return static_cast(m_objects.size()); }
- CBaseObject* GetObject(int nIndex) const { return m_objects[nIndex]; }
- void AddObject(CBaseObject* object);
-
- void ClearObjects()
- {
- m_objects.clear();
- m_entityIds.clear();
- }
-
- void Reserve(int nCount)
- {
- m_objects.reserve(nCount);
- m_entityIds.reserve(nCount);
- }
-
- const AZStd::vector& GetEntityIdCache() const { return m_entityIds; }
-
- /// Checksum is used as a dirty flag.
- unsigned int GetSerialNumber() { return m_serialNumber; }
- void SetSerialNumber(unsigned int serialNumber) { m_serialNumber = serialNumber; }
-private:
- //! List of objects that was displayed at last frame.
- std::vector<_smart_ptr > m_objects;
- AZStd::vector m_entityIds;
- unsigned int m_serialNumber = 0;
-};
-
/*!
* CObjectManager is a singleton object that
* manages global set of objects in level.
*/
class CObjectManager
: public IObjectManager
- , private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
+ , private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler
{
public:
//! Selection functor callback.
@@ -363,9 +330,11 @@ private:
void FindDisplayableObjects(DisplayContext& dc, bool bDisplay);
- // EditorComponentModeNotificationBus
- void EnteredComponentMode(const AZStd::vector& componentModeTypes) override;
- void LeftComponentMode(const AZStd::vector& componentModeTypes) override;
+ // ViewportEditorModeNotificationsBus overrides ...
+ void OnEditorModeActivated(
+ const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
+ void OnEditorModeDeactivated(
+ const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
private:
typedef std::map Objects;
diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp
index 666700a874..41e950a058 100644
--- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp
+++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp
@@ -142,8 +142,7 @@ void GetSelectedEntitiesSetWithFlattenedHierarchy(AzToolsFramework::EntityIdSet&
}
SandboxIntegrationManager::SandboxIntegrationManager()
- : m_inObjectPickMode(false)
- , m_startedUndoRecordingNestingLevel(0)
+ : m_startedUndoRecordingNestingLevel(0)
, m_dc(nullptr)
, m_notificationWindowManager(new AzToolsFramework::SliceOverridesNotificationWindowManager())
{
@@ -1000,62 +999,6 @@ void SandboxIntegrationManager::SetupSliceContextMenu_Modify(QMenu* menu, const
revertAction->setEnabled(canRevert);
}
-void SandboxIntegrationManager::HandleObjectModeSelection(const AZ::Vector2& point, [[maybe_unused]] int flags, bool& handled)
-{
- // Todo - Use a custom "edit tool". This will eliminate the need for this bus message entirely, which technically
- // makes this feature less intrusive on Sandbox.
- // UPDATE: This is now provided by EditorPickEntitySelection when the new Viewport Interaction Model changes are enabled.
- if (m_inObjectPickMode)
- {
- CViewport* view = GetIEditor()->GetViewManager()->GetGameViewport();
- const QPoint viewPoint(static_cast(point.GetX()), static_cast(point.GetY()));
-
- HitContext hitInfo;
- hitInfo.view = view;
- if (view->HitTest(viewPoint, hitInfo))
- {
- if (hitInfo.object && (hitInfo.object->GetType() == OBJTYPE_AZENTITY))
- {
- CComponentEntityObject* entityObject = static_cast(hitInfo.object);
- AzToolsFramework::EditorPickModeRequestBus::Broadcast(
- &AzToolsFramework::EditorPickModeRequests::PickModeSelectEntity, entityObject->GetAssociatedEntityId());
- }
- }
-
- AzToolsFramework::EditorPickModeRequestBus::Broadcast(
- &AzToolsFramework::EditorPickModeRequests::StopEntityPickMode);
-
- handled = true;
- }
-}
-
-void SandboxIntegrationManager::UpdateObjectModeCursor(AZ::u32& cursorId, AZStd::string& cursorStr)
-{
- if (m_inObjectPickMode)
- {
- cursorId = static_cast(STD_CURSOR_HAND);
- cursorStr = "Pick an entity...";
- }
-}
-
-void SandboxIntegrationManager::OnEntityPickModeStarted()
-{
- m_inObjectPickMode = true;
-
- // Currently this object pick mode is activated only via PropertyEntityIdCtrl picker.
- // When the picker button is clicked, we transfer focus to the viewport so the
- // spacebar can still be used to activate selection helpers.
- if (CViewport* view = GetIEditor()->GetViewManager()->GetGameViewport())
- {
- view->SetFocus();
- }
-}
-
-void SandboxIntegrationManager::OnEntityPickModeStopped()
-{
- m_inObjectPickMode = false;
-}
-
void SandboxIntegrationManager::CreateEditorRepresentation(AZ::Entity* entity)
{
IEditor* editor = GetIEditor();
@@ -1952,7 +1895,7 @@ void SandboxIntegrationManager::MakeSliceFromEntities(const AzToolsFramework::En
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(entitiesAndDescendants,
&AzToolsFramework::ToolsApplicationRequestBus::Events::GatherEntitiesAndAllDescendents, entities);
- const AZStd::string slicesAssetsPath = "@devassets@/Slices";
+ const AZStd::string slicesAssetsPath = "@projectroot@/Slices";
if (!gEnv->pFileIO->Exists(slicesAssetsPath.c_str()))
{
diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h
index 617c5cb2c8..40962409a3 100644
--- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h
+++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h
@@ -93,7 +93,6 @@ namespace AzToolsFramework
class SandboxIntegrationManager
: private AzToolsFramework::ToolsApplicationEvents::Bus::Handler
, private AzToolsFramework::EditorRequests::Bus::Handler
- , private AzToolsFramework::EditorPickModeNotificationBus::Handler
, private AzToolsFramework::EditorContextMenuBus::Handler
, private AzToolsFramework::EditorWindowRequests::Bus::Handler
, private AzFramework::AssetCatalogEventBus::Handler
@@ -140,8 +139,6 @@ private:
QDockWidget* InstanceViewPane(const char* paneName) override;
void CloseViewPane(const char* paneName) override;
void BrowseForAssets(AzToolsFramework::AssetBrowser::AssetSelectionModel& selection) override;
- void HandleObjectModeSelection(const AZ::Vector2& point, int flags, bool& handled) override;
- void UpdateObjectModeCursor(AZ::u32& cursorId, AZStd::string& cursorStr) override;
void CreateEditorRepresentation(AZ::Entity* entity) override;
bool DestroyEditorRepresentation(AZ::EntityId entityId, bool deleteAZEntity) override;
void CloneSelection(bool& handled) override;
@@ -175,10 +172,6 @@ private:
QWidget* GetAppMainWindow() override;
//////////////////////////////////////////////////////////////////////////
- // EditorPickModeNotificationBus
- void OnEntityPickModeStarted() override;
- void OnEntityPickModeStopped() override;
-
//////////////////////////////////////////////////////////////////////////
// AzToolsFramework::EditorContextMenu::Bus::Handler overrides
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override;
@@ -281,7 +274,6 @@ private:
private:
AZ::Vector2 m_contextMenuViewPoint;
- int m_inObjectPickMode;
short m_startedUndoRecordingNestingLevel; // used in OnBegin/EndUndo to ensure we only accept undo's we started recording
AzToolsFramework::SliceOverridesNotificationWindowManager* m_notificationWindowManager;
diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp
index 9ed7c4a144..803deb3509 100644
--- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp
+++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp
@@ -36,6 +36,7 @@
#include
#include
#include
+#include
#include
#include
@@ -267,8 +268,7 @@ OutlinerWidget::OutlinerWidget(QWidget* pParent, Qt::WindowFlags flags)
ToolsApplicationEvents::Bus::Handler::BusConnect();
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusConnect();
- AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
- AzToolsFramework::GetEntityContextId());
+ AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId());
AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusConnect();
AzToolsFramework::EditorWindowUIRequestBus::Handler::BusConnect();
}
@@ -276,7 +276,7 @@ OutlinerWidget::OutlinerWidget(QWidget* pParent, Qt::WindowFlags flags)
OutlinerWidget::~OutlinerWidget()
{
AzToolsFramework::EditorWindowUIRequestBus::Handler::BusDisconnect();
- AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
+ AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusDisconnect();
AzToolsFramework::EditorPickModeNotificationBus::Handler::BusDisconnect();
EntityHighlightMessages::Bus::Handler::BusDisconnect();
@@ -1335,14 +1335,22 @@ void OutlinerWidget::SetEditorUiEnabled(bool enable)
EnableUi(enable);
}
-void OutlinerWidget::EnteredComponentMode([[maybe_unused]] const AZStd::vector& componentModeTypes)
+void OutlinerWidget::OnEditorModeActivated(
+ [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
{
- EnableUi(false);
+ if (mode == AzToolsFramework::ViewportEditorMode::Component)
+ {
+ EnableUi(false);
+ }
}
-void OutlinerWidget::LeftComponentMode([[maybe_unused]] const AZStd::vector& componentModeTypes)
+void OutlinerWidget::OnEditorModeDeactivated(
+ [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
{
- EnableUi(true);
+ if (mode == AzToolsFramework::ViewportEditorMode::Component)
+ {
+ EnableUi(true);
+ }
}
void OutlinerWidget::OnSliceInstantiated(const AZ::Data::AssetId& /*sliceAssetId*/, AZ::SliceComponent::SliceInstanceAddress& sliceAddress, const AzFramework::SliceInstantiationTicket& /*ticket*/)
diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.hxx b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.hxx
index b29032a760..364ab05eb7 100644
--- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.hxx
+++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.hxx
@@ -16,7 +16,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -58,7 +58,7 @@ class OutlinerWidget
, private AzToolsFramework::EditorEntityContextNotificationBus::Handler
, private AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler
, private AzToolsFramework::EditorEntityInfoNotificationBus::Handler
- , private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
+ , private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler
, private AzToolsFramework::EditorWindowUIRequestBus::Handler
{
Q_OBJECT;
@@ -105,9 +105,11 @@ private:
void OnEntityInfoUpdatedAddChildEnd(AZ::EntityId /*parentId*/, AZ::EntityId /*childId*/) override;
void OnEntityInfoUpdatedName(AZ::EntityId entityId, const AZStd::string& /*name*/) override;
- // EditorComponentModeNotificationBus
- void EnteredComponentMode(const AZStd::vector& componentModeTypes) override;
- void LeftComponentMode(const AZStd::vector& componentModeTypes) override;
+ // ViewportEditorModeNotificationsBus overrides ...
+ void OnEditorModeActivated(
+ const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
+ void OnEditorModeDeactivated(
+ const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
// EditorWindowUIRequestBus overrides
void SetEditorUiEnabled(bool enable) override;
diff --git a/Code/Editor/Plugins/EditorAssetImporter/AssetImporterWindow.cpp b/Code/Editor/Plugins/EditorAssetImporter/AssetImporterWindow.cpp
index 98bf228391..0ff9467f33 100644
--- a/Code/Editor/Plugins/EditorAssetImporter/AssetImporterWindow.cpp
+++ b/Code/Editor/Plugins/EditorAssetImporter/AssetImporterWindow.cpp
@@ -30,6 +30,7 @@ class CXTPDockingPaneLayout; // Needed for settings.h
#include
#include
#include
+#include
#include
#include
#include
@@ -47,41 +48,6 @@ class CXTPDockingPaneLayout; // Needed for settings.h
const char* AssetImporterWindow::s_documentationWebAddress = "http://docs.aws.amazon.com/lumberyard/latest/userguide/char-fbx-importer.html";
const AZ::Uuid AssetImporterWindow::s_browseTag = AZ::Uuid::CreateString("{C240D2E1-BFD2-4FFA-BB5B-CC0FA389A5D3}");
-void MakeUserFriendlySourceAssetPath(QString& out, const QString& sourcePath)
-{
- char devAssetsRoot[AZ_MAX_PATH_LEN] = { 0 };
- if (!gEnv->pFileIO->ResolvePath("@devroot@", devAssetsRoot, AZ_MAX_PATH_LEN))
- {
- out = sourcePath;
- return;
- }
-
- AZStd::replace(devAssetsRoot, devAssetsRoot + AZ_MAX_PATH_LEN- 1, AZ_WRONG_FILESYSTEM_SEPARATOR, AZ_CORRECT_FILESYSTEM_SEPARATOR);
-
- // Find if the sourcePathArray is a sub directory of the devAssets folder
- // Keep reference to sourcePathArray long enough to use in PathView
- QByteArray sourcePathArray = sourcePath.toUtf8();
- AZ::IO::PathView sourcePathRootView(sourcePathArray.data());
- AZ::IO::PathView devAssetsRootView(devAssetsRoot);
- auto [sourcePathIter, devAssetsIter] = AZStd::mismatch(sourcePathRootView.begin(), sourcePathRootView.end(),
- devAssetsRootView.begin(), devAssetsRootView.end());
- // If the devAssets path iterator is not equal to the end, then there was a mismistch while comparing it
- // against the source path indicating that the source path is not a sub-directory
- if (devAssetsIter != devAssetsRootView.end())
- {
- out = sourcePath;
- return;
- }
-
- int offset = aznumeric_cast(strlen(devAssetsRoot));
- if (sourcePath.at(offset) == AZ_CORRECT_FILESYSTEM_SEPARATOR)
- {
- ++offset;
- }
- out = sourcePath.right(sourcePath.length() - offset);
-
-}
-
AssetImporterWindow::AssetImporterWindow()
: AssetImporterWindow(nullptr)
{
@@ -102,7 +68,7 @@ AssetImporterWindow::AssetImporterWindow(QWidget* parent)
AssetImporterWindow::~AssetImporterWindow()
{
- AZ_Assert(m_processingOverlayIndex == AZ::SceneAPI::UI::OverlayWidget::s_invalidOverlayIndex,
+ AZ_Assert(m_processingOverlayIndex == AZ::SceneAPI::UI::OverlayWidget::s_invalidOverlayIndex,
"Processing overlay (and potentially background thread) still active at destruction.");
AZ_Assert(!m_processingOverlay, "Processing overlay (and potentially background thread) still active at destruction.");
}
@@ -133,7 +99,7 @@ void AssetImporterWindow::OpenFile(const AZStd::string& filePath)
QMessageBox::warning(this, "In progress", "Unable to close one or more windows at this time.");
return;
}
-
+
OpenFileInternal(filePath);
}
@@ -146,7 +112,7 @@ void AssetImporterWindow::closeEvent(QCloseEvent* ev)
if (m_processingOverlay)
{
- AZ_Assert(m_processingOverlayIndex != AZ::SceneAPI::UI::OverlayWidget::s_invalidOverlayIndex,
+ AZ_Assert(m_processingOverlayIndex != AZ::SceneAPI::UI::OverlayWidget::s_invalidOverlayIndex,
"Processing overlay present, but not the index in the overlay for it.");
if (m_processingOverlay->HasProcessingCompleted())
{
@@ -157,7 +123,7 @@ void AssetImporterWindow::closeEvent(QCloseEvent* ev)
}
else
{
- QMessageBox::critical(this, "Processing In Progress", "Unable to close the result window at this time.",
+ QMessageBox::critical(this, "Processing In Progress", "Unable to close the result window at this time.",
QMessageBox::Ok, QMessageBox::Ok);
ev->ignore();
return;
@@ -165,7 +131,7 @@ void AssetImporterWindow::closeEvent(QCloseEvent* ev)
}
else
{
- QMessageBox::critical(this, "Processing In Progress", "Please wait until processing has completed to try again.",
+ QMessageBox::critical(this, "Processing In Progress", "Please wait until processing has completed to try again.",
QMessageBox::Ok, QMessageBox::Ok);
ev->ignore();
return;
@@ -199,7 +165,9 @@ void AssetImporterWindow::Init()
// Load the style sheets
AzQtComponents::StylesheetPreprocessor styleSheetProcessor(nullptr);
- AZStd::string mainWindowQSSPath = Path::GetEditingRootFolder() + "\\Editor\\Styles\\AssetImporterWindow.qss";
+ auto mainWindowQSSPath = AZ::IO::Path(AZ::Utils::GetEnginePath()) / "Assets";
+ mainWindowQSSPath /= "Editor/Styles/AssetImporterWindow.qss";
+ mainWindowQSSPath.MakePreferred();
QFile mainWindowStyleSheetFile(mainWindowQSSPath.c_str());
if (mainWindowStyleSheetFile.open(QFile::ReadOnly))
{
@@ -212,7 +180,7 @@ void AssetImporterWindow::Init()
{
ui->m_actionInspect->setVisible(false);
}
-
+
ResetMenuAccess(WindowState::InitialNothingLoaded);
// Setup the overlay system, and set the root to be the root display. The root display has the browse,
@@ -220,7 +188,7 @@ void AssetImporterWindow::Init()
m_overlay.reset(aznew AZ::SceneAPI::UI::OverlayWidget(this));
m_rootDisplay.reset(aznew ImporterRootDisplay(m_serializeContext));
connect(m_rootDisplay.data(), &ImporterRootDisplay::UpdateClicked, this, &AssetImporterWindow::UpdateClicked);
-
+
connect(m_overlay.data(), &AZ::SceneAPI::UI::OverlayWidget::LayerAdded, this, &AssetImporterWindow::OverlayLayerAdded);
connect(m_overlay.data(), &AZ::SceneAPI::UI::OverlayWidget::LayerRemoved, this, &AssetImporterWindow::OverlayLayerRemoved);
@@ -242,7 +210,7 @@ void AssetImporterWindow::Init()
AZStd::string joinedExtensions;
AzFramework::StringFunc::Join(joinedExtensions, extensions.begin(), extensions.end(), " or ");
- AZStd::string firstLineText =
+ AZStd::string firstLineText =
AZStd::string::format(
"%s files are available for use after placing them in any folder within your game project. "
"These files will automatically be processed and may be accessed via the Asset Browser. Learn more...",
@@ -250,13 +218,13 @@ void AssetImporterWindow::Init()
ui->m_initialPromptFirstLine->setText(firstLineText.c_str());
- AZStd::string secondLineText =
+ AZStd::string secondLineText =
AZStd::string::format("To adjust the %s settings, right-click the file in the Asset Browser and select \"Edit Settings\" from the context menu.", joinedExtensions.c_str());
ui->m_initialPromptSecondLine->setText(secondLineText.c_str());
}
else
{
- AZStd::string firstLineText =
+ AZStd::string firstLineText =
AZStd::string::format(
"Files are available for use after placing them in any folder within your game project. "
"These files will automatically be processed and may be accessed via the Asset Browser. Learn more...", s_documentationWebAddress);
@@ -282,12 +250,12 @@ void AssetImporterWindow::OpenFileInternal(const AZStd::string& filePath)
auto asyncLoadHandler = AZStd::make_shared(
s_browseTag,
[this, filePath]()
- {
- m_assetImporterDocument->LoadScene(filePath);
+ {
+ m_assetImporterDocument->LoadScene(filePath);
},
[this]()
{
- HandleAssetLoadingCompleted();
+ HandleAssetLoadingCompleted();
}, this);
m_processingOverlay.reset(new ProcessingOverlayWidget(m_overlay.data(), ProcessingOverlayWidget::Layout::Loading, s_browseTag));
@@ -304,7 +272,7 @@ bool AssetImporterWindow::IsAllowedToChangeSourceFile()
return true;
}
- QMessageBox messageBox(QMessageBox::Icon::NoIcon, "Unsaved changes",
+ QMessageBox messageBox(QMessageBox::Icon::NoIcon, "Unsaved changes",
"You have unsaved changes. Do you want to discard those changes?",
QMessageBox::StandardButton::Discard | QMessageBox::StandardButton::Cancel, this);
messageBox.exec();
@@ -406,7 +374,7 @@ void AssetImporterWindow::OnSceneResetRequested()
else
{
m_assetImporterDocument->ClearScene();
- AZ_TracePrintf(ErrorWindow, "Manifest reset returned in '%s'",
+ AZ_TracePrintf(ErrorWindow, "Manifest reset returned in '%s'",
result.GetResult() == ProcessingResult::Failure ? "Failure" : "Ignored");
}
},
@@ -456,7 +424,7 @@ void AssetImporterWindow::OnInspect()
// make sure the inspector doesn't outlive the AssetImporterWindow, since we own the data it will be inspecting.
auto* theInspectWidget = aznew AZ::SceneAPI::UI::SceneGraphInspectWidget(*m_assetImporterDocument->GetScene());
QObject::connect(this, &QObject::destroyed, theInspectWidget, [theInspectWidget]() { theInspectWidget->window()->close(); } );
-
+
m_overlay->PushLayer(label, theInspectWidget, "Scene Inspector", buttons);
}
@@ -483,7 +451,7 @@ void AssetImporterWindow::OverlayLayerRemoved()
else
{
ResetMenuAccess(WindowState::InitialNothingLoaded);
-
+
ui->m_initialBrowseContainer->show();
m_rootDisplay->hide();
}
@@ -533,8 +501,9 @@ void AssetImporterWindow::HandleAssetLoadingCompleted()
m_fullSourcePath = m_assetImporterDocument->GetScene()->GetSourceFilename();
SetTitle(m_fullSourcePath.c_str());
- QString userFriendlyFileName;
- MakeUserFriendlySourceAssetPath(userFriendlyFileName, m_fullSourcePath.c_str());
+ AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
+ AZ::IO::FixedMaxPath relativeSourcePath = AZ::IO::PathView(m_fullSourcePath).LexicallyProximate(projectPath);
+ auto userFriendlyFileName = QString::fromUtf8(relativeSourcePath.c_str(), static_cast(relativeSourcePath.Native().size()));
m_rootDisplay->SetSceneDisplay(userFriendlyFileName, m_assetImporterDocument->GetScene());
// Once we've browsed to something successfully, we need to hide the initial browse button layer and
diff --git a/Code/Editor/Plugins/EditorAssetImporter/SceneSerializationHandler.cpp b/Code/Editor/Plugins/EditorAssetImporter/SceneSerializationHandler.cpp
index b1d07af41c..5ee54667b9 100644
--- a/Code/Editor/Plugins/EditorAssetImporter/SceneSerializationHandler.cpp
+++ b/Code/Editor/Plugins/EditorAssetImporter/SceneSerializationHandler.cpp
@@ -7,9 +7,11 @@
*/
#include
+#include
#include
#include
#include
+#include
#include
#include
#include
@@ -50,22 +52,15 @@ namespace AZ
return nullptr;
}
- AZStd::string cleanPath = filePath;
- if (AzFramework::StringFunc::Path::IsRelative(filePath.c_str()))
+ AZ::IO::Path enginePath;
+ if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
- const char* absolutePath = nullptr;
- AzToolsFramework::AssetSystemRequestBus::BroadcastResult(absolutePath,
- &AzToolsFramework::AssetSystemRequestBus::Events::GetAbsoluteDevRootFolderPath);
- AZ_Assert(absolutePath, "Unable to retrieve the dev folder path");
- AzFramework::StringFunc::Path::Join(absolutePath, cleanPath.c_str(), cleanPath);
- }
- else
- {
- // Normalizing is not needed if the path is relative as Join(...) will also normalize.
- AzFramework::StringFunc::Path::Normalize(cleanPath);
+ settingsRegistry->Get(enginePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
}
- auto sceneIt = m_scenes.find(cleanPath);
+ AZ::IO::Path cleanPath = (enginePath / filePath).LexicallyNormal();
+
+ auto sceneIt = m_scenes.find(cleanPath.Native());
if (sceneIt != m_scenes.end())
{
AZStd::shared_ptr scene = sceneIt->second.lock();
@@ -98,14 +93,14 @@ namespace AZ
}
AZStd::shared_ptr scene =
- AssetImportRequest::LoadSceneFromVerifiedPath(cleanPath, sceneSourceGuid, AssetImportRequest::RequestingApplication::Editor, SceneAPI::SceneCore::LoadingComponent::TYPEINFO_Uuid());
+ AssetImportRequest::LoadSceneFromVerifiedPath(cleanPath.Native(), sceneSourceGuid, AssetImportRequest::RequestingApplication::Editor, SceneAPI::SceneCore::LoadingComponent::TYPEINFO_Uuid());
if (!scene)
{
AZ_TracePrintf(Utilities::ErrorWindow, "Failed to load the requested scene.");
return nullptr;
}
- m_scenes.emplace(AZStd::move(cleanPath), scene);
+ m_scenes.emplace(AZStd::move(cleanPath.Native()), scene);
return scene;
}
diff --git a/Code/Editor/Plugins/EditorCommon/CMakeLists.txt b/Code/Editor/Plugins/EditorCommon/CMakeLists.txt
index cd9f2e79c7..609482b581 100644
--- a/Code/Editor/Plugins/EditorCommon/CMakeLists.txt
+++ b/Code/Editor/Plugins/EditorCommon/CMakeLists.txt
@@ -39,7 +39,6 @@ ly_add_target(
EDITOR_COMMON_IMPORTS
BUILD_DEPENDENCIES
PRIVATE
- 3rdParty::zlib
3rdParty::Qt::Core
3rdParty::Qt::Widgets
Legacy::CryCommon
diff --git a/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsToolWindow.cpp b/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsToolWindow.cpp
index 6b454474be..a53ce966c4 100644
--- a/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsToolWindow.cpp
+++ b/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsToolWindow.cpp
@@ -46,7 +46,6 @@ namespace ProjectSettingsTool
, LastPathBus::Handler()
, m_ui(new Ui::ProjectSettingsToolWidget())
, m_reconfigureProcess()
- , m_devRoot(GetDevRoot())
, m_projectRoot(GetProjectRoot())
, m_projectName(GetProjectName())
, m_plistsInitVector(
diff --git a/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsToolWindow.h b/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsToolWindow.h
index 1c9aa4b1bf..daa5bea27c 100644
--- a/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsToolWindow.h
+++ b/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsToolWindow.h
@@ -147,7 +147,6 @@ namespace ProjectSettingsTool
// The process used to reconfigure settings
QProcess m_reconfigureProcess;
- AZStd::string m_devRoot;
AZStd::string m_projectRoot;
AZStd::string m_projectName;
diff --git a/Code/Editor/Plugins/ProjectSettingsTool/Utils.cpp b/Code/Editor/Plugins/ProjectSettingsTool/Utils.cpp
index 0e171adf04..d5b94469cc 100644
--- a/Code/Editor/Plugins/ProjectSettingsTool/Utils.cpp
+++ b/Code/Editor/Plugins/ProjectSettingsTool/Utils.cpp
@@ -27,37 +27,31 @@ namespace
}
template
- StringType GetAbsoluteDevRoot()
+ StringType GetAbsoluteEngineRoot()
{
- const char* devRoot = nullptr;
- AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
- devRoot,
- &AzToolsFramework::AssetSystemRequestBus::Handler::GetAbsoluteDevRootFolderPath);
+ AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
- if (!devRoot)
+ if (engineRoot.empty())
{
return "";
}
- StringType devRootString(devRoot);
- ToUnixPath(devRootString);
- return devRootString;
+ StringType engineRootString(engineRoot.c_str());
+ ToUnixPath(engineRootString);
+ return engineRootString;
}
template
StringType GetAbsoluteProjectRoot()
{
- const char* projectRoot = nullptr;
- AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
- projectRoot,
- &AzToolsFramework::AssetSystemRequestBus::Handler::GetAbsoluteDevGameFolderPath);
+ AZ::IO::FixedMaxPath projectRoot = AZ::Utils::GetProjectPath();
- if (!projectRoot)
+ if (projectRoot.empty())
{
return "";
}
- StringType projectRootString(projectRoot);
+ StringType projectRootString(projectRoot.c_str());
ToUnixPath(projectRootString);
return projectRootString;
}
@@ -87,9 +81,9 @@ namespace ProjectSettingsTool
return reinterpret_cast(func);
}
- AZStd::string GetDevRoot()
+ AZStd::string GetEngineRoot()
{
- return GetAbsoluteDevRoot();
+ return GetAbsoluteEngineRoot();
}
AZStd::string GetProjectRoot()
{
@@ -104,7 +98,7 @@ namespace ProjectSettingsTool
QString SelectXmlFromFileDialog(const QString& currentFile)
{
// The selected file must be relative to this path
- QString defaultPath = GetAbsoluteDevRoot();
+ QString defaultPath = GetAbsoluteEngineRoot();
QString startPath;
// Choose the starting path for file dialog
@@ -139,7 +133,7 @@ namespace ProjectSettingsTool
QString SelectImageFromFileDialog(const QString& currentFile)
{
- QString defaultPath = QStringLiteral("%1Code%2/Resources/").arg(GetAbsoluteDevRoot(), ::GetProjectName());
+ QString defaultPath = QStringLiteral("%1Code%2/Resources/").arg(GetAbsoluteEngineRoot(), ::GetProjectName());
QString startPath;
@@ -188,7 +182,7 @@ namespace ProjectSettingsTool
// Android
if (group <= ImageGroup::AndroidPortrait)
{
- root = GetDevRoot() + "/Code/Tools/Android/ProjectBuilder/app_";
+ root = GetEngineRoot() + "/Code/Tools/Android/ProjectBuilder/app_";
}
//Ios
else
diff --git a/Code/Editor/Plugins/ProjectSettingsTool/Utils.h b/Code/Editor/Plugins/ProjectSettingsTool/Utils.h
index 4226d534a6..050fb3b85b 100644
--- a/Code/Editor/Plugins/ProjectSettingsTool/Utils.h
+++ b/Code/Editor/Plugins/ProjectSettingsTool/Utils.h
@@ -17,7 +17,7 @@
namespace ProjectSettingsTool
{
void* ConvertFunctorToVoid(AZStd::pair(*func)(const QString&));
- AZStd::string GetDevRoot();
+ AZStd::string GetEngineRoot();
AZStd::string GetProjectRoot();
AZStd::string GetProjectName();
diff --git a/Code/Editor/QtViewPaneManager.cpp b/Code/Editor/QtViewPaneManager.cpp
index eff3a7331e..1ac4b9cfe3 100644
--- a/Code/Editor/QtViewPaneManager.cpp
+++ b/Code/Editor/QtViewPaneManager.cpp
@@ -37,6 +37,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -44,11 +45,54 @@
#include
#include
#include
-
#include
#include "ShortcutDispatcher.h"
+// Helper for EditorComponentModeNotifications to be used
+// as a member instead of inheriting from EBus directly.
+class ViewportEditorModeNotificationsBusImpl
+ : public AzToolsFramework::ViewportEditorModeNotificationsBus::Handler
+{
+ public:
+ // Set the function to be called when entering ComponentMode.
+ void SetEnteredComponentModeFunc(
+ const AZStd::function& enteredComponentModeFunc)
+ {
+ m_enteredComponentModeFunc = enteredComponentModeFunc;
+ }
+
+ // Set the function to be called when leaving ComponentMode.
+ void SetLeftComponentModeFunc(
+ const AZStd::function& leftComponentModeFunc)
+ {
+ m_leftComponentModeFunc = leftComponentModeFunc;
+ }
+
+ private:
+ // ViewportEditorModeNotificationsBus overrides ...
+ void OnEditorModeActivated(
+ const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override
+ {
+ if (mode == AzToolsFramework::ViewportEditorMode::Component)
+ {
+ m_enteredComponentModeFunc(editorModeState);
+ }
+ }
+
+ void OnEditorModeDeactivated(
+ const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override
+ {
+ if (mode == AzToolsFramework::ViewportEditorMode::Component)
+ {
+ m_leftComponentModeFunc(editorModeState);
+ }
+ }
+
+ AZStd::function m_enteredComponentModeFunc; ///< Function to call when entering ComponentMode.
+ AZStd::function m_leftComponentModeFunc; ///< Function to call when leaving ComponentMode.
+};
+
struct ViewLayoutState
{
QVector viewPanes;
@@ -519,16 +563,17 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent)
, m_settings(nullptr)
, m_restoreInProgress(false)
, m_advancedDockManager(nullptr)
+ , m_componentModeNotifications(AZStd::make_unique())
{
qRegisterMetaTypeStreamOperators("ViewLayoutState");
qRegisterMetaTypeStreamOperators >("QVector");
// view pane manager is interested when we enter/exit ComponentMode
- m_componentModeNotifications.BusConnect(AzToolsFramework::GetEntityContextId());
+ m_componentModeNotifications->BusConnect(AzToolsFramework::GetEntityContextId());
m_windowRequest.BusConnect();
- m_componentModeNotifications.SetEnteredComponentModeFunc(
- [this](const AZStd::vector& /*componentModeTypes*/)
+ m_componentModeNotifications->SetEnteredComponentModeFunc(
+ [this](const AzToolsFramework::ViewportEditorModesInterface&)
{
// gray out panels when entering ComponentMode
SetDefaultActionsEnabled(false, m_registeredPanes, [](QWidget* widget, bool on)
@@ -537,8 +582,8 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent)
});
});
- m_componentModeNotifications.SetLeftComponentModeFunc(
- [this](const AZStd::vector& /*componentModeTypes*/)
+ m_componentModeNotifications->SetLeftComponentModeFunc(
+ [this](const AzToolsFramework::ViewportEditorModesInterface&)
{
// enable panels again when leaving ComponentMode
SetDefaultActionsEnabled(true, m_registeredPanes, [](QWidget* widget, bool on)
@@ -563,7 +608,7 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent)
QtViewPaneManager::~QtViewPaneManager()
{
m_windowRequest.BusDisconnect();
- m_componentModeNotifications.BusDisconnect();
+ m_componentModeNotifications->BusDisconnect();
}
static bool lessThan(const QtViewPane& v1, const QtViewPane& v2)
diff --git a/Code/Editor/QtViewPaneManager.h b/Code/Editor/QtViewPaneManager.h
index 3ad1cc9cf7..0515ae726e 100644
--- a/Code/Editor/QtViewPaneManager.h
+++ b/Code/Editor/QtViewPaneManager.h
@@ -17,7 +17,6 @@
#include
#include
#include
-#include
#include
#include
@@ -34,6 +33,7 @@
#endif
class QMainWindow;
+class ViewportEditorModeNotificationsBusImpl;
struct ViewLayoutState;
namespace AzQtComponents
@@ -245,9 +245,9 @@ private:
QPointer m_advancedDockManager;
- using EditorComponentModeNotificationBusImpl = AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBusImpl;
- EditorComponentModeNotificationBusImpl m_componentModeNotifications; //!< Helper for EditorComponentModeNotificationBus so
- //!< QtViewPaneManager does not need to inherit directly from it. */
+ AZStd::unique_ptr
+ m_componentModeNotifications; //!< Helper for EditorComponentModeNotificationBus so
+ //!< QtViewPaneManager does not need to inherit directly from it. */
using EditorWindowRequestBusImpl = AzToolsFramework::EditorWindowRequestBusImpl;
EditorWindowRequestBusImpl m_windowRequest; //!< Helper for EditorWindowRequestBus so
diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp
index 05a6960695..47743d1c42 100644
--- a/Code/Editor/Settings.cpp
+++ b/Code/Editor/Settings.cpp
@@ -935,8 +935,9 @@ void SEditorSettings::LoadDefaultGamePaths()
searchPaths[EDITOR_PATH_MATERIALS].push_back((Path::GetEditingGameDataFolder() + "/Materials").c_str());
}
- AZStd::string iconsPath;
- AZ::StringFunc::Path::Join(Path::GetEditingRootFolder().c_str(), "Editor/UI/Icons", iconsPath);
+ auto iconsPath = AZ::IO::Path(AZ::Utils::GetEnginePath()) / "Assets";
+ iconsPath /= "Editor/UI/Icons";
+ iconsPath.MakePreferred();
searchPaths[EDITOR_PATH_UI_ICONS].push_back(iconsPath.c_str());
}
diff --git a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp
index b510315995..d7901e338a 100644
--- a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp
+++ b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp
@@ -269,7 +269,7 @@ void CSequenceBatchRenderDialog::OnRenderItemSelChange()
// Enable/disable the 'remove'/'update' button properly.
bool bNoSelection = !m_ui->m_renderList->selectionModel()->hasSelection();
m_ui->BATCH_RENDER_REMOVE_SEQ->setEnabled(bNoSelection ? false : true);
-
+
CheckForEnableUpdateButton();
if (bNoSelection)
@@ -360,7 +360,7 @@ void CSequenceBatchRenderDialog::OnRenderItemSelChange()
cvarsText += item.cvars[static_cast(i)];
cvarsText += "\r\n";
}
- m_ui->m_cvarsEdit->setPlainText(cvarsText);
+ m_ui->m_cvarsEdit->setPlainText(cvarsText);
}
void CSequenceBatchRenderDialog::CheckForEnableUpdateButton()
@@ -494,7 +494,7 @@ void CSequenceBatchRenderDialog::OnSavePreset()
}
void CSequenceBatchRenderDialog::stashActiveViewportResolution()
-{
+{
// stash active resolution in global vars
activeViewportWidth = resolutions[0][0];
activeViewportHeight = resolutions[0][1];
@@ -502,7 +502,7 @@ void CSequenceBatchRenderDialog::stashActiveViewportResolution()
if (activeViewport)
{
activeViewport->GetDimensions(&activeViewportWidth, &activeViewportHeight);
- }
+ }
}
void CSequenceBatchRenderDialog::OnGo()
@@ -640,7 +640,7 @@ void CSequenceBatchRenderDialog::OnResolutionSelected()
int defaultH;
const QString currentCustomResText = m_ui->m_resolutionCombo->currentText();
GetResolutionFromCustomResText(currentCustomResText.toStdString().c_str(), defaultW, defaultH);
-
+
CCustomResolutionDlg resDlg(defaultW, defaultH, this);
if (resDlg.exec() == QDialog::Accepted)
{
@@ -752,7 +752,7 @@ bool CSequenceBatchRenderDialog::LoadOutputOptions(const QString& pathname)
{
const QString customResText = resolutionNode->getContent();
m_ui->m_resolutionCombo->setItemText(curSel, customResText);
-
+
GetResolutionFromCustomResText(customResText.toStdString().c_str(), m_customResW, m_customResH);
}
m_ui->m_resolutionCombo->setCurrentIndex(curSel);
@@ -907,12 +907,12 @@ void CSequenceBatchRenderDialog::CaptureItemStart()
folder += "/";
folder += itemText;
- // If this is a relative path, prepend the @assets@ folder to match where the Renderer is going
+ // If this is a relative path, prepend the @products@ folder to match where the Renderer is going
// to dump the frame buffer image captures.
if (AzFramework::StringFunc::Path::IsRelative(folder.toUtf8().data()))
{
AZStd::string absolutePath;
- AZStd::string assetsRoot = AZ::IO::FileIOBase::GetInstance()->GetAlias("@assets@");
+ AZStd::string assetsRoot = AZ::IO::FileIOBase::GetInstance()->GetAlias("@products@");
AzFramework::StringFunc::Path::Join(assetsRoot.c_str(), folder.toUtf8().data(), absolutePath);
folder = absolutePath.c_str();
}
@@ -962,7 +962,7 @@ void CSequenceBatchRenderDialog::CaptureItemStart()
m_renderContext.cvarDisplayInfoBU = cvarDebugInfo->GetIVal();
if (renderItem.disableDebugInfo && cvarDebugInfo->GetIVal())
{
- const int DISPLAY_INFO_OFF = 0;
+ const int DISPLAY_INFO_OFF = 0;
cvarDebugInfo->Set(DISPLAY_INFO_OFF);
}
}
@@ -1100,13 +1100,13 @@ void CSequenceBatchRenderDialog::OnUpdateEnd(IAnimSequence* sequence)
sequence->SetActiveDirector(m_renderContext.pActiveDirectorBU);
const auto imageFormat = m_ui->m_imageFormatCombo->currentText();
-
+
SRenderItem renderItem = m_renderItems[m_renderContext.currentItemIndex];
if (m_bFFMPEGCommandAvailable && renderItem.bCreateVideo)
{
// Create a video using the ffmpeg plug-in from captured images.
m_renderContext.processingFFMPEG = true;
-
+
AZStd::string outputFolder = m_renderContext.captureOptions.folder;
auto future = QtConcurrent::run(
[renderItem, outputFolder, imageFormat]
@@ -1238,7 +1238,7 @@ void CSequenceBatchRenderDialog::OnKickIdleTimout()
}
void CSequenceBatchRenderDialog::OnKickIdle()
-{
+{
if (m_renderContext.captureState == CaptureState::WarmingUpAfterResChange)
{
OnUpdateWarmingUpAfterResChange();
@@ -1254,7 +1254,7 @@ void CSequenceBatchRenderDialog::OnKickIdle()
else if (m_renderContext.captureState == CaptureState::Capturing)
{
OnUpdateCapturing();
- }
+ }
else if (m_renderContext.captureState == CaptureState::End)
{
OnUpdateEnd(m_renderContext.endingSequence);
diff --git a/Code/Editor/UndoDropDown.cpp b/Code/Editor/UndoDropDown.cpp
index 6bf807ebf4..4f346b57dd 100644
--- a/Code/Editor/UndoDropDown.cpp
+++ b/Code/Editor/UndoDropDown.cpp
@@ -101,13 +101,13 @@ public:
if (fresh.size() < m_stackNames.size())
{
- beginRemoveRows(createIndex(-1, -1), static_cast(fresh.size()), static_cast(m_stackNames.size() - 1));
+ beginRemoveRows(QModelIndex(), static_cast(fresh.size()), static_cast(m_stackNames.size() - 1));
m_stackNames = fresh;
endRemoveRows();
}
else
{
- beginInsertRows(createIndex(-1, -1), static_cast(m_stackNames.size()), static_cast(fresh.size() - 1));
+ beginInsertRows(QModelIndex(), static_cast(m_stackNames.size()), static_cast(fresh.size() - 1));
m_stackNames = fresh;
endInsertRows();
}
diff --git a/Code/Editor/Util/PathUtil.cpp b/Code/Editor/Util/PathUtil.cpp
index c9e6823824..ca3481ddae 100644
--- a/Code/Editor/Util/PathUtil.cpp
+++ b/Code/Editor/Util/PathUtil.cpp
@@ -11,9 +11,9 @@
#include "PathUtil.h"
-#include // for AZ_MAX_PATH_LEN
+#include
+#include
#include // for ebus events
-#include
#include
#include
#include
@@ -179,7 +179,7 @@ namespace Path
EBUS_EVENT_RESULT(engineRoot, AzFramework::ApplicationRequests::Bus, GetEngineRoot);
return QString(engineRoot);
}
-
+
//////////////////////////////////////////////////////////////////////////
QString& ReplaceFilename(const QString& strFilepath, const QString& strFilename, QString& strOutputFilename, bool bCallCaselessPath)
{
@@ -216,30 +216,21 @@ namespace Path
//////////////////////////////////////////////////////////////////////////
QString GetResolvedUserSandboxFolder()
{
- char resolvedPath[AZ_MAX_PATH_LEN] = { 0 };
- gEnv->pFileIO->ResolvePath(GetUserSandboxFolder().toUtf8().data(), resolvedPath, AZ_MAX_PATH_LEN);
- return QString::fromLatin1(resolvedPath);
+ AZ::IO::FixedMaxPath userSandboxFolderPath;
+ gEnv->pFileIO->ResolvePath(userSandboxFolderPath, GetUserSandboxFolder().toUtf8().constData());
+ return QString::fromUtf8(userSandboxFolderPath.c_str(), static_cast(userSandboxFolderPath.Native().size()));
}
// internal function, you should use GetEditingGameDataFolder instead.
AZStd::string GetGameAssetsFolder()
{
- const char* resultValue = nullptr;
- EBUS_EVENT_RESULT(resultValue, AzToolsFramework::AssetSystemRequestBus, GetAbsoluteDevGameFolderPath);
- if (!resultValue)
- {
- if ((gEnv) && (gEnv->pFileIO))
- {
- resultValue = gEnv->pFileIO->GetAlias("@devassets@");
- }
- }
-
- if (!resultValue)
+ AZ::IO::Path projectPath;
+ if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
- resultValue = ".";
+ settingsRegistry->Get(projectPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath);
}
- return resultValue;
+ return projectPath.Native();
}
/// Get the data folder
@@ -258,26 +249,6 @@ namespace Path
return str;
}
- //! Get the root folder (in source control or other writable assets) where you should save root data.
- AZStd::string GetEditingRootFolder()
- {
- const char* resultValue = nullptr;
- EBUS_EVENT_RESULT(resultValue, AzToolsFramework::AssetSystemRequestBus, GetAbsoluteDevRootFolderPath);
-
- if (!resultValue)
- {
- if ((gEnv) && (gEnv->pFileIO))
- {
- resultValue = gEnv->pFileIO->GetAlias("@devassets@");
- }
- }
- if (!resultValue)
- {
- resultValue = ".";
- }
- return resultValue;
- }
-
AZStd::string MakeModPathFromGamePath(const char* relGamePath)
{
@@ -335,165 +306,60 @@ namespace Path
return "";
}
- bool relPathfound = false;
+ bool relPathFound = false;
AZStd::string relativePath;
AZStd::string fullAssetPath(fullPath.toUtf8().data());
- EBUS_EVENT_RESULT(relPathfound, AzToolsFramework::AssetSystemRequestBus, GetRelativeProductPathFromFullSourceOrProductPath, fullAssetPath, relativePath);
+ EBUS_EVENT_RESULT(relPathFound, AzToolsFramework::AssetSystemRequestBus, GetRelativeProductPathFromFullSourceOrProductPath, fullAssetPath, relativePath);
- if (relPathfound)
+ if (relPathFound)
{
// do not normalize this path, it will already be an appropriate asset ID.
return CaselessPaths(relativePath.c_str());
}
- char rootpath[_MAX_PATH] = { 0 };
- azstrcpy(rootpath, _MAX_PATH, Path::GetEditingRootFolder().c_str());
-
- if (bRelativeToGameFolder)
- {
- azstrcpy(rootpath, _MAX_PATH, Path::GetEditingGameDataFolder().c_str());
- }
-
- QString rootPathNormalized(rootpath);
- QString srcPathNormalized(fullPath);
-
-#if defined(AZ_PLATFORM_WINDOWS)
- // avoid confusing PathRelativePathTo
- rootPathNormalized.replace('/', '\\');
- srcPathNormalized.replace('/', '\\');
-#endif
+ AZ::IO::FixedMaxPath rootPath = bRelativeToGameFolder ? AZ::Utils::GetProjectPath() : AZ::Utils::GetEnginePath();
+ AZ::IO::FixedMaxPath resolvedFullPath;
+ AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(resolvedFullPath, fullPath.toUtf8().constData());
// Create relative path
- char resolvedSrcPath[AZ_MAX_PATH_LEN] = { 0 };
- AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(srcPathNormalized.toUtf8().data(), resolvedSrcPath, AZ_MAX_PATH_LEN);
- QByteArray path = QDir(rootPathNormalized).relativeFilePath(resolvedSrcPath).toUtf8();
- if (path.isEmpty())
- {
- return fullPath;
- }
- // The following code is required because the windows PathRelativePathTo function will always return "./SomePath" instead of just "SomePath"
- // Only remove single dot (.) and slash parts of a path, never the double dot (..)
- const char* pBuffer = path.data();
- bool bHasDot = false;
- while (*pBuffer && pBuffer != path.end())
- {
- switch (*pBuffer)
- {
- case '.':
- if (bHasDot)
- {
- // Found a double dot, rewind and stop removing
- pBuffer--;
- break;
- }
- // Fall through intended
- case '/':
- case '\\':
- bHasDot = (*pBuffer == '.');
- pBuffer++;
- continue;
- }
- break;
- }
-
- QString relPath = pBuffer;
- return CaselessPaths(relPath);
+ return CaselessPaths(resolvedFullPath.LexicallyProximate(rootPath).MakePreferred().c_str());
}
QString GamePathToFullPath(const QString& path)
{
using namespace AzToolsFramework;
- AZ_Warning("GamePathToFullPath", path.size() <= AZ_MAX_PATH_LEN, "Path exceeds maximum path length of %d", AZ_MAX_PATH_LEN);
- if ((gEnv) && (gEnv->pFileIO) && gEnv->pCryPak && path.size() <= AZ_MAX_PATH_LEN)
+ AZ_Warning("GamePathToFullPath", path.size() <= AZ::IO::MaxPathLength, "Path exceeds maximum path length of %zu", AZ::IO::MaxPathLength);
+ if (path.size() <= AZ::IO::MaxPathLength)
{
// first, adjust the file name for mods:
- bool fullPathfound = false;
- AZStd::string assetFullPath;
- AZStd::string adjustedFilePath = path.toUtf8().data();
- AssetSystemRequestBus::BroadcastResult(fullPathfound, &AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, adjustedFilePath, assetFullPath);
- if (fullPathfound)
+ bool fullPathFound = false;
+ AZ::IO::Path assetFullPath;
+ AZ::IO::Path adjustedFilePath = path.toUtf8().constData();
+ AssetSystemRequestBus::BroadcastResult(fullPathFound, &AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath,
+ adjustedFilePath.Native(), assetFullPath.Native());
+ if (fullPathFound)
{
- //if the bus message succeeds than normalize and lowercase the path
- AzFramework::StringFunc::Path::Normalize(assetFullPath);
- return assetFullPath.c_str();
+ //if the bus message succeeds than normalize
+ return assetFullPath.LexicallyNormal().c_str();
}
- // if the bus message didn't succeed, 'guess' the source assets:
+ // if the bus message didn't succeed, check if he path exist as a resolved path
else
{
// Not all systems have been converted to use local paths. Some editor files save XML files directly, and a full or correctly aliased path is already passed in.
// If the path passed in exists already, then return the resolved filepath
if (AZ::IO::FileIOBase::GetDirectInstance()->Exists(adjustedFilePath.c_str()))
{
- char resolvedPath[AZ_MAX_PATH_LEN + PathUtil::maxAliasLength] = { 0 };
- AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(adjustedFilePath.c_str(), resolvedPath, AZ_MAX_PATH_LEN + PathUtil::maxAliasLength);
- return QString::fromUtf8(resolvedPath);
+ AZ::IO::FixedMaxPath resolvedPath;
+ AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(resolvedPath, adjustedFilePath);
+ return QString::fromUtf8(resolvedPath.c_str(), static_cast(resolvedPath.Native().size()));
}
- // if we get here it means that the Asset Processor does not know about this file. most of the time we should never get here
- // the rest of this code just does a bunch of heuristic guesses in case of missing files or if the user has hand-edited
- // the asset cache by moving files in via some other means or external process.
- if (adjustedFilePath[0] != '@')
- {
- const char* prefix = (adjustedFilePath[0] == '/' || adjustedFilePath[0] == '\\') ? "@devassets@" : "@devassets@/";
- adjustedFilePath = prefix + adjustedFilePath;
- }
-
- char szAdjustedFile[AZ_MAX_PATH_LEN + PathUtil::maxAliasLength] = { 0 };
- gEnv->pFileIO->ResolvePath(adjustedFilePath.c_str(), szAdjustedFile, AZ_ARRAY_SIZE(szAdjustedFile));
-
- if ((azstrnicmp(szAdjustedFile, "@devassets@", 11) == 0) && ((szAdjustedFile[11] == '/') || (szAdjustedFile[11] == '\\')))
- {
- if (!gEnv->pCryPak->IsFileExist(szAdjustedFile))
- {
- AZStd::string newName(szAdjustedFile);
- AzFramework::StringFunc::Replace(newName, "@devassets@", "@devroot@/engine", false);
-
- if (gEnv->pCryPak->IsFileExist(newName.c_str()))
- {
- azstrcpy(szAdjustedFile, AZ_ARRAY_SIZE(szAdjustedFile), newName.c_str());
- }
- else
- {
- // getting tricky here, try @devroot@ alone, in case its 'editor'
- AzFramework::StringFunc::Replace(newName, "@devassets@", "@devroot@", false);
- if (gEnv->pCryPak->IsFileExist(szAdjustedFile))
- {
- azstrcpy(szAdjustedFile, AZ_ARRAY_SIZE(szAdjustedFile), newName.c_str());
- }
- // give up, best guess is just @devassets@
- }
- }
- }
-
- // we should very rarely actually get to this point in the code.
-
- // szAdjustedFile may contain an alias at this point. (@assets@/blah.whatever)
- // there is a case in which the loose asset exists only within a pak file for some reason
- // this is not recommended but it is possible.in that case, we want to return the original szAdjustedFile
- // without touching it or resolving it so that crypak can open it successfully.
- char adjustedPath[AZ_MAX_PATH_LEN + PathUtil::maxAliasLength] = { 0 };
- if (gEnv->pFileIO->ResolvePath(szAdjustedFile, adjustedPath, AZ_MAX_PATH_LEN + PathUtil::maxAliasLength)) // resolve to full path
- {
- if ((gEnv->pCryPak->IsFileExist(adjustedPath)) || (!gEnv->pCryPak->IsFileExist(szAdjustedFile)))
- {
- // note that if we get here, then EITHER
- // the file exists as a loose asset in the actual adjusted path
- // OR the file does not exist in the original passed-in aliased name (like '@assets@/whatever')
- // in which case we may as well just resolve the path to a full path and return it.
- assetFullPath = adjustedPath;
- AzFramework::StringFunc::Path::Normalize(assetFullPath);
- azstrcpy(szAdjustedFile, AZ_MAX_PATH_LEN + PathUtil::maxAliasLength, assetFullPath.c_str());
- }
- // if the above case succeeded then it means that the file does NOT exist loose
- // but DOES exist in a pak, in which case we leave szAdjustedFile with the alias on the front of it, meaning
- // fopens via crypak will actually succeed.
- }
- return szAdjustedFile;
+ return path;
}
}
else
{
- return "";
+ return QString{};
}
}
diff --git a/Code/Editor/Util/PathUtil.h b/Code/Editor/Util/PathUtil.h
index 2c49031155..163d74e358 100644
--- a/Code/Editor/Util/PathUtil.h
+++ b/Code/Editor/Util/PathUtil.h
@@ -44,9 +44,6 @@ namespace Path
//! always returns a full path
EDITOR_CORE_API AZStd::string GetEditingGameDataFolder();
- //! Get the root folder (in source control or other writable assets) where you should save root data.
- EDITOR_CORE_API AZStd::string GetEditingRootFolder();
-
//! Set the current mod NAME for editing purposes. After doing this the above functions will take this into account
//! name only, please!
EDITOR_CORE_API void SetModName(const char* input);
@@ -69,93 +66,6 @@ namespace Path
return strPath;
}
- //! Split full file name to path and filename
- //! @param filepath [IN] Full file name inclusing path.
- //! @param path [OUT] Extracted file path.
- //! @param file [OUT] Extracted file (with extension).
- inline void Split(const QString& filepath, QString& path, QString& file)
- {
- char path_buffer[_MAX_PATH];
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
- char fname[_MAX_FNAME];
- char ext[_MAX_EXT];
-#ifdef AZ_COMPILER_MSVC
- _splitpath_s(filepath.toUtf8().data(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
- _makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
- path = path_buffer;
- _makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), 0, 0, fname, ext);
-#else
- _splitpath(filepath.toUtf8().data(), drive, dir, fname, ext);
- _makepath(path_buffer, drive, dir, 0, 0);
- path = path_buffer;
- _makepath(path_buffer, 0, 0, fname, ext);
-#endif
- file = path_buffer;
- }
- inline void Split(const AZStd::string& filepath, AZStd::string& path, AZStd::string& file)
- {
- char path_buffer[_MAX_PATH];
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
- char fname[_MAX_FNAME];
- char ext[_MAX_EXT];
-#ifdef AZ_COMPILER_MSVC
- _splitpath_s(filepath.c_str(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), 0, 0, 0, 0);
- _makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
- path = path_buffer;
- _makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), 0, 0, fname, ext);
-#else
- _splitpath(filepath.c_str(), drive, dir, fname, ext);
- _makepath(path_buffer, drive, dir, 0, 0);
- path = path_buffer;
- _makepath(path_buffer, 0, 0, fname, ext);
-#endif
- file = path_buffer;
- }
-
- //! Split full file name to path and filename
- //! @param filepath [IN] Full file name inclusing path.
- //! @param path [OUT] Extracted file path.
- //! @param filename [OUT] Extracted file (without extension).
- //! @param ext [OUT] Extracted files extension.
- inline void Split(const QString& filepath, QString& path, QString& filename, QString& fext)
- {
- char path_buffer[_MAX_PATH];
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
- char fname[_MAX_FNAME];
- char ext[_MAX_EXT];
-#ifdef AZ_COMPILER_MSVC
- _splitpath_s(filepath.toUtf8().data(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
- _makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
-#else
- _splitpath(filepath.toUtf8().data(), drive, dir, fname, ext);
- _makepath(path_buffer, drive, dir, 0, 0);
-#endif
- path = path_buffer;
- filename = fname;
- fext = ext;
- }
- inline void Split(const AZStd::string& filepath, AZStd::string& path, AZStd::string& filename, AZStd::string& fext)
- {
- char path_buffer[_MAX_PATH];
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
- char fname[_MAX_FNAME];
- char ext[_MAX_EXT];
-#ifdef AZ_COMPILER_MSVC
- _splitpath_s(filepath.c_str(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
- _makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
-#else
- _splitpath(filepath.c_str(), drive, dir, fname, ext);
- _makepath(path_buffer, drive, dir, 0, 0);
-#endif
- path = path_buffer;
- filename = fname;
- fext = ext;
- }
-
//! Split path into segments
//! @param filepath [IN] path
inline QStringList SplitIntoSegments(const QString& path)
diff --git a/Code/Editor/Viewport.cpp b/Code/Editor/Viewport.cpp
index 2d41538d92..c8f2e268d9 100644
--- a/Code/Editor/Viewport.cpp
+++ b/Code/Editor/Viewport.cpp
@@ -19,6 +19,7 @@
#include
#include
+#include
// Editor
#include "ViewManager.h"
@@ -173,8 +174,6 @@ QtViewport::QtViewport(QWidget* parent)
m_bAdvancedSelectMode = false;
- m_pVisibleObjectsCache = new CBaseObjectsCache;
-
m_constructionPlane.SetPlane(Vec3_OneZ, Vec3_Zero);
m_constructionPlaneAxisX = Vec3_Zero;
m_constructionPlaneAxisY = Vec3_Zero;
@@ -204,8 +203,6 @@ QtViewport::QtViewport(QWidget* parent)
//////////////////////////////////////////////////////////////////////////
QtViewport::~QtViewport()
{
- delete m_pVisibleObjectsCache;
-
GetIEditor()->GetViewManager()->UnregisterViewport(this);
}
@@ -376,11 +373,6 @@ void QtViewport::OnDeactivate()
void QtViewport::ResetContent()
{
m_pMouseOverObject = nullptr;
-
- // Need to clear visual object cache.
- // Right after loading new level, some code(e.g. OnMouseMove) access invalid
- // previous level object before cache updated.
- GetVisibleObjectsCache()->ClearObjects();
}
//////////////////////////////////////////////////////////////////////////
@@ -398,11 +390,8 @@ void QtViewport::Update()
m_viewportUi.Update();
m_bAdvancedSelectMode = false;
- bool bSpaceClick = false;
- {
- bSpaceClick = CheckVirtualKey(Qt::Key_Space) & !CheckVirtualKey(Qt::Key_Shift) /*& !CheckVirtualKey(Qt::Key_Control)*/;
- }
- if (bSpaceClick && hasFocus())
+
+ if (CheckVirtualKey(Qt::Key_Space) && !CheckVirtualKey(Qt::Key_Shift) && hasFocus())
{
m_bAdvancedSelectMode = true;
}
diff --git a/Code/Editor/Viewport.h b/Code/Editor/Viewport.h
index 60c1306420..7f8ccc4c4f 100644
--- a/Code/Editor/Viewport.h
+++ b/Code/Editor/Viewport.h
@@ -157,7 +157,7 @@ public:
virtual Vec3 SnapToGrid(const Vec3& vec) = 0;
- //! Get selection procision tolerance.
+ //! Get selection precision tolerance.
virtual float GetSelectionTolerance() const = 0;
//////////////////////////////////////////////////////////////////////////
@@ -491,10 +491,6 @@ public:
void ResetCursor() override;
void SetSupplementaryCursorStr(const QString& str) override;
- //////////////////////////////////////////////////////////////////////////
- // Return visble objects cache.
- CBaseObjectsCache* GetVisibleObjectsCache() override { return m_pVisibleObjectsCache; };
-
void RegisterRenderListener(IRenderListener* piListener) override;
bool UnregisterRenderListener(IRenderListener* piListener) override;
bool IsRenderListenerRegistered(IRenderListener* piListener) override;
@@ -612,8 +608,6 @@ protected:
int m_nLastUpdateFrame;
int m_nLastMouseMoveFrame;
- CBaseObjectsCache* m_pVisibleObjectsCache;
-
QRect m_rcClient;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp
index 3a83aa5d1c..3fa3b39ca5 100644
--- a/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp
@@ -173,6 +173,7 @@ namespace AZ
if (assetTracker)
{
+ assetTracker->FixUpAsset(*instance);
assetTracker->AddAsset(*instance);
}
@@ -185,7 +186,20 @@ namespace AZ
return context.Report(result, message);
}
- void SerializedAssetTracker::AddAsset(Asset& asset)
+ void SerializedAssetTracker::SetAssetFixUp(AssetFixUp assetFixUpCallback)
+ {
+ m_assetFixUpCallback = AZStd::move(assetFixUpCallback);
+ }
+
+ void SerializedAssetTracker::FixUpAsset(Asset& asset)
+ {
+ if (m_assetFixUpCallback)
+ {
+ m_assetFixUpCallback(asset);
+ }
+ }
+
+ void SerializedAssetTracker::AddAsset(Asset asset)
{
m_serializedAssets.emplace_back(asset);
}
@@ -199,5 +213,6 @@ namespace AZ
{
return m_serializedAssets;
}
+
} // namespace Data
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.h b/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.h
index 879952c82d..e1b8cda00d 100644
--- a/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.h
@@ -39,13 +39,18 @@ namespace AZ
{
public:
AZ_RTTI(SerializedAssetTracker, "{1E067091-8C0A-44B1-A455-6E97663F6963}");
+ using AssetFixUp = AZStd::function& asset)>;
- void AddAsset(Asset& asset);
+ void SetAssetFixUp(AssetFixUp assetFixUpCallback);
+ void FixUpAsset(Asset& asset);
+
+ void AddAsset(Asset asset);
AZStd::vector>& GetTrackedAssets();
const AZStd::vector>& GetTrackedAssets() const;
private:
AZStd::vector> m_serializedAssets;
+ AssetFixUp m_assetFixUpCallback;
};
} // namespace Data
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/AzCoreModule.cpp b/Code/Framework/AzCore/AzCore/AzCoreModule.cpp
index ec45335f95..67123ed826 100644
--- a/Code/Framework/AzCore/AzCore/AzCoreModule.cpp
+++ b/Code/Framework/AzCore/AzCore/AzCoreModule.cpp
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
namespace AZ
{
@@ -44,6 +45,10 @@ namespace AZ
EventSchedulerSystemComponent::CreateDescriptor(),
TaskGraphSystemComponent::CreateDescriptor(),
+#if !defined(_RELEASE)
+ Statistics::StatisticalProfilerProxySystemComponent::CreateDescriptor(),
+#endif
+
#if !defined(AZCORE_EXCLUDE_LUA)
ScriptSystemComponent::CreateDescriptor(),
#endif // #if !defined(AZCORE_EXCLUDE_LUA)
@@ -58,6 +63,10 @@ namespace AZ
azrtti_typeid(),
azrtti_typeid(),
azrtti_typeid(),
+
+#if !defined(_RELEASE)
+ azrtti_typeid(),
+#endif
};
}
}
diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
index 168807cd97..7e9accffd7 100644
--- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
+++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
@@ -1367,9 +1367,6 @@ namespace AZ
#endif
}
- //=========================================================================
- // Tick
- //=========================================================================
void ComponentApplication::Tick(float deltaOverride /*= -1.f*/)
{
{
@@ -1397,9 +1394,6 @@ namespace AZ
}
}
- //=========================================================================
- // Tick
- //=========================================================================
void ComponentApplication::TickSystem()
{
AZ_PROFILE_SCOPE(System, "Component application tick");
@@ -1547,5 +1541,4 @@ namespace AZ
AZ::SettingsRegistryScriptUtils::ReflectSettingsRegistryToBehaviorContext(*behaviorContext);
}
}
-
} // namespace AZ
diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h
index bfc541ca09..8e95ff5fa3 100644
--- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h
+++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h
@@ -5,6 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
+
#pragma once
#include
diff --git a/Code/Framework/AzCore/AzCore/Console/Console.cpp b/Code/Framework/AzCore/AzCore/Console/Console.cpp
index a1b8a1759d..9f207d9afd 100644
--- a/Code/Framework/AzCore/AzCore/Console/Console.cpp
+++ b/Code/Framework/AzCore/AzCore/Console/Console.cpp
@@ -476,15 +476,16 @@ namespace AZ
// Responsible for using the Json Serialization Issue Callback system
// to determine when a JSON Patch or JSON Merge Patch modifies a value
- // at a path underneath the IConsole::ConsoleRootCommandKey JSON pointer
+ // at a path underneath the IConsole::ConsoleRuntimeCommandKey JSON pointer
JsonSerializationResult::ResultCode operator()(AZStd::string_view message,
JsonSerializationResult::ResultCode result, AZStd::string_view path)
{
- AZ::IO::PathView consoleRootCommandKey{ IConsole::ConsoleRootCommandKey, AZ::IO::PosixPathSeparator };
+ constexpr AZ::IO::PathView consoleRootCommandKey{ IConsole::ConsoleRuntimeCommandKey, AZ::IO::PosixPathSeparator };
+ constexpr AZ::IO::PathView consoleAutoexecCommandKey{ IConsole::ConsoleAutoexecCommandKey, AZ::IO::PosixPathSeparator };
AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator };
if (result.GetTask() == JsonSerializationResult::Tasks::Merge
&& result.GetProcessing() == JsonSerializationResult::Processing::Completed
- && inputKey.IsRelativeTo(consoleRootCommandKey))
+ && (inputKey.IsRelativeTo(consoleRootCommandKey) || inputKey.IsRelativeTo(consoleAutoexecCommandKey)))
{
if (auto type = m_settingsRegistry.GetType(path); type != SettingsRegistryInterface::Type::NoType)
{
@@ -510,12 +511,24 @@ namespace AZ
{
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
- AZ::IO::PathView consoleRootCommandKey{ IConsole::ConsoleRootCommandKey, AZ::IO::PosixPathSeparator };
+ constexpr AZ::IO::PathView consoleRuntimeCommandKey{ IConsole::ConsoleRuntimeCommandKey, AZ::IO::PosixPathSeparator };
+ constexpr AZ::IO::PathView consoleAutoexecCommandKey{ IConsole::ConsoleAutoexecCommandKey, AZ::IO::PosixPathSeparator };
AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator };
- // The ConsoleRootComamndKey is not a command itself so strictly children keys are being examined
- if (inputKey.IsRelativeTo(consoleRootCommandKey) && inputKey != consoleRootCommandKey)
+
+ // Abuses the IsRelativeToFuncton function of the path class to extract the console
+ // command from the settings registry objects
+ FixedValueString command;
+ if (inputKey != consoleRuntimeCommandKey && inputKey.IsRelativeTo(consoleRuntimeCommandKey))
+ {
+ command = inputKey.LexicallyRelative(consoleRuntimeCommandKey).Native();
+ }
+ else if (inputKey != consoleAutoexecCommandKey && inputKey.IsRelativeTo(consoleAutoexecCommandKey))
+ {
+ command = inputKey.LexicallyRelative(consoleAutoexecCommandKey).Native();
+ }
+
+ if (!command.empty())
{
- FixedValueString command = inputKey.LexicallyRelative(consoleRootCommandKey).Native();
ConsoleCommandContainer commandArgs;
// Argument string which stores the value from the Settings Registry long enough
// to pass into the PerformCommand. The ConsoleCommandContainer stores string_views
@@ -603,9 +616,10 @@ namespace AZ
void Console::RegisterCommandInvokerWithSettingsRegistry(AZ::SettingsRegistryInterface& settingsRegistry)
{
- // Make sure the there is a JSON object at the path of AZ::IConsole::ConsoleRootCommandKey
+ // Make sure the there is a JSON object at the ConsoleRuntimeCommandKey or ConsoleAutoexecKey
// So that JSON Patch is able to add values underneath that object (JSON Patch doesn't create intermediate objects)
- settingsRegistry.MergeSettings(R"({ "Amazon": { "AzCore": { "Runtime": { "ConsoleCommands": {} } }}})",
+ settingsRegistry.MergeSettings(R"({ "Amazon": { "AzCore": { "Runtime": { "ConsoleCommands": {} } } })"
+ R"(,"O3DE": { "Autoexec": { "ConsoleCommands": {} } } })",
SettingsRegistryInterface::Format::JsonMergePatch);
m_consoleCommandKeyHandler = settingsRegistry.RegisterNotifier(ConsoleCommandKeyNotificationHandler{ settingsRegistry, *this });
diff --git a/Code/Framework/AzCore/AzCore/Console/IConsole.h b/Code/Framework/AzCore/AzCore/Console/IConsole.h
index dafc284ce3..73d17ac65a 100644
--- a/Code/Framework/AzCore/AzCore/Console/IConsole.h
+++ b/Code/Framework/AzCore/AzCore/Console/IConsole.h
@@ -31,7 +31,8 @@ namespace AZ
using FunctorVisitor = AZStd::function;
- inline static constexpr AZStd::string_view ConsoleRootCommandKey = "/Amazon/AzCore/Runtime/ConsoleCommands";
+ inline static constexpr AZStd::string_view ConsoleRuntimeCommandKey = "/Amazon/AzCore/Runtime/ConsoleCommands";
+ inline static constexpr AZStd::string_view ConsoleAutoexecCommandKey = "/O3DE/Autoexec/ConsoleCommands";
IConsole() = default;
virtual ~IConsole() = default;
diff --git a/Code/Framework/AzCore/AzCore/Debug/Budget.cpp b/Code/Framework/AzCore/AzCore/Debug/Budget.cpp
index f9fe7e462a..4a6f3ed114 100644
--- a/Code/Framework/AzCore/AzCore/Debug/Budget.cpp
+++ b/Code/Framework/AzCore/AzCore/Debug/Budget.cpp
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
AZ_DEFINE_BUDGET(Animation);
AZ_DEFINE_BUDGET(Audio);
@@ -30,8 +31,7 @@ namespace AZ::Debug
};
Budget::Budget(const char* name)
- : m_name{ name }
- , m_crc{ Crc32(name) }
+ : Budget( name, Crc32(name) )
{
}
@@ -40,6 +40,10 @@ namespace AZ::Debug
, m_crc{ crc }
{
m_impl = aznew BudgetImpl;
+ if (auto statsProfiler = Interface::Get(); statsProfiler)
+ {
+ statsProfiler->RegisterProfilerId(m_crc);
+ }
}
Budget::~Budget()
diff --git a/Code/Framework/AzCore/AzCore/Debug/Profiler.h b/Code/Framework/AzCore/AzCore/Debug/Profiler.h
index 56103e8314..6e86de2e93 100644
--- a/Code/Framework/AzCore/AzCore/Debug/Profiler.h
+++ b/Code/Framework/AzCore/AzCore/Debug/Profiler.h
@@ -8,6 +8,7 @@
#pragma once
#include
+#include
#ifdef USE_PIX
#include
@@ -44,7 +45,10 @@
#define AZ_PROFILE_INTERVAL_START(...)
#define AZ_PROFILE_INTERVAL_START_COLORED(...)
#define AZ_PROFILE_INTERVAL_END(...)
-#define AZ_PROFILE_INTERVAL_SCOPED(...)
+#define AZ_PROFILE_INTERVAL_SCOPED(budget, scopeNameId, ...) \
+ static constexpr AZ::Crc32 AZ_JOIN(blockId, __LINE__)(scopeNameId); \
+ AZ::Statistics::StatisticalProfilerProxy::TimedScope AZ_JOIN(scope, __LINE__)(AZ_CRC_CE(#budget), AZ_JOIN(blockId, __LINE__));
+
#endif
#ifndef AZ_PROFILE_DATAPOINT
diff --git a/Code/Framework/AzCore/AzCore/Debug/Timer.h b/Code/Framework/AzCore/AzCore/Debug/Timer.h
index 47bd3e1b95..6585fe7468 100644
--- a/Code/Framework/AzCore/AzCore/Debug/Timer.h
+++ b/Code/Framework/AzCore/AzCore/Debug/Timer.h
@@ -46,5 +46,23 @@ namespace AZ
private:
AZStd::sys_time_t m_timeStamp;
};
+
+ //! Utility type that updates the given variable with the lifetime of the object in cycles.
+ //! Useful for quick scope based timing.
+ struct ScopedTimer
+ {
+ explicit ScopedTimer(AZStd::sys_time_t& variable)
+ : m_variable(variable)
+ {
+ m_timer.Stamp();
+ }
+ ~ScopedTimer()
+ {
+ m_variable = m_timer.GetDeltaTimeInTicks();
+ }
+
+ AZStd::sys_time_t& m_variable;
+ Timer m_timer;
+ };
}
}
diff --git a/Code/Framework/AzCore/AzCore/Debug/Trace.cpp b/Code/Framework/AzCore/AzCore/Debug/Trace.cpp
index 14504cc282..3edcbaa273 100644
--- a/Code/Framework/AzCore/AzCore/Debug/Trace.cpp
+++ b/Code/Framework/AzCore/AzCore/Debug/Trace.cpp
@@ -224,6 +224,8 @@ namespace AZ
void Debug::Trace::Terminate(int exitCode)
{
+ AZ_TracePrintf("Exit", "Called Terminate() with exit code: 0x%x", exitCode);
+ AZ::Debug::Trace::PrintCallstack("Exit");
Platform::Terminate(exitCode);
}
diff --git a/Code/Framework/AzCore/AzCore/Debug/Trace.h b/Code/Framework/AzCore/AzCore/Debug/Trace.h
index a1334d334e..507ba48e53 100644
--- a/Code/Framework/AzCore/AzCore/Debug/Trace.h
+++ b/Code/Framework/AzCore/AzCore/Debug/Trace.h
@@ -262,17 +262,17 @@ namespace AZ
#else // !AZ_ENABLE_TRACING
- #define AZ_Assert(...) AZ_UNUSED(__VA_ARGS__);
- #define AZ_Error(...) AZ_UNUSED(__VA_ARGS__);
- #define AZ_ErrorOnce(...) AZ_UNUSED(__VA_ARGS__);
- #define AZ_Warning(...) AZ_UNUSED(__VA_ARGS__);
- #define AZ_WarningOnce(...) AZ_UNUSED(__VA_ARGS__);
- #define AZ_TracePrintf(...) AZ_UNUSED(__VA_ARGS__);
- #define AZ_TracePrintfOnce(...) AZ_UNUSED(__VA_ARGS__);
-
- #define AZ_Verify(...) AZ_UNUSED(__VA_ARGS__);
- #define AZ_VerifyError(...) AZ_UNUSED(__VA_ARGS__);
- #define AZ_VerifyWarning(...) AZ_UNUSED(__VA_ARGS__);
+ #define AZ_Assert(...)
+ #define AZ_Error(...)
+ #define AZ_ErrorOnce(...)
+ #define AZ_Warning(...)
+ #define AZ_WarningOnce(...)
+ #define AZ_TracePrintf(...)
+ #define AZ_TracePrintfOnce(...)
+
+ #define AZ_Verify(expression, ...) AZ_UNUSED(expression)
+ #define AZ_VerifyError(window, expression, ...) AZ_UNUSED(expression)
+ #define AZ_VerifyWarning(window, expression, ...) AZ_UNUSED(expression)
#endif // AZ_ENABLE_TRACING
diff --git a/Code/Framework/AzCore/AzCore/EBus/BusImpl.h b/Code/Framework/AzCore/AzCore/EBus/BusImpl.h
index 8e655c0525..e2b1c2e92b 100644
--- a/Code/Framework/AzCore/AzCore/EBus/BusImpl.h
+++ b/Code/Framework/AzCore/AzCore/EBus/BusImpl.h
@@ -160,8 +160,8 @@ namespace AZ
/**
* Locking primitive that is used when executing events in the event queue.
*/
- using EventQueueMutexType = typename AZStd::Utils::if_c::value, // if EventQueueMutexType==NullMutex use MutexType otherwise EventQueueMutexType
- MutexType, typename Traits::EventQueueMutexType>::type;
+ using EventQueueMutexType = AZStd::conditional_t::value, // if EventQueueMutexType==NullMutex use MutexType otherwise EventQueueMutexType
+ MutexType, typename Traits::EventQueueMutexType>;
/**
* Pointer to an address on the bus.
@@ -180,14 +180,22 @@ namespace AZ
* `::ExecuteQueuedEvents()`.
* By default, the event queue is disabled.
*/
- static const bool EnableEventQueue = Traits::EnableEventQueue;
- static const bool EventQueueingActiveByDefault = Traits::EventQueueingActiveByDefault;
- static const bool EnableQueuedReferences = Traits::EnableQueuedReferences;
+ static constexpr bool EnableEventQueue = Traits::EnableEventQueue;
+ static constexpr bool EventQueueingActiveByDefault = Traits::EventQueueingActiveByDefault;
+ static constexpr bool EnableQueuedReferences = Traits::EnableQueuedReferences;
/**
* True if the EBus supports more than one address. Otherwise, false.
*/
- static const bool HasId = Traits::AddressPolicy != EBusAddressPolicy::Single;
+ static constexpr bool HasId = Traits::AddressPolicy != EBusAddressPolicy::Single;
+
+ /**
+ * Template Lock Guard class that wraps around the Mutex
+ * The EBus uses for Dispatching Events.
+ * This is not the EBus Context Mutex if LocklessDispatch is true
+ */
+ template
+ using DispatchLockGuard = typename Traits::template DispatchLockGuard;
};
/**
@@ -460,7 +468,7 @@ namespace AZ
using BusPtr = typename Traits::BusPtr;
/**
- * Helper to queue an event by BusIdType only when function queueing is enabled
+ * Helper to queue an event by BusIdType only when function queueing is enabled
* @param id Address ID. Handlers that are connected to this ID will receive the event.
* @param func Function pointer of the event to dispatch.
* @param args Function arguments that are passed to each handler.
@@ -581,7 +589,7 @@ namespace AZ
, public EBusBroadcaster
, public EBusEventer
, public EBusEventEnumerator
- , public AZStd::Utils::if_c, EBusNullQueue>::type
+ , public AZStd::conditional_t, EBusNullQueue>
{
};
@@ -599,7 +607,7 @@ namespace AZ
: public EventDispatcher
, public EBusBroadcaster
, public EBusBroadcastEnumerator
- , public AZStd::Utils::if_c, EBusNullQueue>::type
+ , public AZStd::conditional_t, EBusNullQueue>
{
};
diff --git a/Code/Framework/AzCore/AzCore/EBus/EBus.h b/Code/Framework/AzCore/AzCore/EBus/EBus.h
index ff8966e8e0..a3dc10b103 100644
--- a/Code/Framework/AzCore/AzCore/EBus/EBus.h
+++ b/Code/Framework/AzCore/AzCore/EBus/EBus.h
@@ -12,7 +12,7 @@
* that Open 3D Engine uses to dispatch notifications and receive requests.
* EBuses are configurable and support many different use cases.
* For more information about %EBuses, see AZ::EBus in this guide and
- * [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html)
+ * [Event Bus](https://o3de.org/docs/user-guide/engine/ebus/)
* in the *Open 3D Engine Developer Guide*.
*/
@@ -62,7 +62,7 @@ namespace AZ
* @endcode
*
* For more information about %EBuses, see EBus in this guide and
- * [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html)
+ * [Event Bus](https://o3de.org/docs/user-guide/engine/ebus/)
* in the *Open 3D Engine Developer Guide*.
*/
struct EBusTraits
@@ -236,6 +236,17 @@ namespace AZ
* code before or after an event.
*/
using EventProcessingPolicy = EBusEventProcessingPolicy;
+
+ /**
+ * Template Lock Guard class that wraps around the Mutex
+ * The EBus Context uses the LockGuard when dispatching
+ * (either AZStd::scoped_lock or NullLockGuard)
+ * The IsLocklessDispatch bool is there to defer evaluation of the LocklessDispatch constant
+ * Otherwise the value above in EBusTraits.h is always used and not the value
+ * that the derived trait class sets.
+ */
+ template
+ using DispatchLockGuard = AZStd::conditional_t