diff --git a/.clang-format b/.clang-format
index 565f28130e..04e0284f97 100644
--- a/.clang-format
+++ b/.clang-format
@@ -46,7 +46,7 @@ SortIncludes: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
-SpaceBeforeCpp11BracedList: true
+SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
diff --git a/.gitignore b/.gitignore
index c3af907e97..664680c5bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@ __pycache__
AssetProcessorTemp/**
[Bb]uild/**
[Cc]ache/
+/install/
Editor/EditorEventLog.xml
Editor/EditorLayout.xml
**/*egg-info/**
@@ -19,3 +20,4 @@ _savebackup/
TestResults/**
*.swatches
/imgui.ini
+/scripts/project_manager/logs/
diff --git a/Assets/Engine/SeedAssetList.seed b/Assets/Engine/SeedAssetList.seed
index 45a02f7682..77ec509721 100644
--- a/Assets/Engine/SeedAssetList.seed
+++ b/Assets/Engine/SeedAssetList.seed
@@ -67,106 +67,98 @@
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -264,109 +256,101 @@
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -387,498 +371,474 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -896,14 +856,6 @@
-
-
-
-
-
-
-
-
@@ -928,29 +880,13 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
@@ -1451,146 +1387,146 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -1699,42 +1635,42 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/AutomatedTesting/EngineFinder.cmake b/AutomatedTesting/EngineFinder.cmake
index 1fdcef2b56..fbbe3d8cfe 100644
--- a/AutomatedTesting/EngineFinder.cmake
+++ b/AutomatedTesting/EngineFinder.cmake
@@ -20,31 +20,49 @@ if(json_error)
message(FATAL_ERROR "Unable to read key 'engine' from 'project.json', error: ${json_error}")
endif()
-# Read the list of paths from ~.o3de/o3de_manifest.json
-file(TO_CMAKE_PATH "$ENV{USERPROFILE}" home_directory) # Windows
-if((NOT home_directory) OR (NOT EXISTS ${home_directory}))
- file(TO_CMAKE_PATH "$ENV{HOME}" home_directory)# Unix
+if(DEFINED ENV{USERPROFILE} AND EXISTS $ENV{USERPROFILE})
+ set(manifest_path $ENV{USERPROFILE}/.o3de/o3de_manifest.json) # Windows
+else()
+ set(manifest_path $ENV{HOME}/.o3de/o3de_manifest.json) # Unix
endif()
-if (NOT home_directory)
- message(FATAL_ERROR "Cannot find user home directory, the o3de manifest cannot be found")
-endif()
-# Set manifest path to path in the user home directory
-set(manifest_path ${home_directory}/.o3de/o3de_manifest.json)
-
+# Read the ~/.o3de/o3de_manifest.json file and look through the 'engines_path' object.
+# Find a key that matches LY_ENGINE_NAME_TO_USE and use that as the engine path.
if(EXISTS ${manifest_path})
file(READ ${manifest_path} manifest_json)
- string(JSON engines_count ERROR_VARIABLE json_error LENGTH ${manifest_json} engines)
+
+ string(JSON engines_path_count ERROR_VARIABLE json_error LENGTH ${manifest_json} engines_path)
if(json_error)
- message(FATAL_ERROR "Unable to read key 'engines' from '${manifest_path}', error: ${json_error}")
+ message(FATAL_ERROR "Unable to read key 'engines_path' from '${manifest_path}', error: ${json_error}")
endif()
- math(EXPR engines_count "${engines_count}-1")
- foreach(engine_path_index RANGE ${engines_count})
- string(JSON engine_path ERROR_VARIABLE json_error GET ${manifest_json} engines ${engine_path_index})
- if(${json_error})
- message(FATAL_ERROR "Unable to read engines[${engine_path_index}] '${manifest_path}', error: ${json_error}")
+ string(JSON engines_path_type ERROR_VARIABLE json_error TYPE ${manifest_json} engines_path)
+ if(json_error OR NOT ${engines_path_type} STREQUAL "OBJECT")
+ message(FATAL_ERROR "Type of 'engines_path' in '${manifest_path}' is not a JSON Object, error: ${json_error}")
+ endif()
+
+ math(EXPR engines_path_count "${engines_path_count}-1")
+ foreach(engine_path_index RANGE ${engines_path_count})
+ string(JSON engine_name ERROR_VARIABLE json_error MEMBER ${manifest_json} engines_path ${engine_path_index})
+ if(json_error)
+ message(FATAL_ERROR "Unable to read 'engines_path/${engine_path_index}' from '${manifest_path}', error: ${json_error}")
+ endif()
+
+ if(LY_ENGINE_NAME_TO_USE STREQUAL engine_name)
+ string(JSON engine_path ERROR_VARIABLE json_error GET ${manifest_json} engines_path ${engine_name})
+ if(json_error)
+ message(FATAL_ERROR "Unable to read value from 'engines_path/${engine_name}', error: ${json_error}")
+ endif()
+
+ if(engine_path)
+ list(APPEND CMAKE_MODULE_PATH "${engine_path}/cmake")
+ break()
+ endif()
endif()
- list(APPEND CMAKE_MODULE_PATH "${engine_path}/cmake")
endforeach()
+else()
+ # If the user is passing CMAKE_MODULE_PATH we assume thats where we will find the engine
+ if(NOT CMAKE_MODULE_PATH)
+ message(FATAL_ERROR "Engine registration is required before configuring a project. Please register an engine by running 'scripts/o3de register --this-engine'")
+ endif()
endif()
diff --git a/AutomatedTesting/Gem/Code/CMakeLists.txt b/AutomatedTesting/Gem/Code/CMakeLists.txt
index 2bcc304bde..548aa51ad1 100644
--- a/AutomatedTesting/Gem/Code/CMakeLists.txt
+++ b/AutomatedTesting/Gem/Code/CMakeLists.txt
@@ -28,30 +28,41 @@ ly_add_target(
Gem::Atom_AtomBridge.Static
)
+# if enabled, AutomatedTesting is used by all kinds of applications
+ly_create_alias(NAME AutomatedTesting.Builders NAMESPACE Gem TARGETS Gem::AutomatedTesting)
+ly_create_alias(NAME AutomatedTesting.Tools NAMESPACE Gem TARGETS Gem::AutomatedTesting)
+ly_create_alias(NAME AutomatedTesting.Clients NAMESPACE Gem TARGETS Gem::AutomatedTesting)
+ly_create_alias(NAME AutomatedTesting.Servers NAMESPACE Gem TARGETS Gem::AutomatedTesting)
+
################################################################################
# Gem dependencies
################################################################################
-ly_add_project_dependencies(
- PROJECT_NAME
- AutomatedTesting
- TARGETS
- AutomatedTesting.GameLauncher
- DEPENDENCIES_FILES
- runtime_dependencies.cmake
- ${pal_dir}/runtime_dependencies.cmake
-)
-if(PAL_TRAIT_BUILD_HOST_TOOLS)
- ly_add_project_dependencies(
- PROJECT_NAME
- AutomatedTesting
- TARGETS
- AssetBuilder
- AssetProcessor
- AssetProcessorBatch
- Editor
- DEPENDENCIES_FILES
- tool_dependencies.cmake
- ${pal_dir}/tool_dependencies.cmake
- )
+# The GameLauncher uses "Clients" gem variants:
+ly_enable_gems(PROJECT_NAME AutomatedTesting GEM_FILE enabled_gems.cmake
+ TARGETS AutomatedTesting.GameLauncher
+ VARIANTS Clients)
+
+# If we build a server, then apply the gems to the server
+if(PAL_TRAIT_BUILD_SERVER_SUPPORTED)
+ # if we're making a server, then add the "Server" gem variants to it:
+ ly_enable_gems(PROJECT_NAME AutomatedTesting GEM_FILE enabled_gems.cmake
+ TARGETS AutomatedTesting.ServerLauncher
+ VARIANTS Servers)
+
+ set_property(GLOBAL APPEND PROPERTY LY_LAUNCHER_SERVER_PROJECTS AutomatedTesting)
+endif()
+
+if (PAL_TRAIT_BUILD_HOST_TOOLS)
+ # The Editor uses "Tools" gem variants:
+ ly_enable_gems(
+ PROJECT_NAME AutomatedTesting GEM_FILE enabled_gems.cmake
+ TARGETS Editor
+ VARIANTS Tools)
+
+ # The pipeline tools use "Builders" gem variants:
+ ly_enable_gems(
+ PROJECT_NAME AutomatedTesting GEM_FILE enabled_gems.cmake
+ TARGETS AssetBuilder AssetProcessor AssetProcessorBatch
+ VARIANTS Builders)
endif()
diff --git a/AutomatedTesting/Gem/Code/enabled_gems.cmake b/AutomatedTesting/Gem/Code/enabled_gems.cmake
new file mode 100644
index 0000000000..d99d17b55e
--- /dev/null
+++ b/AutomatedTesting/Gem/Code/enabled_gems.cmake
@@ -0,0 +1,58 @@
+#
+# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+# its licensors.
+#
+# For complete copyright and license terms please see the LICENSE at the root of this
+# distribution (the "License"). All use of this software is governed by the License,
+# or, if provided, by the license below or the license accompanying this file. Do not
+# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#
+
+set(ENABLED_GEMS
+ ImGui
+ ScriptEvents
+ ExpressionEvaluation
+ Gestures
+ CertificateManager
+ DebugDraw
+ SceneProcessing
+ GraphCanvas
+ InAppPurchases
+ AutomatedTesting
+ EditorPythonBindings
+ QtForPython
+ PythonAssetBuilder
+ Metastream
+ AudioSystem
+ Camera
+ EMotionFX
+ PhysX
+ CameraFramework
+ StartingPointMovement
+ StartingPointCamera
+ ScriptCanvas
+ ScriptCanvasPhysics
+ ScriptCanvasTesting
+ LyShineExamples
+ StartingPointInput
+ PhysXDebug
+ WhiteBox
+ FastNoise
+ SurfaceData
+ GradientSignal
+ Vegetation
+ GraphModel
+ LandscapeCanvas
+ NvCloth
+ Blast
+ Maestro
+ TextureAtlas
+ LmbrCentral
+ LyShine
+ HttpRequestor
+ Atom_AtomBridge
+ AWSCore
+ AWSClientAuth
+ AWSMetrics
+)
diff --git a/AutomatedTesting/Gem/Code/runtime_dependencies.cmake b/AutomatedTesting/Gem/Code/runtime_dependencies.cmake
deleted file mode 100644
index 280c25bcf7..0000000000
--- a/AutomatedTesting/Gem/Code/runtime_dependencies.cmake
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-# its licensors.
-#
-# For complete copyright and license terms please see the LICENSE at the root of this
-# distribution (the License). All use of this software is governed by the License,
-# or, if provided, by the license below or the license accompanying this file. Do not
-# remove or modify any license notices. This file is distributed on an AS IS BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#
-
-# Extracted from Game
-set(GEM_DEPENDENCIES
- Gem::Maestro
- Gem::TextureAtlas
- Gem::LmbrCentral
- Gem::LyShine
- Gem::HttpRequestor
- Gem::ScriptEvents
- Gem::ExpressionEvaluation
- Gem::Gestures
- Gem::CertificateManager
- Gem::DebugDraw
- Gem::AudioSystem
- Gem::InAppPurchases
- Gem::AutomatedTesting
- Gem::Metastream
- Gem::Camera
- Gem::EMotionFX
- Gem::PhysX
- Gem::CameraFramework
- Gem::StartingPointMovement
- Gem::StartingPointCamera
- Gem::ScriptCanvas
- Gem::ImGui
- Gem::LyShineExamples
- Gem::StartingPointInput
- Gem::ScriptCanvasPhysics
- Gem::PhysXDebug
- Gem::WhiteBox
- Gem::FastNoise
- Gem::SurfaceData
- Gem::GradientSignal
- Gem::Vegetation
- Gem::Atom_AtomBridge
- Gem::NvCloth
- Gem::Blast
-)
diff --git a/AutomatedTesting/Gem/Code/tool_dependencies.cmake b/AutomatedTesting/Gem/Code/tool_dependencies.cmake
deleted file mode 100644
index 1d70c02b1c..0000000000
--- a/AutomatedTesting/Gem/Code/tool_dependencies.cmake
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-# its licensors.
-#
-# For complete copyright and license terms please see the LICENSE at the root of this
-# distribution (the License). All use of this software is governed by the License,
-# or, if provided, by the license below or the license accompanying this file. Do not
-# remove or modify any license notices. This file is distributed on an AS IS BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#
-
-# Extracted from Editor.xml
-set(GEM_DEPENDENCIES
- Gem::Maestro.Editor
- Gem::TextureAtlas.Editor
- Gem::LmbrCentral.Editor
- Gem::LyShine.Editor
- Gem::HttpRequestor
- Gem::ScriptEvents.Editor
- Gem::ExpressionEvaluation
- Gem::Gestures
- Gem::CertificateManager
- Gem::DebugDraw.Editor
- Gem::SceneProcessing.Editor
- Gem::GraphCanvas.Editor
- Gem::InAppPurchases
- Gem::AutomatedTesting
- Gem::EditorPythonBindings.Editor
- Gem::PythonAssetBuilder.Editor
- Gem::Metastream
- Gem::AudioSystem.Editor
- Gem::Camera.Editor
- Gem::EMotionFX.Editor
- Gem::PhysX.Editor
- Gem::CameraFramework
- Gem::StartingPointMovement
- Gem::StartingPointCamera
- Gem::ScriptCanvas.Editor
- Gem::ScriptEvents.Editor
- Gem::ImGui.Editor
- Gem::LyShineExamples
- Gem::StartingPointInput.Editor
- Gem::ScriptCanvasPhysics
- Gem::ScriptCanvasTesting.Editor
- Gem::PhysXDebug.Editor
- Gem::WhiteBox.Editor
- Gem::FastNoise.Editor
- Gem::SurfaceData.Editor
- Gem::GradientSignal.Editor
- Gem::Vegetation.Editor
- Gem::GraphModel.Editor
- Gem::LandscapeCanvas.Editor
- Gem::EMotionFX.Editor
- Gem::ImGui.Editor
- Gem::Atom_RHI.Private
- Gem::Atom_Feature_Common.Editor
- Gem::Atom_AtomBridge.Editor
- Gem::NvCloth.Editor
- Gem::Blast.Editor
-)
diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py
index 7a85cb1813..34af4d9115 100755
--- a/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py
+++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/ap_fixtures/bundler_batch_setup_fixture.py
@@ -162,7 +162,7 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
else:
cmd.append(f"--{key}")
if append_defaults:
- cmd.append(f"--project={workspace.project}")
+ cmd.append(f"--project-path={workspace.project}")
return cmd
# ******
@@ -300,9 +300,9 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
workspace.paths.engine_root(),
"Code",
"Framework",
- "AzFramework",
- "AzFramework",
- "Platform",
+ "AzCore",
+ "AzCore",
+ "PlatformId",
"PlatformDefaults.h",
)
@@ -318,7 +318,7 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
if start_gathering:
result = get_platform.match(line) # Try the regex
if result:
- platform_values[result.group(1).lower()] = counter
+ platform_values[result.group(1).replace("_ID", "").lower()] = counter
counter = counter << 1
elif "(Invalid, -1)" in line: # The line right before the first platform
start_gathering = True
diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py
index 8738e8acdf..1043bbaefa 100755
--- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py
+++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/asset_bundler_batch_tests.py
@@ -302,7 +302,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
that generating debug information does not affect asset list creation
"""
helper = bundler_batch_helper
- seed_list = os.path.join(workspace.paths.engine_root(), "Engine", "SeedAssetList.seed") # Engine seed list
+ seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed") # Engine seed list
asset = r"levels\testdependencieslevel\level.pak"
# Create Asset list
@@ -377,7 +377,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
subcommands.
"""
helper = bundler_batch_helper
- seed_list = os.path.join(workspace.paths.engine_root(), "Engine", "SeedAssetList.seed") # Engine seed list
+ seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed") # Engine seed list
asset = r"levels\testdependencieslevel\level.pak"
# Useful bundle locations / names (2 for comparing contents)
@@ -465,7 +465,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
"Please rerun with commandline option: '--bundle_platforms=pc,mac'"
# fmt:on
- seed_list = os.path.join(workspace.paths.engine_root(), "Engine", "SeedAssetList.seed") # Engine seed list
+ seed_list = os.path.join(workspace.paths.engine_root(), "Assets", "Engine", "SeedAssetList.seed") # Engine seed list
# Useful bundle / asset list locations
bundle_dir = os.path.dirname(helper["bundle_file"])
@@ -502,13 +502,13 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
for bundle_file in bundle_files.values():
assert os.path.isfile(bundle_file)
- # This asset is created on mac platform but not on windows
- file_to_check = b"engineassets/shading/defaultprobe_cm.dds.5" # [use byte str because file is in binary]
+ # This asset is created both on mac and windows platform
+ file_to_check = b"engineassets/shading/defaultprobe_cm_ibldiffuse.tif.streamingimage" # [use byte str because file is in binary]
# Extract the delta catalog file from pc archive. {file_to_check} SHOULD NOT be present for PC
file_contents = helper.extract_file_content(bundle_files["pc"], "DeltaCatalog.xml")
# fmt:off
- assert file_to_check not in file_contents, \
+ assert file_to_check in file_contents, \
f"{file_to_check} was found in DeltaCatalog.xml in pc bundle file {bundle_files['pc']}"
# fmt:on
@@ -619,7 +619,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
# Validate both mac and pc are activated for seed
# fmt:off
check_seed_platform(helper["seed_list_file"], test_asset,
- helper["platform_values"]["pc"] + helper["platform_values"]["osx"])
+ helper["platform_values"]["pc"] + helper["platform_values"]["mac"])
# fmt:on
# Remove MAC platform
@@ -651,7 +651,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
# Validate Mac platform was added back on. Save file contents
# fmt:off
all_lines = check_seed_platform(helper["seed_list_file"], test_asset,
- helper["platform_values"]["pc"] + helper["platform_values"]["osx"])
+ helper["platform_values"]["pc"] + helper["platform_values"]["mac"])
# fmt:on
# Try to remove platform without specifying a platform to remove (should fail)
@@ -1046,7 +1046,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
"--addDefaultSeedListFiles",
"--platform=pc",
"--print",
- f"--project={workspace.project}"
+ f"--project-path={workspace.project}"
],
universal_newlines=True,
)
@@ -1115,7 +1115,7 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
bundle_result_path = os.path.join(bundles_folder,
helper.platform_file_name("bundle.pak", workspace.asset_processor_platform))
- bundle_cache_path = os.path.join(workspace.paths.platform_cache(), workspace.project,
+ bundle_cache_path = os.path.join(workspace.paths.platform_cache(),
"Bundles",
helper.platform_file_name("bundle.pak", workspace.asset_processor_platform))
@@ -1156,13 +1156,15 @@ class TestsAssetBundlerBatch_WindowsAndMac(object):
# fmt:off
def test_WindowsAndMac_FilesMarkedSkip_FilesAreSkipped(self, workspace, bundler_batch_helper):
expected_assets = [
- "libs/particles/milestone2particles.xml",
- "textures/milestone2/particles/fx_sparkstreak_01.dds"
+ "ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas",
+ "ui/textures/prefab/button_normal.sprite"
]
bundler_batch_helper.call_assetLists(
assetListFile=bundler_batch_helper['asset_info_file_request'],
- addSeed="libs/particles/milestone2particles.xml",
- skip="textures/milestone2/particles/fx_launchermuzzlering_01.dds,textures/milestone2/particles/fx_launchermuzzlefront_01.dds"
+ addSeed="ui/canvases/lyshineexamples/animation/multiplesequences.uicanvas",
+ skip="ui/textures/prefab/button_disabled.sprite,ui/scripts/lyshineexamples/animation/multiplesequences.luac,"
+ "ui/textures/prefab/tooltip_sliced.sprite,ui/scripts/lyshineexamples/unloadthiscanvasbutton.luac,fonts/vera.fontfamily,fonts/vera-italic.font,"
+ "fonts/vera.font,fonts/vera-bold.font,fonts/vera-bold-italic.font,fonts/vera-italic.ttf,fonts/vera.ttf,fonts/vera-bold.ttf,fonts/vera-bold-italic.ttf"
)
assert os.path.isfile(bundler_batch_helper["asset_info_file_result"])
assets_in_list = []
diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py
index 8f1f2f7481..2cf55c7a58 100644
--- a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py
+++ b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py
@@ -42,6 +42,7 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
+ @fm.file_override('physxsystemconfiguration.setreg','C4044459_Material_DynamicFriction.setreg_override', 'AutomatedTesting/Registry')
def test_C4044459_Material_DynamicFriction(self, request, workspace, editor, launcher_platform):
from . import C4044459_Material_DynamicFriction as test_module
self._run_test(request, workspace, editor, test_module)
diff --git a/AutomatedTesting/Gem/PythonTests/scripting/ScriptEvents_AllParamDatatypes_CreationSuccess.py b/AutomatedTesting/Gem/PythonTests/scripting/ScriptEvents_AllParamDatatypes_CreationSuccess.py
new file mode 100644
index 0000000000..4beedec7cf
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/scripting/ScriptEvents_AllParamDatatypes_CreationSuccess.py
@@ -0,0 +1,210 @@
+"""
+All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+its licensors.
+
+For complete copyright and license terms please see the LICENSE at the root of this
+distribution (the "License"). All use of this software is governed by the License,
+or, if provided, by the license below or the license accompanying this file. Do not
+remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+"""
+
+
+# fmt: off
+class Tests():
+ new_event_created = ("New Script Event created", "New Script Event not created")
+ child_event_created = ("Child Event created", "Child Event not created")
+ params_added = ("New parameters added", "New parameters are not added")
+ file_saved = ("Script event file saved", "Script event file did not save")
+ node_found = ("Node found in Script Canvas", "Node not found in Script Canvas")
+# fmt: on
+
+
+def ScriptEvents_AllParamDatatypes_CreationSuccess():
+ """
+ Summary:
+ Parameters of all types can be created.
+
+ Expected Behavior:
+ The Method handles the large number of Parameters gracefully.
+ Parameters of all data types can be successfully created.
+ Updated ScriptEvent toast appears in Script Canvas.
+
+ Test Steps:
+ 1) Open Asset Editor
+ 2) Initially create new Script Event file with one method
+ 3) Add new method and set name to it
+ 4) Add new parameters of each type
+ 5) Verify if parameters are added
+ 6) Expand the parameter rows
+ 7) Set different names and datatypes for each parameter
+ 8) Save file and verify node in SC Node Palette
+ 9) Close Asset Editor
+
+ Note:
+ - This test file must be called from the Open 3D Engine Editor command terminal
+ - Any passed and failed tests are written to the Editor.log file.
+ Parsing the file or running a log_monitor are required to observe the test results.
+
+ :return: None
+ """
+ import os
+ from utils import TestHelper as helper
+ import pyside_utils
+
+ # Open 3D Engine imports
+ import azlmbr.legacy.general as general
+ import azlmbr.editor as editor
+ import azlmbr.bus as bus
+
+ # Pyside imports
+ from PySide2 import QtWidgets, QtTest, QtCore
+
+ GENERAL_WAIT = 1.0 # seconds
+
+ FILE_PATH = os.path.join("AutomatedTesting", "TestAssets", "test_file.scriptevents")
+ N_VAR_TYPES = 10 # Top 10 variable types
+ TEST_METHOD_NAME = "test_method_name"
+
+ editor_window = pyside_utils.get_editor_main_window()
+ asset_editor = asset_editor_widget = container = menu_bar = None
+ sc = node_palette = tree = search_frame = search_box = None
+
+ def initialize_asset_editor_qt_objects():
+ nonlocal asset_editor, asset_editor_widget, container, menu_bar
+ asset_editor = editor_window.findChild(QtWidgets.QDockWidget, "Asset Editor")
+ asset_editor_widget = asset_editor.findChild(QtWidgets.QWidget, "AssetEditorWindowClass")
+ container = asset_editor_widget.findChild(QtWidgets.QWidget, "ContainerForRows")
+ menu_bar = asset_editor_widget.findChild(QtWidgets.QMenuBar)
+
+ def initialize_sc_qt_objects():
+ nonlocal sc, node_palette, tree, search_frame, search_box
+ sc = editor_window.findChild(QtWidgets.QDockWidget, "Script Canvas")
+ if sc.findChild(QtWidgets.QDockWidget, "NodePalette") is None:
+ action = pyside_utils.find_child_by_pattern(sc, {"text": "Node Palette", "type": QtWidgets.QAction})
+ action.trigger()
+ node_palette = sc.findChild(QtWidgets.QDockWidget, "NodePalette")
+ tree = node_palette.findChild(QtWidgets.QTreeView, "treeView")
+ search_frame = node_palette.findChild(QtWidgets.QFrame, "searchFrame")
+ search_box = search_frame.findChild(QtWidgets.QLineEdit, "searchFilter")
+
+ def save_file():
+ editor.AssetEditorWidgetRequestsBus(bus.Broadcast, "SaveAssetAs", FILE_PATH)
+ action = pyside_utils.find_child_by_pattern(menu_bar, {"type": QtWidgets.QAction, "iconText": "Save"})
+ action.trigger()
+ # wait till file is saved, to validate that check the text of QLabel at the bottom of the AssetEditor,
+ # if there are no unsaved changes we will not have any * in the text
+ label = asset_editor.findChild(QtWidgets.QLabel, "textEdit")
+ return helper.wait_for_condition(lambda: "*" not in label.text(), 3.0)
+
+ def expand_container_rows(object_name):
+ children = container.findChildren(QtWidgets.QFrame, object_name)
+ for child in children:
+ check_box = child.findChild(QtWidgets.QCheckBox)
+ if check_box and not check_box.isChecked():
+ QtTest.QTest.mouseClick(check_box, QtCore.Qt.LeftButton, QtCore.Qt.NoModifier)
+
+ def node_palette_search(node_name):
+ search_box.setText(node_name)
+ helper.wait_for_condition(lambda: search_box.text() == node_name, 1.0)
+ # Try clicking ENTER in search box multiple times
+ for _ in range(20):
+ QtTest.QTest.keyClick(search_box, QtCore.Qt.Key_Enter, QtCore.Qt.NoModifier)
+ if pyside_utils.find_child_by_pattern(tree, {"text": node_name}) is not None:
+ break
+
+ def verify_added_params():
+ for index in range(N_VAR_TYPES):
+ if container.findChild(QtWidgets.QFrame, f"[{index}]") is None:
+ return False
+ return True
+
+ # 1) Open Asset Editor
+ general.idle_enable(True)
+ # Initially close the Asset Editor and then reopen to ensure we don't have any existing assets open
+ general.close_pane("Asset Editor")
+ general.open_pane("Asset Editor")
+ helper.wait_for_condition(lambda: general.is_pane_visible("Asset Editor"), 5.0)
+
+ # 2) Initially create new Script Event file with one method
+ initialize_asset_editor_qt_objects()
+ action = pyside_utils.find_child_by_pattern(menu_bar, {"type": QtWidgets.QAction, "text": "Script Events"})
+ action.trigger()
+ result = helper.wait_for_condition(
+ lambda: container.findChild(QtWidgets.QFrame, "Events") is not None
+ and container.findChild(QtWidgets.QFrame, "Events").findChild(QtWidgets.QToolButton, "") is not None,
+ 3 * GENERAL_WAIT,
+ )
+ Report.result(Tests.new_event_created, result)
+
+ # 3) Add new method and set name to it
+ add_event = container.findChild(QtWidgets.QFrame, "Events").findChild(QtWidgets.QToolButton, "")
+ add_event.click()
+ result = helper.wait_for_condition(
+ lambda: asset_editor_widget.findChild(QtWidgets.QFrame, "EventName") is not None, GENERAL_WAIT
+ )
+ Report.result(Tests.child_event_created, result)
+ expand_container_rows("EventName")
+ expand_container_rows("Name")
+ initialize_asset_editor_qt_objects()
+ children = container.findChildren(QtWidgets.QFrame, "Name")
+ for child in children:
+ line_edit = child.findChild(QtWidgets.QLineEdit)
+ if line_edit is not None and line_edit.text() == "MethodName":
+ line_edit.setText(TEST_METHOD_NAME)
+
+ # 4) Add new parameters of each type
+ helper.wait_for_condition(lambda: container.findChild(QtWidgets.QFrame, "Parameters") is not None, 2.0)
+ parameters = container.findChild(QtWidgets.QFrame, "Parameters")
+ add_param = parameters.findChild(QtWidgets.QToolButton, "")
+ for _ in range(N_VAR_TYPES):
+ add_param.click()
+
+ # 5) Verify if parameters are added
+ result = helper.wait_for_condition(verify_added_params, 3.0)
+ Report.result(Tests.params_added, result)
+
+ # 6) Expand the parameter rows (to render QFrame 'Type' for each param)
+ for index in range(N_VAR_TYPES):
+ expand_container_rows(f"[{index}]")
+
+ # 7) Set different names and datatypes for each parameter
+ expand_container_rows("Name")
+ children = container.findChildren(QtWidgets.QFrame, "Name")
+ index = 0
+ for child in children:
+ line_edit = child.findChild(QtWidgets.QLineEdit)
+ if line_edit is not None and line_edit.text() == "ParameterName":
+ line_edit.setText(f"param_{index}")
+ index += 1
+
+ children = container.findChildren(QtWidgets.QFrame, "Type")
+ index = 0
+ for child in children:
+ combo_box = child.findChild(QtWidgets.QComboBox)
+ if combo_box is not None and index < N_VAR_TYPES:
+ combo_box.setCurrentIndex(index)
+ index += 1
+
+ # 8) Save file and verify node in SC Node Palette
+ Report.result(Tests.file_saved, save_file())
+ general.open_pane("Script Canvas")
+ helper.wait_for_condition(lambda: general.is_pane_visible("Script Canvas"), 5.0)
+ initialize_sc_qt_objects()
+ node_palette_search(TEST_METHOD_NAME)
+ get_node_index = lambda: pyside_utils.find_child_by_pattern(tree, {"text": TEST_METHOD_NAME}) is not None
+ result = helper.wait_for_condition(get_node_index, 2.0)
+ Report.result(Tests.node_found, result)
+
+ # 9) Close Asset Editor
+ general.close_pane("Asset Editor")
+ general.close_pane("Script Canvas")
+
+
+if __name__ == "__main__":
+ import ImportPathHelper as imports
+
+ imports.init()
+ from utils import Report
+
+ Report.start_test(ScriptEvents_AllParamDatatypes_CreationSuccess)
diff --git a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py
index 85d0b4523f..91d6b3e53e 100755
--- a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py
+++ b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py
@@ -113,10 +113,6 @@ class TestAutomation(TestAutomationBase):
from . import Debugger_HappyPath_TargetMultipleGraphs as test_module
self._run_test(request, workspace, editor, test_module)
- def test_Debugging_TargetMultipleGraphs(self, request, workspace, editor, launcher_platform, project):
- from . import Debugging_TargetMultipleGraphs as test_module
- self._run_test(request, workspace, editor, test_module)
-
@pytest.mark.parametrize("level", ["tmp_level"])
def test_Debugger_HappyPath_TargetMultipleEntities(self, request, workspace, editor, launcher_platform, project, level):
def teardown():
@@ -317,4 +313,30 @@ class TestScriptCanvasTests(object):
auto_test_mode=False,
timeout=60,
)
+
+ def test_ScriptEvents_AllParamDatatypes_CreationSuccess(self, request, workspace, editor, launcher_platform):
+ def teardown():
+ file_system.delete(
+ [os.path.join(workspace.paths.project(), "TestAssets", "test_file.scriptevents")], True, True
+ )
+ request.addfinalizer(teardown)
+ file_system.delete(
+ [os.path.join(workspace.paths.project(), "TestAssets", "test_file.scriptevents")], True, True
+ )
+ expected_lines = [
+ "Success: New Script Event created",
+ "Success: Child Event created",
+ "Success: New parameters added",
+ "Success: Script event file saved",
+ "Success: Node found in Script Canvas",
+ ]
+ hydra.launch_and_validate_results(
+ request,
+ TEST_DIRECTORY,
+ editor,
+ "ScriptEvents_AllParamDatatypes_CreationSuccess.py",
+ expected_lines,
+ auto_test_mode=False,
+ timeout=60,
+ )
\ No newline at end of file
diff --git a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt
index d351ec0e6c..a3b6e36250 100644
--- a/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/smoke/CMakeLists.txt
@@ -14,6 +14,24 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
TEST_SUITE smoke
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}
+ PYTEST_MARKS "SUITE_smoke"
+ TIMEOUT 1500
+ RUNTIME_DEPENDENCIES
+ AZ::AssetProcessor
+ AZ::PythonBindingsExample
+ Legacy::Editor
+ AutomatedTesting.GameLauncher
+ AutomatedTesting.Assets
+ COMPONENT
+ Smoke
+ )
+
+ ly_add_pytest(
+ NAME AutomatedTesting::SandboxTest
+ TEST_SUITE sandbox
+ TEST_SERIAL
+ PATH ${CMAKE_CURRENT_LIST_DIR}
+ PYTEST_MARKS "SUITE_sandbox"
TIMEOUT 1500
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
diff --git a/AutomatedTesting/Gem/PythonTests/smoke/test_Editor_NewExistingLevels_Works.py b/AutomatedTesting/Gem/PythonTests/smoke/test_Editor_NewExistingLevels_Works.py
index 985740307f..e6b072ba58 100644
--- a/AutomatedTesting/Gem/PythonTests/smoke/test_Editor_NewExistingLevels_Works.py
+++ b/AutomatedTesting/Gem/PythonTests/smoke/test_Editor_NewExistingLevels_Works.py
@@ -15,7 +15,7 @@ from automatedtesting_shared.base import TestAutomationBase
import ly_test_tools.environment.file_system as file_system
-@pytest.mark.SUITE_smoke
+@pytest.mark.SUITE_sandbox
@pytest.mark.parametrize("launcher_platform", ["windows_editor"])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("level", ["temp_level"])
diff --git a/AutomatedTesting/Registry/C3510644_Collider_CollisionGroups.setreg_override b/AutomatedTesting/Registry/C3510644_Collider_CollisionGroups.setreg_override
index 9fa5e26768..696a0a74da 100644
--- a/AutomatedTesting/Registry/C3510644_Collider_CollisionGroups.setreg_override
+++ b/AutomatedTesting/Registry/C3510644_Collider_CollisionGroups.setreg_override
@@ -119,6 +119,9 @@
]
}
},
+ "DefaultMaterial": {
+ "SurfaceType": "Default_1"
+ },
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
diff --git a/AutomatedTesting/Registry/C4044459_Material_DynamicFriction.setreg_override b/AutomatedTesting/Registry/C4044459_Material_DynamicFriction.setreg_override
new file mode 100644
index 0000000000..c53b04e5c2
--- /dev/null
+++ b/AutomatedTesting/Registry/C4044459_Material_DynamicFriction.setreg_override
@@ -0,0 +1,118 @@
+{
+ "Amazon": {
+ "Gems": {
+ "PhysX": {
+ "PhysXSystemConfiguration": {
+ "CollisionConfig": {
+ "Layers": {
+ "LayerNames": [
+ "Default",
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ "TouchBend"
+ ]
+ },
+ "Groups": {
+ "GroupPresets": [
+ {
+ "Name": "All",
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
+ },
+ "Name": "None",
+ "Group": {
+ "Mask": 0
+ },
+ "ReadOnly": true
+ },
+ {
+ "Id": {
+ "GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
+ },
+ "Name": "All_NoTouchBend",
+ "Group": {
+ "Mask": 9223372036854775807
+ },
+ "ReadOnly": true
+ }
+ ]
+ }
+ },
+ "DefaultMaterial": {
+ "SurfaceType": "Default_1"
+ },
+ "MaterialLibrary": {
+ "assetId": {
+ "guid": "{6AA79EE4-7EC3-5717-87AE-EDD7D886FD7F}"
+ },
+ "loadBehavior": "QueueLoad",
+ "assetHint": "levels/physics/c4044459_material_dynamicfriction/dynamic_friction.physmaterial"
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Registry/C4976227_Collider_NewGroup.setreg_override b/AutomatedTesting/Registry/C4976227_Collider_NewGroup.setreg_override
index afbe6a9d38..5e98e08ede 100644
--- a/AutomatedTesting/Registry/C4976227_Collider_NewGroup.setreg_override
+++ b/AutomatedTesting/Registry/C4976227_Collider_NewGroup.setreg_override
@@ -107,6 +107,9 @@
]
}
},
+ "DefaultMaterial": {
+ "SurfaceType": "Default_1"
+ },
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
diff --git a/AutomatedTesting/Registry/C4976244_Collider_SameGroupSameLayerCollision.setreg_override b/AutomatedTesting/Registry/C4976244_Collider_SameGroupSameLayerCollision.setreg_override
index 9fa5e26768..696a0a74da 100644
--- a/AutomatedTesting/Registry/C4976244_Collider_SameGroupSameLayerCollision.setreg_override
+++ b/AutomatedTesting/Registry/C4976244_Collider_SameGroupSameLayerCollision.setreg_override
@@ -119,6 +119,9 @@
]
}
},
+ "DefaultMaterial": {
+ "SurfaceType": "Default_1"
+ },
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
diff --git a/AutomatedTesting/Registry/C4976245_PhysXCollider_CollisionLayerTest.setreg_override b/AutomatedTesting/Registry/C4976245_PhysXCollider_CollisionLayerTest.setreg_override
index 9fa5e26768..696a0a74da 100644
--- a/AutomatedTesting/Registry/C4976245_PhysXCollider_CollisionLayerTest.setreg_override
+++ b/AutomatedTesting/Registry/C4976245_PhysXCollider_CollisionLayerTest.setreg_override
@@ -119,6 +119,9 @@
]
}
},
+ "DefaultMaterial": {
+ "SurfaceType": "Default_1"
+ },
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
diff --git a/AutomatedTesting/Registry/C4982593_PhysXCollider_CollisionLayer.setreg_override b/AutomatedTesting/Registry/C4982593_PhysXCollider_CollisionLayer.setreg_override
index 9fa5e26768..696a0a74da 100644
--- a/AutomatedTesting/Registry/C4982593_PhysXCollider_CollisionLayer.setreg_override
+++ b/AutomatedTesting/Registry/C4982593_PhysXCollider_CollisionLayer.setreg_override
@@ -119,6 +119,9 @@
]
}
},
+ "DefaultMaterial": {
+ "SurfaceType": "Default_1"
+ },
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
diff --git a/AutomatedTesting/Registry/physxsystemconfiguration.setreg b/AutomatedTesting/Registry/physxsystemconfiguration.setreg
index 02f65b685b..30e9dced44 100644
--- a/AutomatedTesting/Registry/physxsystemconfiguration.setreg
+++ b/AutomatedTesting/Registry/physxsystemconfiguration.setreg
@@ -101,6 +101,9 @@
]
}
},
+ "DefaultMaterial": {
+ "SurfaceType": "Default_1"
+ },
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
diff --git a/AutomatedTesting/surfacetypemateriallibrary.physmaterial b/AutomatedTesting/surfacetypemateriallibrary.physmaterial
index 3c39d5521e..481cd2fbfa 100644
--- a/AutomatedTesting/surfacetypemateriallibrary.physmaterial
+++ b/AutomatedTesting/surfacetypemateriallibrary.physmaterial
@@ -1,19 +1,155 @@
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a7e42613cb..387f536966 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,34 +25,13 @@ include(cmake/LySet.cmake)
include(cmake/Version.cmake)
include(cmake/OutputDirectory.cmake)
-# Set the engine_path and engine_json
-set(o3de_engine_path ${CMAKE_CURRENT_LIST_DIR})
-set(o3de_engine_json ${o3de_engine_path}/engine.json)
-
if(NOT PROJECT_NAME)
project(O3DE
LANGUAGES C CXX
VERSION ${LY_VERSION_STRING}
)
-
- # o3de manifest
- include(cmake/o3de_manifest.cmake)
endif()
-################################################################################
-# Resolve this engines name and restricted path
-################################################################################
-o3de_engine_name(${o3de_engine_json} o3de_engine_name)
-o3de_restricted_path(${o3de_engine_json} o3de_engine_restricted_path)
-message(STATUS "O3DE Engine Name: ${o3de_engine_name}")
-message(STATUS "O3DE Engine Path: ${o3de_engine_path}")
-if(o3de_engine_restricted_path)
- message(STATUS "O3DE Engine Restricted Path: ${o3de_engine_restricted_path}")
-endif()
-
-# add the engines cmake folder to the CMAKE_MODULE_PATH
-list(APPEND CMAKE_MODULE_PATH "${o3de_engine_path}/cmake")
-
################################################################################
# Initialize
################################################################################
@@ -60,6 +39,7 @@ include(cmake/GeneralSettings.cmake)
include(cmake/FileUtil.cmake)
include(cmake/PAL.cmake)
include(cmake/PALTools.cmake)
+include(cmake/RuntimeDependencies.cmake)
include(cmake/Install.cmake)
include(cmake/Configurations.cmake) # Requires to be after PAL so we get platform variable definitions
include(cmake/Dependencies.cmake)
@@ -67,92 +47,106 @@ include(cmake/Deployment.cmake)
include(cmake/3rdParty.cmake)
include(cmake/LYPython.cmake)
include(cmake/LYWrappers.cmake)
+include(cmake/Gems.cmake)
include(cmake/UnitTest.cmake)
include(cmake/LYTestWrappers.cmake)
include(cmake/Monolithic.cmake)
include(cmake/SettingsRegistry.cmake)
include(cmake/TestImpactFramework/LYTestImpactFramework.cmake)
include(cmake/CMakeFiles.cmake)
+include(cmake/O3DEJson.cmake)
################################################################################
# Subdirectory processing
################################################################################
+function(add_engine_json_external_subdirectories)
+ read_json_external_subdirs(external_subdis ${LY_ROOT_FOLDER}/engine.json)
+ foreach(external_subdir ${external_subdis})
+ file(REAL_PATH ${external_subdir} real_external_subdir BASE_DIRECTORY ${LY_ROOT_FOLDER})
+ list(APPEND engine_external_subdirs ${real_external_subdir})
+ endforeach()
+
+ set_property(GLOBAL APPEND PROPERTY LY_EXTERNAL_SUBDIRS ${engine_external_subdirs})
+endfunction()
+
# Add the projects first so the Launcher can find them
include(cmake/Projects.cmake)
if(NOT INSTALLED_ENGINE)
+
# Add the rest of the targets
add_subdirectory(Code)
+ add_subdirectory(scripts)
+
+ # SPEC-1417 will investigate and fix this
+ if(NOT PAL_PLATFORM_NAME STREQUAL "Mac")
+ add_subdirectory(Tools/LyTestTools/tests/)
+ add_subdirectory(Tools/RemoteConsole/ly_remote_console/tests/)
+ endif()
+
+ # Add external subdirectories listed in the engine.json. LY_EXTERNAL_SUBDIRS is a cache variable so the user can add extra
+ # external subdirectories
+ add_engine_json_external_subdirectories()
+ get_property(external_subdirs GLOBAL PROPERTY LY_EXTERNAL_SUBDIRS)
+ list(APPEND LY_EXTERNAL_SUBDIRS ${external_subdirs})
+
+ # Loop over the additional external subdirectories and invoke add_subdirectory on them
+ foreach(external_directory ${LY_EXTERNAL_SUBDIRS})
+ # Hash the extenal_directory name and append it to the Binary Directory section of add_subdirectory
+ # This is to deal with potential situations where multiple external directories has the same last directory name
+ # For example if D:/Company1/RayTracingGem and F:/Company2/Path/RayTracingGem were both added as a subdirectory
+ file(REAL_PATH ${external_directory} full_directory_path)
+ string(SHA256 full_directory_hash ${full_directory_path})
+ # Truncate the full_directory_hash down to 8 characters to avoid hitting the Windows 260 character path limit
+ # when the external subdirectory contains relative paths of significant length
+ string(SUBSTRING ${full_directory_hash} 0 8 full_directory_hash)
+ # Use the last directory as the suffix path to use for the Binary Directory
+ get_filename_component(directory_name ${external_directory} NAME)
+ add_subdirectory(${external_directory} ${CMAKE_BINARY_DIR}/External/${directory_name}-${full_directory_hash})
+ endforeach()
+
else()
ly_find_o3de_packages()
endif()
-# Add external subdirectories listed in the manifest
-list(APPEND LY_EXTERNAL_SUBDIRS ${o3de_engine_external_subdirectories})
-
-set(enabled_platforms
- ${PAL_PLATFORM_NAME}
- ${LY_PAL_TOOLS_ENABLED})
-
-# Add any engine restricted platforms as external subdirs
-o3de_add_engine_restricted_platform_external_subdirs()
-
-if(NOT INSTALLED_ENGINE)
- add_subdirectory(scripts)
-endif()
-
-# SPEC-1417 will investigate and fix this
-if(NOT PAL_PLATFORM_NAME STREQUAL "Mac")
- add_subdirectory(Tools/LyTestTools/tests/)
- add_subdirectory(Tools/RemoteConsole/ly_remote_console/tests/)
-endif()
-
################################################################################
# Post-processing
################################################################################
-
-# Loop over the additional external subdirectories and invoke add_subdirectory on them
-foreach(external_directory ${LY_EXTERNAL_SUBDIRS})
- # Hash the extenal_directory name and append it to the Binary Directory section of add_subdirectory
- # This is to deal with potential situations where multiple external directories has the same last directory name
- # For example if D:/Company1/RayTracingGem and F:/Company2/Path/RayTracingGem were both added as a subdirectory
- file(REAL_PATH ${external_directory} full_directory_path)
- string(SHA256 full_directory_hash ${full_directory_path})
- # Truncate the full_directory_hash down to 8 characters to avoid hitting the Windows 260 character path limit
- # when the external subdirectory contains relative paths of significant length
- string(SUBSTRING ${full_directory_hash} 0 8 full_directory_hash)
- # Use the last directory as the suffix path to use for the Binary Directory
- get_filename_component(directory_name ${external_directory} NAME)
- add_subdirectory(${external_directory} ${CMAKE_BINARY_DIR}/External/${directory_name}-${full_directory_hash})
-endforeach()
-
# The following steps have to be done after all targets are registered:
# Defer generation of the StaticModules.inl file which is needed to create the AZ::Module derived class in monolithic
# builds until after all the targets are known
ly_delayed_generate_static_modules_inl()
-# 1. generate a settings registry .setreg file for all ly_add_project_dependencies() and ly_add_target_dependencies() calls
+# 1. Add any dependencies registered via ly_enable_gems
+ly_enable_gems_delayed()
+
+# 2. generate a settings registry .setreg file for all ly_add_project_dependencies() and ly_add_target_dependencies() calls
# to provide applications with the filenames of gem modules to load
# This must be done before ly_delayed_target_link_libraries() as that inserts BUILD_DEPENDENCIES as MANUALLY_ADDED_DEPENDENCIES
# if the build dependency is a MODULE_LIBRARY. That would cause a false load dependency to be generated
ly_delayed_generate_settings_registry()
-# 2. link targets where the dependency was yet not declared, we need to have the declaration so we do different
+
+# 3. link targets where the dependency was yet not declared, we need to have the declaration so we do different
# linking logic depending on the type of target
ly_delayed_target_link_libraries()
-# 3. generate a registry file for unit testing for platforms that support unit testing
+
+# 4. generate a registry file for unit testing for platforms that support unit testing
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_delayed_generate_unit_test_module_registry()
endif()
-# 4. inject runtime dependencies to the targets. We need to do this after (1) since we are going to walk through
-# the dependencies
-include(cmake/RuntimeDependencies.cmake)
-# 5. Perform test impact framework post steps once all of the targets have been enumerated
-ly_test_impact_post_step()
-# 6. Generate the O3DE find file and setup install locations for scripts, tools, assets etc., required by the engine
-if(NOT INSTALLED_ENGINE)
- ly_setup_o3de_install()
- # IMPORTANT: must be included last
+# 5. inject runtime dependencies to the targets. We need to do this after (1) since we are going to walk through
+# the dependencies
+ly_delayed_generate_runtime_dependencies()
+
+# 6. Perform test impact framework post steps once all of the targets have been enumerated
+ly_test_impact_post_step()
+
+# 7. Generate the O3DE find file and setup install locations for scripts, tools, assets etc., required by the engine
+if(NOT INSTALLED_ENGINE)
+ # 8. Generate the O3DE find file and setup install locations for scripts, tools, assets etc., required by the engine
+ ly_setup_o3de_install()
+ # 9. CPack information (to be included after install)
include(cmake/Packaging.cmake)
endif()
diff --git a/Code/CryEngine/CrySystem/LevelSystem/SpawnableLevelSystem.cpp b/Code/CryEngine/CrySystem/LevelSystem/SpawnableLevelSystem.cpp
index ff6ebc0d17..31d1540d77 100644
--- a/Code/CryEngine/CrySystem/LevelSystem/SpawnableLevelSystem.cpp
+++ b/Code/CryEngine/CrySystem/LevelSystem/SpawnableLevelSystem.cpp
@@ -36,8 +36,8 @@ namespace LegacyLevelSystem
//------------------------------------------------------------------------
static void LoadLevel(const AZ::ConsoleCommandContainer& arguments)
{
- AZ_Error("SpawnableLevelSystem", arguments.empty(), "LoadLevel requires a level file name to be provided.");
- AZ_Error("SpawnableLevelSystem", arguments.size() > 1, "LoadLevel requires a single level file name to be provided.");
+ AZ_Error("SpawnableLevelSystem", !arguments.empty(), "LoadLevel requires a level file name to be provided.");
+ AZ_Error("SpawnableLevelSystem", arguments.size() == 1, "LoadLevel requires a single level file name to be provided.");
if (!arguments.empty() && gEnv->pSystem && gEnv->pSystem->GetILevelSystem() && !gEnv->IsEditor())
{
diff --git a/Code/CryEngine/CrySystem/SystemInit.cpp b/Code/CryEngine/CrySystem/SystemInit.cpp
index 25d6b9c601..79041fa233 100644
--- a/Code/CryEngine/CrySystem/SystemInit.cpp
+++ b/Code/CryEngine/CrySystem/SystemInit.cpp
@@ -864,11 +864,6 @@ bool CSystem::InitShine([[maybe_unused]] const SSystemInitParams& initParams)
EBUS_EVENT(UiSystemBus, InitializeSystem);
- if (!m_env.pLyShine)
- {
- AZ_Error(AZ_TRACE_SYSTEM_WINDOW, false, "LYShine System did not initialize correctly. Please check that the LyShine gem is enabled for this project in *_dependencies.cmake.");
- return false;
- }
return true;
}
diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
index f03b1aac76..7b33359023 100644
--- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
+++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
@@ -77,6 +77,27 @@
#endif // defined(AZ_ENABLE_DEBUG_TOOLS)
#include
+#include
+
+static void PrintEntityName(const AZ::ConsoleCommandContainer& arguments)
+{
+ if (arguments.empty())
+ {
+ return;
+ }
+
+ const auto entityIdStr = AZStd::string(arguments.front());
+ const auto entityIdValue = AZStd::stoull(entityIdStr);
+
+ AZStd::string entityName;
+ AZ::ComponentApplicationBus::BroadcastResult(
+ entityName, &AZ::ComponentApplicationBus::Events::GetEntityName, AZ::EntityId(entityIdValue));
+
+ AZ_Printf("Entity Debug", "EntityId: %" PRIu64 ", Entity Name: %s", entityIdValue, entityName.c_str());
+}
+
+AZ_CONSOLEFREEFUNC(
+ PrintEntityName, AZ::ConsoleFunctorFlags::Null, "Parameter: EntityId value, Prints the name of the entity to the console");
namespace AZ
{
@@ -1260,7 +1281,7 @@ namespace AZ
// So auto load is turned off if option "AutoLoad" key is bool that is false
if (valueName == "AutoLoad" && !value)
{
- // Strip off the AutoLoead entry from the path
+ // Strip off the AutoLoad entry from the path
auto autoLoadKey = AZ::StringFunc::TokenizeLast(path, "/");
if (!autoLoadKey)
{
@@ -1330,7 +1351,7 @@ namespace AZ
{
auto CompareDynamicModuleDescriptor = [&dynamicLibraryPath](const DynamicModuleDescriptor& entry)
{
- return entry.m_dynamicLibraryPath.contains(dynamicLibraryPath);
+ return AZ::IO::PathView(entry.m_dynamicLibraryPath).Stem() == AZ::IO::PathView(dynamicLibraryPath).Stem();
};
if (auto moduleIter = AZStd::find_if(gemModules.begin(), gemModules.end(), CompareDynamicModuleDescriptor);
moduleIter == gemModules.end())
diff --git a/Code/Framework/AzCore/AzCore/Component/TransformBus.h b/Code/Framework/AzCore/AzCore/Component/TransformBus.h
index b180e97332..2a8d82c34c 100644
--- a/Code/Framework/AzCore/AzCore/Component/TransformBus.h
+++ b/Code/Framework/AzCore/AzCore/Component/TransformBus.h
@@ -219,18 +219,11 @@ namespace AZ
//! Scale modifiers
//! @{
- //! Set local scale of the transform.
- //! @param scale The new scale to set.
- virtual void SetLocalScale([[maybe_unused]] const AZ::Vector3& scale) {}
-
- //! Get the scale value in local space.
+ //! @deprecated GetLocalScale is deprecated, and is left only to allow migration of legacy vector scale.
+ //! Get the legacy vector scale value in local space.
//! @return The scale value in local space.
virtual AZ::Vector3 GetLocalScale() { return AZ::Vector3(FLT_MAX); }
- //! Get the scale value in world space.
- //! @return The scale value in world space.
- virtual AZ::Vector3 GetWorldScale() { return AZ::Vector3(FLT_MAX); }
-
//! Set the uniform scale value in local space.
virtual void SetLocalUniformScale([[maybe_unused]] float scale) {}
diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.h b/Code/Framework/AzCore/AzCore/IO/Path/Path.h
index 61294cd637..6c1b519224 100644
--- a/Code/Framework/AzCore/AzCore/IO/Path/Path.h
+++ b/Code/Framework/AzCore/AzCore/IO/Path/Path.h
@@ -95,6 +95,12 @@ namespace AZ::IO
constexpr int Compare(AZStd::string_view pathString) const noexcept;
constexpr int Compare(const value_type* pathString) const noexcept;
+ // Extension for fixed strings
+ //! extension: fixed string types with MaxPathLength capacity
+ //! Returns a new instance of an AZStd::fixed_string with capacity of MaxPathLength
+ //! made from the internal string
+ constexpr AZStd::fixed_string FixedMaxPathString() const noexcept;
+
// decomposition
//! Given a windows path of "C:\O3DE\foo\bar\name.txt" and a posix path of
//! "/O3DE/foo/bar/name.txt"
diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl
index 1e42fc9df7..05a92c5247 100644
--- a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl
+++ b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl
@@ -915,6 +915,11 @@ namespace AZ::IO
return compare_string_view(path);
}
+ constexpr AZStd::fixed_string PathView::FixedMaxPathString() const noexcept
+ {
+ return AZStd::fixed_string(m_path.begin(), m_path.end());
+ }
+
// decomposition
constexpr auto PathView::RootName() const -> PathView
{
diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.cpp b/Code/Framework/AzCore/AzCore/Math/Aabb.cpp
index 3f7cb4ecf5..367594be63 100644
--- a/Code/Framework/AzCore/AzCore/Math/Aabb.cpp
+++ b/Code/Framework/AzCore/AzCore/Math/Aabb.cpp
@@ -227,7 +227,7 @@ namespace AZ
// the min and max of each part and sum them to get the min and max co-ordinate of the transformed box. For a given new axis,
// the coefficients for what proportion of each original axis is rotated onto that new axis are the same as the components we
// would get by performing the inverse rotation on the new axis, so we need to take the conjugate to get the inverse rotation.
- axisCoeffs = transform.GetScale() * (transform.GetRotation().GetConjugate().TransformVector(axis));
+ axisCoeffs = transform.GetUniformScale() * (transform.GetRotation().GetConjugate().TransformVector(axis));
a = axisCoeffs * m_min;
b = axisCoeffs * m_max;
diff --git a/Code/Framework/AzCore/AzCore/Math/Obb.cpp b/Code/Framework/AzCore/AzCore/Math/Obb.cpp
index eb511669d0..9226ddd28f 100644
--- a/Code/Framework/AzCore/AzCore/Math/Obb.cpp
+++ b/Code/Framework/AzCore/AzCore/Math/Obb.cpp
@@ -154,7 +154,7 @@ namespace AZ
return Obb::CreateFromPositionRotationAndHalfLengths(
transform.TransformPoint(obb.GetPosition()),
transform.GetRotation() * obb.GetRotation(),
- transform.GetScale() * obb.GetHalfLengths()
+ transform.GetUniformScale() * obb.GetHalfLengths()
);
}
}
diff --git a/Code/Framework/AzCore/AzCore/Math/Transform.cpp b/Code/Framework/AzCore/AzCore/Math/Transform.cpp
index 9090a9e94e..62a390c138 100644
--- a/Code/Framework/AzCore/AzCore/Math/Transform.cpp
+++ b/Code/Framework/AzCore/AzCore/Math/Transform.cpp
@@ -130,8 +130,8 @@ namespace AZ
const Transform* transform = reinterpret_cast(classPtr);
float data[NumFloats];
transform->GetRotation().StoreToFloat4(data);
- transform->GetScale().StoreToFloat3(&data[4]);
- transform->GetTranslation().StoreToFloat3(&data[7]);
+ data[4] = transform->GetUniformScale();
+ transform->GetTranslation().StoreToFloat3(&data[5]);
for (int i = 0; i < NumFloats; i++)
{
@@ -159,8 +159,8 @@ namespace AZ
size_t TransformSerializer::TextToData(const char* text, unsigned int textVersion, IO::GenericStream& stream, bool isDataBigEndian)
{
- const size_t dataBufferSize = AZStd::max(NumFloatsVersion0, NumFloats);
- const size_t numElements = textVersion < 1 ? NumFloatsVersion0 : NumFloats;
+ const size_t dataBufferSize = AZStd::max(AZStd::max(NumFloatsVersion1, NumFloatsVersion0), NumFloats);
+ const size_t numElements = textVersion < 1 ? NumFloatsVersion0 : (textVersion == 1 ? NumFloatsVersion1 : NumFloats);
size_t nextNumberIndex = 0;
AZStd::array data;
@@ -201,7 +201,34 @@ namespace AZ
return true;
}
- // otherwise load as a separate rotation, scale and translation
+ // version 1 had a quaternion rotation, vector3 scale and vector3 translation
+ else if (version == 1)
+ {
+ float data[NumFloatsVersion1];
+ if (stream.GetLength() < sizeof(data))
+ {
+ return false;
+ }
+
+ stream.Read(sizeof(data), reinterpret_cast(data));
+
+ for (unsigned int i = 0; i < AZ_ARRAY_SIZE(data); ++i)
+ {
+ AZ_SERIALIZE_SWAP_ENDIAN(data[i], isDataBigEndian);
+ }
+
+ Quaternion rotation = Quaternion::CreateFromFloat4(data);
+ Vector3 vectorScale = Vector3::CreateFromFloat3(&data[4]);
+ Vector3 translation = Vector3::CreateFromFloat3(&data[7]);
+
+ float uniformScale = vectorScale.GetMaxElement();
+
+ *reinterpret_cast(classPtr) =
+ Transform::CreateFromQuaternionAndTranslation(rotation, translation) * Transform::CreateUniformScale(uniformScale);
+ return true;
+ }
+
+ // otherwise load as a quaternion rotation, float scale and vector3 translation
float data[NumFloats];
if (stream.GetLength() < sizeof(data))
{
@@ -216,11 +243,11 @@ namespace AZ
}
Quaternion rotation = Quaternion::CreateFromFloat4(data);
- Vector3 scale = Vector3::CreateFromFloat3(&data[4]);
- Vector3 translation = Vector3::CreateFromFloat3(&data[7]);
+ float scale = data[4];
+ Vector3 translation = Vector3::CreateFromFloat3(&data[5]);
*reinterpret_cast(classPtr) =
- Transform::CreateFromQuaternionAndTranslation(rotation, translation) * Transform::CreateScale(scale);
+ Transform::CreateFromQuaternionAndTranslation(rotation, translation) * Transform::CreateUniformScale(scale);
return true;
}
@@ -237,7 +264,7 @@ namespace AZ
if (serializeContext)
{
serializeContext->Class()
- ->Version(1)
+ ->Version(2)
->Serializer();
}
@@ -250,7 +277,7 @@ namespace AZ
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
Attribute(Script::Attributes::Storage, Script::Attributes::StorageType::Value)->
Attribute(Script::Attributes::GenericConstructorOverride, &Internal::TransformDefaultConstructor)->
- Constructor()->
+ Constructor()->
Method("GetBasis", &Transform::GetBasis)->
Method("GetBasisX", &Transform::GetBasisX)->
Method("GetBasisY", &Transform::GetBasisY)->
@@ -283,15 +310,10 @@ namespace AZ
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
Method("GetRotation", &Transform::GetRotation)->
Method("SetRotation", &Transform::SetRotation)->
- Method("GetScale", &Transform::GetScale)->
Method("GetUniformScale", &Transform::GetUniformScale)->
- Method("SetScale", &Transform::SetScale)->
Method("SetUniformScale", &Transform::SetUniformScale)->
- Method("ExtractScale", &Transform::ExtractScale)->
- Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
Method("ExtractUniformScale", &Transform::ExtractUniformScale)->
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
- Method("MultiplyByScale", &Transform::MultiplyByScale)->
Method("MultiplyByUniformScale", &Transform::MultiplyByUniformScale)->
Method("GetInverse", &Transform::GetInverse)->
Method("Invert", &Transform::Invert)->
@@ -310,7 +332,6 @@ namespace AZ
Method("CreateFromQuaternionAndTranslation", &Transform::CreateFromQuaternionAndTranslation)->
Method("CreateFromMatrix3x3", &Transform::CreateFromMatrix3x3)->
Method("CreateFromMatrix3x3AndTranslation", &Transform::CreateFromMatrix3x3AndTranslation)->
- Method("CreateScale", &Transform::CreateScale)->
Method("CreateUniformScale", &Transform::CreateUniformScale)->
Method("CreateTranslation", &Transform::CreateTranslation)->
Method("ConstructFromValuesNumeric", &Internal::ConstructTransformFromValues);
@@ -321,7 +342,7 @@ namespace AZ
{
Transform result;
Matrix3x3 tmp = value;
- result.m_scale = tmp.ExtractScale();
+ result.m_scale = tmp.ExtractScale().GetMaxElement();
result.m_rotation = Quaternion::CreateFromMatrix3x3(tmp);
result.m_translation = Vector3::CreateZero();
return result;
@@ -331,7 +352,7 @@ namespace AZ
{
Transform result;
Matrix3x3 tmp = value;
- result.m_scale = tmp.ExtractScale();
+ result.m_scale = tmp.ExtractScale().GetMaxElement();
result.m_rotation = Quaternion::CreateFromMatrix3x3(tmp);
result.m_translation = p;
return result;
@@ -341,7 +362,7 @@ namespace AZ
{
Transform result;
Matrix3x4 tmp = value;
- result.m_scale = tmp.ExtractScale();
+ result.m_scale = tmp.ExtractScale().GetMaxElement();
result.m_rotation = Quaternion::CreateFromMatrix3x4(tmp);
result.m_translation = value.GetTranslation();
return result;
diff --git a/Code/Framework/AzCore/AzCore/Math/Transform.h b/Code/Framework/AzCore/AzCore/Math/Transform.h
index 7ae86edd89..3fe6ddc98a 100644
--- a/Code/Framework/AzCore/AzCore/Math/Transform.h
+++ b/Code/Framework/AzCore/AzCore/Math/Transform.h
@@ -25,10 +25,13 @@ namespace AZ
: public SerializeContext::IDataSerializer
{
public:
- // number of floats in the serialized representation, 4 for rotation, 3 for scale and 3 for translation
- static constexpr int NumFloats = 10;
+ // number of floats in the serialized representation, 4 for rotation, 1 for scale and 3 for translation
+ static constexpr int NumFloats = 8;
- // number of floats in the old format, which stored a 3x4 matrix
+ // number of floats in version 1, which used 4 for rotation, 3 for scale and 3 for translation
+ static constexpr int NumFloatsVersion1 = 10;
+
+ // number of floats in version 0, which stored a 3x4 matrix
static constexpr int NumFloatsVersion0 = 12;
size_t Save(const void* classPtr, IO::GenericStream& stream, bool isDataBigEndian) override;
@@ -45,7 +48,7 @@ namespace AZ
static constexpr float MaxTransformScale = 1e9f;
//! @}
- //! The basic transformation class, represented using a quaternion rotation, vector scale and vector translation.
+ //! The basic transformation class, represented using a quaternion rotation, float scale and vector translation.
//! By design, cannot represent skew transformations.
class Transform
{
@@ -63,7 +66,7 @@ namespace AZ
Transform() = default;
//! Construct a transform from components.
- Transform(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
+ Transform(const Vector3& translation, const Quaternion& rotation, float scale);
//! Creates an identity transform.
static Transform CreateIdentity();
@@ -82,16 +85,20 @@ namespace AZ
static Transform CreateFromQuaternionAndTranslation(const class Quaternion& q, const Vector3& p);
//! Constructs from a Matrix3x3, translation is set to zero.
+ //! Note that Transform only allows uniform scale, so if the matrix has different scale values along its axes,
+ //! the largest matrix scale value will be used to uniformly scale the Transform.
static Transform CreateFromMatrix3x3(const class Matrix3x3& value);
- //! Constructs from a Matrix3x3, translation is set to zero.
+ //! Constructs from a Matrix3x3 and translation Vector3.
+ //! Note that Transform only allows uniform scale, so if the matrix has different scale values along its axes,
+ //! the largest matrix scale value will be used to uniformly scale the Transform.
static Transform CreateFromMatrix3x3AndTranslation(const class Matrix3x3& value, const Vector3& p);
+ //! Constructs from a Matrix3x4.
+ //! Note that Transform only allows uniform scale, so if the matrix has different scale values along its axes,
+ //! the largest matrix scale value will be used to uniformly scale the Transform.
static Transform CreateFromMatrix3x4(const Matrix3x4& value);
- //! Sets the transform to apply scale only, no rotation or translation.
- static Transform CreateScale(const AZ::Vector3& scale);
-
//! Sets the transform to apply (uniform) scale only, no rotation or translation.
static Transform CreateUniformScale(const float scale);
@@ -122,18 +129,12 @@ namespace AZ
const Quaternion& GetRotation() const;
void SetRotation(const Quaternion& rotation);
- Vector3 GetScale() const;
float GetUniformScale() const;
- void SetScale(const Vector3& v);
void SetUniformScale(const float scale);
- //! Sets the transform's scale to a unit value and returns the previous scale value.
- Vector3 ExtractScale();
-
//! Sets the transform's scale to a unit value and returns the previous scale value.
float ExtractUniformScale();
- void MultiplyByScale(const AZ::Vector3& scale);
void MultiplyByUniformScale(float scale);
Transform operator*(const Transform& rhs) const;
@@ -168,7 +169,7 @@ namespace AZ
private:
Quaternion m_rotation;
- Vector3 m_scale;
+ float m_scale;
Vector3 m_translation;
};
diff --git a/Code/Framework/AzCore/AzCore/Math/Transform.inl b/Code/Framework/AzCore/AzCore/Math/Transform.inl
index a7d5e72749..5f71316b52 100644
--- a/Code/Framework/AzCore/AzCore/Math/Transform.inl
+++ b/Code/Framework/AzCore/AzCore/Math/Transform.inl
@@ -12,7 +12,7 @@
namespace AZ
{
- AZ_MATH_INLINE Transform::Transform(const Vector3& translation, const Quaternion& rotation, const Vector3& scale)
+ AZ_MATH_INLINE Transform::Transform(const Vector3& translation, const Quaternion& rotation, float scale)
: m_translation(translation)
, m_rotation(rotation)
, m_scale(scale)
@@ -25,7 +25,7 @@ namespace AZ
{
Transform result;
result.m_rotation = Quaternion::CreateIdentity();
- result.m_scale = Vector3::CreateOne();
+ result.m_scale = 1.0f;
result.m_translation = Vector3::CreateZero();
return result;
}
@@ -49,7 +49,7 @@ namespace AZ
{
Transform result;
result.m_rotation = q;
- result.m_scale = Vector3::CreateOne();
+ result.m_scale = 1.0f;
result.m_translation = Vector3::CreateZero();
return result;
}
@@ -58,26 +58,16 @@ namespace AZ
{
Transform result;
result.m_rotation = q;
- result.m_scale = Vector3::CreateOne();
+ result.m_scale = 1.0f;
result.m_translation = p;
return result;
}
- AZ_MATH_INLINE Transform Transform::CreateScale(const Vector3& scale)
- {
- AZ_WarningOnce("Transform", false, "CreateScale is deprecated, please use CreateUniformScale instead.");
- Transform result;
- result.m_rotation = Quaternion::CreateIdentity();
- result.m_scale = scale;
- result.m_translation = Vector3::CreateZero();
- return result;
- }
-
AZ_MATH_INLINE Transform Transform::CreateUniformScale(float scale)
{
Transform result;
result.m_rotation = Quaternion::CreateIdentity();
- result.m_scale = Vector3(scale);
+ result.m_scale = scale;
result.m_translation = Vector3::CreateZero();
return result;
}
@@ -86,7 +76,7 @@ namespace AZ
{
Transform result;
result.m_rotation = Quaternion::CreateIdentity();
- result.m_scale = Vector3::CreateOne();
+ result.m_scale = 1.0f;
result.m_translation = translation;
return result;
}
@@ -114,17 +104,17 @@ namespace AZ
AZ_MATH_INLINE Vector3 Transform::GetBasisX() const
{
- return m_rotation.TransformVector(Vector3::CreateAxisX(m_scale.GetX()));
+ return m_rotation.TransformVector(Vector3::CreateAxisX(m_scale));
}
AZ_MATH_INLINE Vector3 Transform::GetBasisY() const
{
- return m_rotation.TransformVector(Vector3::CreateAxisY(m_scale.GetY()));
+ return m_rotation.TransformVector(Vector3::CreateAxisY(m_scale));
}
AZ_MATH_INLINE Vector3 Transform::GetBasisZ() const
{
- return m_rotation.TransformVector(Vector3::CreateAxisZ(m_scale.GetZ()));
+ return m_rotation.TransformVector(Vector3::CreateAxisZ(m_scale));
}
AZ_MATH_INLINE void Transform::GetBasisAndTranslation(Vector3* basisX, Vector3* basisY, Vector3* basisZ, Vector3* pos) const
@@ -160,49 +150,23 @@ namespace AZ
m_rotation = rotation;
}
- AZ_MATH_INLINE Vector3 Transform::GetScale() const
- {
- AZ_WarningOnce("Transform", false, "GetScale is deprecated, please use GetUniformScale instead.");
- return m_scale;
- }
-
AZ_MATH_INLINE float Transform::GetUniformScale() const
{
- return m_scale.GetMaxElement();
- }
-
- AZ_MATH_INLINE void Transform::SetScale(const Vector3& scale)
- {
- AZ_WarningOnce("Transform", false, "SetScale is deprecated, please use SetUniformScale instead.");
- m_scale = scale;
+ return m_scale;
}
AZ_MATH_INLINE void Transform::SetUniformScale(const float scale)
{
- m_scale = Vector3(scale);
- }
-
- AZ_MATH_INLINE Vector3 Transform::ExtractScale()
- {
- AZ_WarningOnce("Transform", false, "ExtractScale is deprecated, please use ExtractUniformScale instead.");
- const Vector3 scale = m_scale;
- m_scale = Vector3::CreateOne();
- return scale;
+ m_scale = scale;
}
AZ_MATH_INLINE float Transform::ExtractUniformScale()
{
- const float scale = m_scale.GetMaxElement();
- m_scale = Vector3::CreateOne();
+ const float scale = m_scale;
+ m_scale = 1.0f;
return scale;
}
- AZ_MATH_INLINE void Transform::MultiplyByScale(const Vector3& scale)
- {
- AZ_WarningOnce("Transform", false, "MultiplyByScale is deprecated, please use MultiplyByUniformScale instead.");
- m_scale *= scale;
- }
-
AZ_MATH_INLINE void Transform::MultiplyByUniformScale(float scale)
{
m_scale *= scale;
@@ -240,10 +204,9 @@ namespace AZ
AZ_MATH_INLINE Transform Transform::GetInverse() const
{
- // note - need to be careful about how to calculate inverse when there is non-uniform scale
Transform out;
out.m_rotation = m_rotation.GetConjugate();
- out.m_scale = m_scale.GetReciprocal();
+ out.m_scale = 1.0f / m_scale;
out.m_translation = -out.m_scale * (out.m_rotation.TransformVector(m_translation));
return out;
}
@@ -255,27 +218,27 @@ namespace AZ
AZ_MATH_INLINE bool Transform::IsOrthogonal(float tolerance) const
{
- return m_scale.IsClose(Vector3::CreateOne(), tolerance);
+ return AZ::IsClose(m_scale, 1.0f, tolerance);
}
AZ_MATH_INLINE Transform Transform::GetOrthogonalized() const
{
Transform result;
result.m_rotation = m_rotation;
- result.m_scale = Vector3::CreateOne();
+ result.m_scale = 1.0f;
result.m_translation = m_translation;
return result;
}
AZ_MATH_INLINE void Transform::Orthogonalize()
{
- m_scale = Vector3::CreateOne();
+ m_scale = 1.0f;
}
AZ_MATH_INLINE bool Transform::IsClose(const Transform& rhs, float tolerance) const
{
return m_rotation.IsClose(rhs.m_rotation, tolerance)
- && m_scale.IsClose(rhs.m_scale, tolerance)
+ && AZ::IsClose(m_scale, rhs.m_scale, tolerance)
&& m_translation.IsClose(rhs.m_translation, tolerance);
}
@@ -304,21 +267,21 @@ namespace AZ
AZ_MATH_INLINE void Transform::SetFromEulerDegrees(const Vector3& eulerDegrees)
{
m_translation = Vector3::CreateZero();
- m_scale = Vector3::CreateOne();
+ m_scale = 1.0f;
m_rotation.SetFromEulerDegrees(eulerDegrees);
}
AZ_MATH_INLINE void Transform::SetFromEulerRadians(const Vector3& eulerRadians)
{
m_translation = Vector3::CreateZero();
- m_scale = Vector3::CreateOne();
+ m_scale = 1.0f;
m_rotation.SetFromEulerRadians(eulerRadians);
}
AZ_MATH_INLINE bool Transform::IsFinite() const
{
return m_rotation.IsFinite()
- && m_scale.IsFinite()
+ && AZ::IsFiniteFloat(m_scale)
&& m_translation.IsFinite();
}
diff --git a/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp b/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp
index 86bc1c36ea..36c40265af 100644
--- a/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Math/TransformSerializer.cpp
@@ -67,7 +67,7 @@ namespace AZ
result.Combine(loadResult);
- transformInstance->SetScale(AZ::Vector3(scale));
+ transformInstance->SetUniformScale(scale);
}
return context.Report(
diff --git a/Code/Framework/AzCore/AzCore/Module/ModuleManager.cpp b/Code/Framework/AzCore/AzCore/Module/ModuleManager.cpp
index fe41050b00..0ce3ee5d8d 100644
--- a/Code/Framework/AzCore/AzCore/Module/ModuleManager.cpp
+++ b/Code/Framework/AzCore/AzCore/Module/ModuleManager.cpp
@@ -512,7 +512,7 @@ namespace AZ
// Load DLLs specified in the application descriptor
for (const auto& moduleDescriptor : modules)
{
- // For each module that is loaded, attempt to set the module's folder as a path for dependent module resolution
+ // For each module that is loaded, attempt to set the module's folder as a path for dependent module resolution
moduleSearchPathHelper.SetModuleSearchPath(moduleDescriptor);
LoadModuleOutcome result = LoadDynamicModule(moduleDescriptor.m_dynamicLibraryPath.c_str(), lastStepToPerform, maintainReferences);
diff --git a/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl b/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl
index 1016027966..dfd0707ed2 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl
+++ b/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl
@@ -123,6 +123,7 @@ namespace AZ
const static AZ::Crc32 NameLabelOverride = AZ_CRC("NameLabelOverride", 0x9ff79cab);
const static AZ::Crc32 AssetPickerTitle = AZ_CRC_CE("AssetPickerTitle");
+ const static AZ::Crc32 HideProductFilesInAssetPicker = AZ_CRC_CE("HideProductFilesInAssetPicker");
const static AZ::Crc32 ChildNameLabelOverride = AZ_CRC("ChildNameLabelOverride", 0x73dd2909);
//! Container attribute that is used to override labels for its elements given the index of the element
const static AZ::Crc32 IndexedChildNameLabelOverride = AZ_CRC("IndexedChildNameLabelOverride", 0x5f313ac2);
diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
index 5870c66633..2abef3f808 100644
--- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
+++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp
@@ -88,6 +88,35 @@ namespace AZ::Internal
m_enginePaths.emplace_back(EngineInfo{AZ::IO::FixedMaxPath{value}.LexicallyNormal(), {}});
}
+ AZ::SettingsRegistryInterface::VisitResponse Traverse(
+ [[maybe_unused]] AZStd::string_view path, AZStd::string_view valueName,
+ AZ::SettingsRegistryInterface::VisitAction action, AZ::SettingsRegistryInterface::Type type) override
+ {
+ auto response = AZ::SettingsRegistryInterface::VisitResponse::Continue;
+ if (action == AZ::SettingsRegistryInterface::VisitAction::Begin)
+ {
+ if (type == AZ::SettingsRegistryInterface::Type::Array)
+ {
+ if (valueName.compare("engines") != 0)
+ {
+ response = AZ::SettingsRegistryInterface::VisitResponse::Skip;
+ }
+ }
+ }
+ else if (action == AZ::SettingsRegistryInterface::VisitAction::Value)
+ {
+ if (type == AZ::SettingsRegistryInterface::Type::String)
+ {
+ if (valueName.compare("path") != 0)
+ {
+ response = AZ::SettingsRegistryInterface::VisitResponse::Skip;
+ }
+ }
+ }
+
+ return response;
+ }
+
AZStd::vector m_enginePaths{};
};
diff --git a/Code/Framework/AzCore/Tests/AZTestShared/Math/MathTestHelpers.cpp b/Code/Framework/AzCore/Tests/AZTestShared/Math/MathTestHelpers.cpp
index 42b77f6976..f9616702f1 100644
--- a/Code/Framework/AzCore/Tests/AZTestShared/Math/MathTestHelpers.cpp
+++ b/Code/Framework/AzCore/Tests/AZTestShared/Math/MathTestHelpers.cpp
@@ -68,7 +68,7 @@ namespace AZ
return os
<< "translation: " << transform.GetTranslation()
<< " rotation: " << transform.GetRotation()
- << " scale: " << transform.GetScale();
+ << " scale: " << transform.GetUniformScale();
}
std::ostream& operator<<(std::ostream& os, const Color& color)
diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/TransformSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/TransformSerializerTests.cpp
index 7eabd6e5e0..750f2ebc9c 100644
--- a/Code/Framework/AzCore/Tests/Serialization/Json/TransformSerializerTests.cpp
+++ b/Code/Framework/AzCore/Tests/Serialization/Json/TransformSerializerTests.cpp
@@ -44,7 +44,7 @@ namespace JsonSerializationTests
AZStd::shared_ptr CreateFullySetInstance() override
{
return AZStd::make_shared(
- AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion(0.25f, 0.5f, 0.75f, 1.0f), AZ::Vector3(9.0f));
+ AZ::Vector3(1.0f, 2.0f, 3.0f), AZ::Quaternion(0.25f, 0.5f, 0.75f, 1.0f), 9.0f);
}
AZStd::string_view GetJsonForFullySetInstance() override
@@ -95,7 +95,7 @@ namespace JsonSerializationTests
AZ::Transform expectedTransform(
AZ::Vector3(2.25f, 3.5f, 4.75f),
AZ::Quaternion(0.25f, 0.5f, 0.75f, 1.0f),
- AZ::Vector3(5.5f));
+ 5.5f);
rapidjson::Document json;
json.Parse(R"({ "Translation": [ 2.25, 3.5, 4.75 ], "Rotation": [ 0.25, 0.5, 0.75, 1.0 ], "Scale": 5.5 })");
diff --git a/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.cpp b/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.cpp
index 49adab2252..b3c4f1b256 100644
--- a/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.cpp
@@ -406,21 +406,10 @@ namespace AzFramework
return m_localTM.GetRotation();
}
- void TransformComponent::SetLocalScale(const AZ::Vector3& scale)
- {
- AZ::Transform newLocalTM = m_localTM;
- newLocalTM.SetScale(scale);
- SetLocalTM(newLocalTM);
- }
-
AZ::Vector3 TransformComponent::GetLocalScale()
{
- return m_localTM.GetScale();
- }
-
- AZ::Vector3 TransformComponent::GetWorldScale()
- {
- return m_worldTM.GetScale();
+ AZ_WarningOnce("TransformComponent", false, "GetLocalScale is deprecated, please use GetLocalUniformScale instead");
+ return AZ::Vector3(m_localTM.GetUniformScale());
}
void TransformComponent::SetLocalUniformScale(float scale)
@@ -756,11 +745,11 @@ namespace AzFramework
->Event("GetLocalRotationQuaternion", &AZ::TransformBus::Events::GetLocalRotationQuaternion)
->Attribute("Rotation", AZ::Edit::Attributes::PropertyRotation)
->VirtualProperty("Rotation", "GetLocalRotationQuaternion", "SetLocalRotationQuaternion")
- ->Event("SetLocalScale", &AZ::TransformBus::Events::SetLocalScale)
->Event("GetLocalScale", &AZ::TransformBus::Events::GetLocalScale)
->Attribute("Scale", AZ::Edit::Attributes::PropertyScale)
- ->VirtualProperty("Scale", "GetLocalScale", "SetLocalScale")
- ->Event("GetWorldScale", &AZ::TransformBus::Events::GetWorldScale)
+ ->Event("SetLocalUniformScale", &AZ::TransformBus::Events::SetLocalUniformScale)
+ ->Event("GetLocalUniformScale", &AZ::TransformBus::Events::GetLocalUniformScale)
+ ->VirtualProperty("Uniform Scale", "GetLocalUniformScale", "SetLocalUniformScale")
->Event("GetChildren", &AZ::TransformBus::Events::GetChildren)
->Event("GetAllDescendants", &AZ::TransformBus::Events::GetAllDescendants)
->Event("GetEntityAndAllDescendants", &AZ::TransformBus::Events::GetEntityAndAllDescendants)
diff --git a/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.h b/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.h
index 9009c6bff9..0301334a0d 100644
--- a/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.h
+++ b/Code/Framework/AzFramework/AzFramework/Components/TransformComponent.h
@@ -128,9 +128,7 @@ namespace AzFramework
AZ::Quaternion GetLocalRotationQuaternion() override;
// Scale Modifiers
- void SetLocalScale(const AZ::Vector3& scale) override;
AZ::Vector3 GetLocalScale() override;
- AZ::Vector3 GetWorldScale() override;
void SetLocalUniformScale(float scale) override;
float GetLocalUniformScale() override;
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/ClassConverters.cpp b/Code/Framework/AzFramework/AzFramework/Physics/ClassConverters.cpp
index e43bda4c88..4f206858af 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/ClassConverters.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Physics/ClassConverters.cpp
@@ -259,11 +259,18 @@ namespace Physics
if (success)
{
- success = success && dataElement.RemoveElementByName(AZ_CRC("MaterialId", 0x9360e002));
+ dataElement.RemoveElementByName(AZ_CRC("MaterialId", 0x9360e002));
+ success = success && (dataElement.FindElement(AZ_CRC("MaterialId", 0x9360e002)) < 0);
success = success && dataElement.AddElementWithData(context, "MaterialIds", AZStd::vector { materialId });
}
}
+ if (success && dataElement.GetVersion() <= 2)
+ {
+ dataElement.RemoveElementByName(AZ_CRC_CE("Material"));
+ success = success && (dataElement.FindElement(AZ_CRC_CE("Material")) < 0);
+ }
+
return success;
}
} // namespace ClassConverters
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsEvents.h b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsEvents.h
index d5a82c0367..a3a34dc1df 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsEvents.h
+++ b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsEvents.h
@@ -58,9 +58,18 @@ namespace AzPhysics
//! When triggered will send the handle to the old Scene (after this call, the Handle will be invalid).
using OnSceneRemovedEvent = AZ::Event;
- //! Event that triggers when the default material library changes.
+ //! Event that triggers when the material library changes.
//! When triggered the event will send the Asset Id of the new material library.
- using OnDefaultMaterialLibraryChangedEvent = AZ::Event;
+ using OnMaterialLibraryChangedEvent = AZ::Event;
+
+ enum class MaterialLibraryLoadErrorType : uint8_t
+ {
+ InvalidId,
+ ErrorLoading
+ };
+
+ //! Event that triggers when the default material library has loaded with errors.
+ using OnMaterialLibraryLoadErrorEvent = AZ::Event;
//! Event that triggers when the default scene configuration changes.
//! When triggered the event will send the new default scene configuration.
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSimulatedBody.h b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSimulatedBody.h
index ed8a68dc24..9d45a17edc 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSimulatedBody.h
+++ b/Code/Framework/AzFramework/AzFramework/Physics/Common/PhysicsSimulatedBody.h
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -68,6 +69,22 @@ namespace AzPhysics
return m_customUserData;
}
+ //! Helper functions for setting frame ID.
+ //! @param frameId Optionally set frame ID for the systems moving the actors back in time.
+ void SetFrameId(uint32_t frameId)
+ {
+ m_frameId = frameId;
+ }
+
+ //! Helper functions for getting the set frame ID.
+ //! @return Will return the frame ID.
+ uint32_t GetFrameId() const
+ {
+ return m_frameId;
+ }
+
+ static constexpr uint32_t UndefinedFrameId = AZStd::numeric_limits::max();
+
//! Perform a ray cast on this Simulated Body.
//! @param request The request to make.
//! @return Returns the closest hit, if any, against this simulated body.
@@ -126,6 +143,7 @@ namespace AzPhysics
SimulatedBodyEvents::OnTriggerExit m_triggerExitEvent;
void* m_customUserData = nullptr;
+ uint32_t m_frameId = UndefinedFrameId;
// helpers for reflecting to behavior context
SimulatedBodyEvents::OnCollisionBegin* GetOnCollisionBeginEvent();
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SystemConfiguration.cpp b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SystemConfiguration.cpp
index cd250b71a9..d7532cbfea 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SystemConfiguration.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SystemConfiguration.cpp
@@ -39,6 +39,8 @@ namespace AzPhysics
->Field("ShapecastBufferSize", &SystemConfiguration::m_shapecastBufferSize)
->Field("OverlapBufferSize", &SystemConfiguration::m_overlapBufferSize)
->Field("CollisionConfig", &SystemConfiguration::m_collisionConfig)
+ ->Field("DefaultMaterial", &SystemConfiguration::m_defaultMaterialConfiguration)
+ ->Field("MaterialLibrary", &SystemConfiguration::m_materialLibraryAsset)
;
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
@@ -79,7 +81,9 @@ namespace AzPhysics
m_overlapBufferSize == other.m_overlapBufferSize &&
AZ::IsClose(m_maxTimestep, other.m_maxTimestep) &&
AZ::IsClose(m_fixedTimestep, other.m_fixedTimestep) &&
- m_collisionConfig == other.m_collisionConfig
+ m_collisionConfig == other.m_collisionConfig &&
+ m_defaultMaterialConfiguration == other.m_defaultMaterialConfiguration &&
+ m_materialLibraryAsset == other.m_materialLibraryAsset
;
}
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SystemConfiguration.h b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SystemConfiguration.h
index 0a00d627a7..56fe9a68c4 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SystemConfiguration.h
+++ b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SystemConfiguration.h
@@ -13,6 +13,7 @@
#include
#include
+#include
namespace AZ
{
@@ -45,6 +46,9 @@ namespace AzPhysics
//! Each Physics Scene uses this as a base and will override as needed.
CollisionConfiguration m_collisionConfig;
+ Physics::MaterialConfiguration m_defaultMaterialConfiguration; //!< Default material parameters for the project.
+ AZ::Data::Asset m_materialLibraryAsset = AZ::Data::AssetLoadBehavior::NoLoad; //!< Material Library exposed by the system component SystemBus API.
+
//! Controls whether the Physics System will self register to the TickBus and call StartSimulation / FinishSimulation on each Scene.
//! Disable this to manually control Physics Scene simulation logic.
bool m_autoManageSimulationUpdate = true;
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Material.cpp b/Code/Framework/AzFramework/AzFramework/Physics/Material.cpp
index 5552cef448..78e0431753 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/Material.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Physics/Material.cpp
@@ -49,10 +49,7 @@ namespace Physics
{
materialSelection->SetMaterialSlots(Physics::MaterialSelection::SlotsArray());
}
- if (materialSelection->IsDefaultMaterialLibraryAsset())
- {
- materialSelection->SyncSelectionToMaterialLibrary();
- }
+ materialSelection->SyncSelectionToMaterialLibrary();
}
};
@@ -122,6 +119,24 @@ namespace Physics
}
}
+ bool MaterialConfiguration::operator==(const MaterialConfiguration& other) const
+ {
+ return m_surfaceType == other.m_surfaceType &&
+ AZ::IsClose(m_dynamicFriction, other.m_dynamicFriction) &&
+ AZ::IsClose(m_staticFriction, other.m_staticFriction) &&
+ AZ::IsClose(m_restitution, other.m_restitution) &&
+ AZ::IsClose(m_density, other.m_density) &&
+ m_restitutionCombine == other.m_restitutionCombine &&
+ m_frictionCombine == other.m_frictionCombine &&
+ m_debugColor == other.m_debugColor
+ ;
+ }
+
+ bool MaterialConfiguration::operator!=(const MaterialConfiguration& other) const
+ {
+ return !(*this == other);
+ }
+
AZ::Color MaterialConfiguration::GenerateDebugColor(const char* materialName)
{
static const AZ::Color colors[] =
@@ -191,51 +206,25 @@ namespace Physics
//////////////////////////////////////////////////////////////////////////
- void MaterialLibraryAssetReflectionWrapper::Reflect(AZ::ReflectContext* context)
- {
- AZ::SerializeContext* serializeContext = azrtti_cast(context);
- if (serializeContext)
- {
- serializeContext->Class()
- ->Version(1)
- ->Field("Asset", &MaterialLibraryAssetReflectionWrapper::m_asset)
- ;
-
- AZ::EditContext* editContext = serializeContext->GetEditContext();
- if (editContext)
- {
- editContext->Class("", "")
- ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
- ->Attribute(AZ::Edit::Attributes::AutoExpand, "")
- ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
- ->DataElement(AZ::Edit::UIHandlers::Default, &MaterialLibraryAssetReflectionWrapper::m_asset, "Physics Material Library", "Physics Material Library")
- ->Attribute("EditButton", "")
- ;
- }
- }
- }
-
- //////////////////////////////////////////////////////////////////////////
-
-
- void DefaultMaterialLibraryAssetReflectionWrapper::Reflect(AZ::ReflectContext* context)
+ void MaterialInfoReflectionWrapper::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast(context);
if (serializeContext)
{
- serializeContext->Class()
+ serializeContext->Class()
->Version(1)
- ->Field("Asset", &DefaultMaterialLibraryAssetReflectionWrapper::m_asset)
+ ->Field("DefaultMaterial", &MaterialInfoReflectionWrapper::m_defaultMaterialConfiguration)
+ ->Field("Asset", &MaterialInfoReflectionWrapper::m_materialLibraryAsset)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
- editContext->Class("", "")
+ editContext->Class("Physics Materials", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
- ->Attribute(AZ::Edit::Attributes::AutoExpand, "")
- ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
- ->DataElement(AZ::Edit::UIHandlers::Default, &DefaultMaterialLibraryAssetReflectionWrapper::m_asset, "Default Physics Material Library", "Library to use by default")
+ ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
+ ->DataElement(AZ::Edit::UIHandlers::Default, &MaterialInfoReflectionWrapper::m_defaultMaterialConfiguration, "Default Physics Material", "Material used by default")
+ ->DataElement(AZ::Edit::UIHandlers::Default, &MaterialInfoReflectionWrapper::m_materialLibraryAsset, "Physics Material Library", "Library to use for the project")
->Attribute(AZ::Edit::Attributes::AllowClearAsset, false)
->Attribute("EditButton", "")
;
@@ -269,6 +258,17 @@ namespace Physics
}
}
+ bool MaterialFromAssetConfiguration::operator==(const MaterialFromAssetConfiguration& other) const
+ {
+ return m_configuration == other.m_configuration &&
+ m_id == other.m_id;
+ }
+
+ bool MaterialFromAssetConfiguration::operator!=(const MaterialFromAssetConfiguration& other) const
+ {
+ return !(*this == other);
+ }
+
//////////////////////////////////////////////////////////////////////////
bool MaterialLibraryAsset::GetDataForMaterialId(const MaterialId& materialId, MaterialFromAssetConfiguration& configuration) const
@@ -370,9 +370,8 @@ namespace Physics
if (auto serializeContext = azrtti_cast(context))
{
serializeContext->Class()
- ->Version(2, &ClassConverters::MaterialSelectionConverter)
+ ->Version(3, &ClassConverters::MaterialSelectionConverter)
->EventHandler()
- ->Field("Material", &MaterialSelection::m_materialLibrary)
->Field("MaterialIds", &MaterialSelection::m_materialIdsAssignedToSlots)
;
@@ -381,14 +380,8 @@ namespace Physics
editContext->Class("Physics Material", "Select physics material library and which materials to use for the object")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
- ->DataElement(AZ::Edit::UIHandlers::Default, &MaterialSelection::m_materialLibrary, "Library", "Physics material library to use for this object")
- ->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, true)
- ->Attribute("EditButton", "")
- ->Attribute("EditDescription", "Open in Asset Editor")
- ->Attribute(AZ::Edit::Attributes::DefaultAsset, &MaterialSelection::GetDefaultMaterialLibraryId)
- ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MaterialSelection::OnMaterialLibraryChanged)
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialSelection::m_materialIdsAssignedToSlots, "Mesh Surfaces", "Specify which Physics Material to use for each element of this object")
- ->ElementAttribute(Attributes::MaterialLibraryAssetId, &MaterialSelection::GetMaterialLibraryAssetId)
+ ->ElementAttribute(Attributes::MaterialLibraryAssetId, &MaterialSelection::GetMaterialLibraryId)
->Attribute(AZ::Edit::Attributes::IndexedChildNameLabelOverride, &MaterialSelection::GetMaterialSlotLabel)
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->ElementAttribute(AZ::Edit::Attributes::ReadOnly, &MaterialSelection::AreMaterialSlotsReadOnly)
@@ -398,12 +391,6 @@ namespace Physics
}
}
- AZ::u32 MaterialSelection::OnMaterialLibraryChanged()
- {
- SyncSelectionToMaterialLibrary();
- return AZ::Edit::PropertyRefreshLevels::EntireTree;
- }
-
AZStd::string MaterialSelection::GetMaterialSlotLabel(int index)
{
if (index < m_materialSlots.size())
@@ -425,28 +412,9 @@ namespace Physics
}
}
- AZ::Data::AssetId MaterialSelection::GetMaterialLibraryAssetId() const
+ void MaterialSelection::OnMaterialLibraryChanged([[maybe_unused]] const AZ::Data::AssetId& defaultMaterialLibraryId)
{
- return GetMaterialLibraryAsset().GetId();
- }
-
- const Physics::MaterialLibraryAsset* MaterialSelection::GetMaterialLibraryAssetData() const
- {
- return GetMaterialLibraryAsset().Get();
- }
-
- const AZStd::string& MaterialSelection::GetMaterialLibraryAssetHint() const
- {
- return m_materialLibrary.GetHint();
- }
-
- void MaterialSelection::OnDefaultMaterialLibraryChanged(const AZ::Data::AssetId& defaultMaterialLibraryId)
- {
- AZ_UNUSED(defaultMaterialLibraryId);
- if (IsDefaultMaterialLibraryAsset())
- {
- OnMaterialLibraryChanged();
- }
+ SyncSelectionToMaterialLibrary();
}
void MaterialSelection::SetSlotsReadOnly(bool readOnly)
@@ -454,45 +422,6 @@ namespace Physics
m_slotsReadOnly = readOnly;
}
- bool MaterialSelection::IsMaterialLibraryValid() const
- {
- if (GetMaterialLibraryAssetId().IsValid())
- {
- auto materialAsset = LoadAsset();
- const auto& materialsData = materialAsset.Get()->GetMaterialsData();
-
- if (materialsData.size() != 0)
- {
- return true;
- }
- }
- return false;
- }
-
- bool MaterialSelection::GetMaterialConfiguration(Physics::MaterialFromAssetConfiguration& configuration, const Physics::MaterialId& materialId) const
- {
- if (IsMaterialLibraryValid())
- {
- auto materialAsset = LoadAsset();
- if (materialAsset.Get())
- {
- return materialAsset.Get()->GetDataForMaterialId(materialId, configuration);
- }
- }
- return false;
- }
-
- void MaterialSelection::SetMaterialLibrary(const AZ::Data::AssetId& assetId)
- {
- m_materialLibrary = AZ::Data::AssetManager::Instance().GetAsset(assetId, m_materialLibrary.GetAutoLoadBehavior());
- m_materialLibrary.BlockUntilLoadComplete();
- }
-
- void MaterialSelection::ResetToDefaultMaterialLibrary()
- {
- m_materialLibrary = {};
- }
-
void MaterialSelection::SetMaterialSlots(const SlotsArray& slots)
{
if (slots.empty())
@@ -533,74 +462,45 @@ namespace Physics
m_materialIdsAssignedToSlots[slotIndex] = materialId;
}
- AZ::Data::Asset MaterialSelection::LoadAsset() const
- {
- AZ::Data::Asset asset = AZ::Data::AssetManager::Instance()
- .GetAsset(GetMaterialLibraryAssetId(), AZ::Data::AssetLoadBehavior::Default);
-
- asset.BlockUntilLoadComplete();
-
- return asset;
- }
-
void MaterialSelection::SyncSelectionToMaterialLibrary()
{
- if (GetMaterialLibraryAssetId().IsValid())
+ auto* materialLibrary = GetMaterialLibrary().Get();
+ if (!materialLibrary)
{
- auto materialLibraryAsset = AZ::Data::AssetManager::Instance().GetAsset(GetMaterialLibraryAssetId(), AZ::Data::AssetLoadBehavior::Default);
+ return;
+ }
- materialLibraryAsset.BlockUntilLoadComplete();
-
- // We try to check whether existing selection matches any materials in the newly assigned library and do one of the following:
- // 1. If previous MaterialId is invalid for this material library, and it is not the Default material, we set it to the Default material from the library.
- // 2. If it's valid, or it is the Default material, we don't change it (useful when user accidentally re-assigns the same library: previous selection won't go away).
-
- if (materialLibraryAsset.Get())
+ for (Physics::MaterialId& materialId : m_materialIdsAssignedToSlots)
+ {
+ // Leave nulls (default) unchanged.
+ if (materialId.IsNull())
{
- for (Physics::MaterialId& materialId : m_materialIdsAssignedToSlots)
- {
- if (!materialLibraryAsset.Get()->HasDataForMaterialId(materialId)
- && !materialId.IsNull()) // Null materialId is the Default material.
- {
- materialId = MaterialId();
- }
- }
+ continue;
}
- else
+
+ // If the material id is not present in the library anymore, set it to default
+ if (!materialLibrary->HasDataForMaterialId(materialId))
{
- AZ_Warning("PhysX", false, "MaterialSelection: invalid material library");
+ materialId = MaterialId();
}
}
}
- const AZ::Data::Asset& MaterialSelection::GetMaterialLibraryAsset() const
- {
- if (IsDefaultMaterialLibraryAsset())
- {
- const AZ::Data::Asset& defaultMaterialLibrary = GetDefaultMaterialLibrary();
- return defaultMaterialLibrary;
- }
-
- return m_materialLibrary;
- }
-
- bool MaterialSelection::IsDefaultMaterialLibraryAsset() const
- {
- return !m_materialLibrary.GetId().IsValid();
- }
-
- const AZ::Data::Asset& MaterialSelection::GetDefaultMaterialLibrary()
+ const AZ::Data::Asset& MaterialSelection::GetMaterialLibrary()
{
if (auto* physicsSystem = AZ::Interface::Get())
{
- return physicsSystem->GetDefaultMaterialLibrary();
+ if (const auto* physicsConfiguration = physicsSystem->GetConfiguration())
+ {
+ return physicsConfiguration->m_materialLibraryAsset;
+ }
}
return s_invalidMaterialLibrary;
}
- const AZ::Data::AssetId& MaterialSelection::GetDefaultMaterialLibraryId()
+ const AZ::Data::AssetId& MaterialSelection::GetMaterialLibraryId()
{
- return GetDefaultMaterialLibrary().GetId();
+ return GetMaterialLibrary().GetId();
}
bool MaterialSelection::AreMaterialSlotsReadOnly() const
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Material.h b/Code/Framework/AzFramework/AzFramework/Physics/Material.h
index e9eaae929f..69edf3ed25 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/Material.h
+++ b/Code/Framework/AzFramework/AzFramework/Physics/Material.h
@@ -29,7 +29,6 @@ namespace Physics
/// =========================
/// This is the interface to the wrapper around native material type (such as PxMaterial in PhysX gem)
/// that stores extra metadata, like Surface Type name.
- /// To see more details about PhysX implementation please refer to PhysX::Material class
///
/// Usage example
/// -------------------------
@@ -37,14 +36,7 @@ namespace Physics
///
/// Physics::MaterialConfiguration materialProperties;
/// AZStd::shared_ptr newMaterial = AZ::Interface::Get()->CreateMaterial(materialProperties);
- ///
- /// To get PxMaterial use GetNativePointer function
- ///
- /// physx::PxMaterial* material = static_cast(newMaterial->GetNativePointer());
- ///
- /// You can use retrieved PxMaterial pointer on its own, provided you increment its reference count.
- /// If this class goes out of scope, the PxMaterial pointer will be valid, but its userData
- /// will be cleaned up to point to nullptr.
+ ///
class Material
{
public:
@@ -63,9 +55,9 @@ namespace Physics
/// Returns AZ::Crc32 of the surface name.
virtual AZ::Crc32 GetSurfaceType() const = 0;
- virtual void SetSurfaceType(AZ::Crc32 surfaceType) = 0;
virtual const AZStd::string& GetSurfaceTypeName() const = 0;
+ virtual void SetSurfaceTypeName(const AZStd::string& surfaceTypeName) = 0;
virtual float GetDynamicFriction() const = 0;
virtual void SetDynamicFriction(float dynamicFriction) = 0;
@@ -85,6 +77,9 @@ namespace Physics
virtual float GetDensity() const = 0;
virtual void SetDensity(float density) = 0;
+ virtual AZ::Color GetDebugColor() const = 0;
+ virtual void SetDebugColor(const AZ::Color& debugColor) = 0;
+
/// If the name of this material matches the name of one of the CrySurface types, it will return its CrySurface Id.\n
/// If there's no match it will return default CrySurface Id.\n
/// CrySurface types are defined in libs/materialeffects/surfacetypes.xml
@@ -122,6 +117,10 @@ namespace Physics
Material::CombineMode m_frictionCombine = Material::CombineMode::Average;
AZ::Color m_debugColor = AZ::Colors::White;
+
+ bool operator==(const MaterialConfiguration& other) const;
+ bool operator!=(const MaterialConfiguration& other) const;
+
private:
static bool VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
static AZ::Color GenerateDebugColor(const char* materialName);
@@ -147,6 +146,7 @@ namespace Physics
static MaterialId FromUUID(const AZ::Uuid& uuid);
bool IsNull() const { return m_id.IsNull(); }
bool operator==(const MaterialId& other) const { return m_id == other.m_id; }
+ bool operator!=(const MaterialId& other) const { return !(*this == other); }
const AZ::Uuid& GetUuid() const { return m_id; }
private:
@@ -166,6 +166,9 @@ namespace Physics
MaterialConfiguration m_configuration;
MaterialId m_id;
+
+ bool operator==(const MaterialFromAssetConfiguration& other) const;
+ bool operator!=(const MaterialFromAssetConfiguration& other) const;
};
/// An asset that holds a list of materials to be edited and assigned in Open 3D Engine Editor
@@ -222,40 +225,27 @@ namespace Physics
AZStd::vector m_materialLibrary;
};
- /// The class is used to expose a MaterialLibraryAsset to Edit Context
+ /// The class is used to expose a default material and material library asset to Edit Context
/// =======================================================================
///
/// Since AZ::Data::Asset doesn't reflect the data to EditContext
/// we have to have a wrapper doing it.
- class MaterialLibraryAssetReflectionWrapper
+ class MaterialInfoReflectionWrapper
{
public:
- AZ_CLASS_ALLOCATOR(MaterialLibraryAssetReflectionWrapper, AZ::SystemAllocator, 0);
- AZ_TYPE_INFO(Physics::MaterialLibraryAssetReflectionWrapper, "{3D2EF5DF-EFD0-47EB-B88F-3E6FE1FEE5B0}");
+ AZ_CLASS_ALLOCATOR(MaterialInfoReflectionWrapper, AZ::SystemAllocator, 0);
+ AZ_TYPE_INFO(Physics::MaterialInfoReflectionWrapper, "{02AB8CBC-D35B-4E0F-89BA-A96D94DAD4F9}");
static void Reflect(AZ::ReflectContext* context);
- AZ::Data::Asset m_asset =
+ Physics::MaterialConfiguration m_defaultMaterialConfiguration;
+ AZ::Data::Asset m_materialLibraryAsset =
AZ::Data::AssetLoadBehavior::NoLoad;
};
- /// Customized material library for use as default material library
- class DefaultMaterialLibraryAssetReflectionWrapper : public Physics::MaterialLibraryAssetReflectionWrapper
- {
- public:
- AZ_CLASS_ALLOCATOR(MaterialLibraryAssetReflectionWrapper, AZ::SystemAllocator, 0);
- AZ_TYPE_INFO(Physics::DefaultMaterialLibraryAssetReflectionWrapper, "{02AB8CBC-D35B-4E0F-89BA-A96D94DAD4F9}");
- static void Reflect(AZ::ReflectContext* context);
-
- AZ::Data::Asset m_asset =
- AZ::Data::AssetLoadBehavior::NoLoad;
- };
-
- /// The class is used to store a MaterialLibraryAsset and a vector of MaterialIds selected from the library
+ /// The class is used to store a vector of MaterialIds selected from the library
/// =======================================================================
///
- /// This class is used to store a reference to the library asset and user's
- /// selection of the materials from this library.\n
- /// It also reflects UI controls for assigning MaterialLibraryAsset and selecting a material from it.
+ /// This class is used to store the user's selection of the materials from this library.
/// You can reflect this class in EditorContext to provide UI for selecting materials
/// on any custom component or QWidget.
class MaterialSelection
@@ -269,27 +259,6 @@ namespace Physics
static void Reflect(AZ::ReflectContext* context);
- /// Returns whether MaterialLibraryAsset assigned to this selection exists and valid. Attempts to load
- /// the library if it's not loaded yet.
- /// @return true if MaterialLibraryAsset has a valid AssetId, loaded and isn't empty
- bool IsMaterialLibraryValid() const;
-
- /// Looks up MaterialLibraryAsset for MaterialFromAssetConfiguration with MaterialId that is stored intrenally.
- /// @param configuration contains material data if there is a material selected by user
- /// and if it exists in the MaterialLibraryAsset
- /// @param materialId MaterialId to retrieve MaterialFromAssetConfiguration for
- /// @return true if lookup was successful.
- bool GetMaterialConfiguration(Physics::MaterialFromAssetConfiguration& configuration, const Physics::MaterialId& materialId) const;
-
- /// Sets and loads MaterialLibraryAsset with specified AssetId.
- /// It is used to construct MaterialSelection at runtime.
- /// It is not a typical use case and mostly needed to convert legacy entities and auto-generate material libraries
- /// @param assetId AssetId to create MaterialLibraryAsset with
- void SetMaterialLibrary(const AZ::Data::AssetId& assetId);
-
- /// Sets the material library to none, this will cause to use the project-wide default material library
- void ResetToDefaultMaterialLibrary();
-
/// Sets an array of material slots to pick MaterialIds for. Having multiple slots is required for assigning multiple materials on a mesh
/// or heightfield object. SlotsArray can be empty and in this case Default slot will be created.
/// @param slots Array of names for slots. Can be empty, in this case Default slot will be created
@@ -298,48 +267,34 @@ namespace Physics
/// Returns a list of MaterialId that were assigned for each corresponding slot.
const AZStd::vector& GetMaterialIdsAssignedToSlots() const;
- /// Sets the MaterialId from MaterialLibraryAsset as the selected material at a specific slotIndex.
- /// @param materialId MaterialId that user selected from the MaterialLibraryAsset
- /// @param slotIndex index of the slot to set MaterialId for
+ /// Sets the MaterialId as the selected material at a specific slotIndex.
+ /// @param materialId MaterialId that user selected
+ /// @param slotIndex Index of the slot to set the MaterialId
void SetMaterialId(const Physics::MaterialId& materialId, int slotIndex = 0);
- /// Returns the material library asset id.
- AZ::Data::AssetId GetMaterialLibraryAssetId() const;
-
/// Returns the material id assigned to this selection at a specific slotIndex.
- /// @param slotIndex index of the slot to retrieve MaterialId for
+ /// @param slotIndex Index of the slot to retrieve the MaterialId
Physics::MaterialId GetMaterialId(int slotIndex = 0) const;
- /// Returns the material library asset.
- const Physics::MaterialLibraryAsset* GetMaterialLibraryAssetData() const;
-
- /// Returns the material library asset hint(UI display string)
- const AZStd::string& GetMaterialLibraryAssetHint() const;
-
/// Called when the material library has changed
- void OnDefaultMaterialLibraryChanged(const AZ::Data::AssetId& defaultMaterialLibraryId);
+ void OnMaterialLibraryChanged(const AZ::Data::AssetId& defaultMaterialLibraryId);
/// Set if the material slots are editable in the edit context
void SetSlotsReadOnly(bool readOnly);
private:
- AZ::Data::Asset m_materialLibrary { AZ::Data::AssetLoadBehavior::NoLoad };
AZStd::vector m_materialIdsAssignedToSlots;
SlotsArray m_materialSlots;
bool m_slotsReadOnly = false;
- const AZ::Data::Asset& GetMaterialLibraryAsset() const;
- AZ::Data::Asset LoadAsset() const;
- bool IsDefaultMaterialLibraryAsset() const;
void SyncSelectionToMaterialLibrary();
- static const AZ::Data::Asset& GetDefaultMaterialLibrary();
- static const AZ::Data::AssetId& GetDefaultMaterialLibraryId();
+ static const AZ::Data::Asset& GetMaterialLibrary();
+ static const AZ::Data::AssetId& GetMaterialLibraryId();
bool AreMaterialSlotsReadOnly() const;
// EditorContext callbacks
- AZ::u32 OnMaterialLibraryChanged();
AZStd::string GetMaterialSlotLabel(int index);
};
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/MaterialBus.h b/Code/Framework/AzFramework/AzFramework/Physics/MaterialBus.h
index edfa3096d3..a7e4869df1 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/MaterialBus.h
+++ b/Code/Framework/AzFramework/AzFramework/Physics/MaterialBus.h
@@ -25,21 +25,26 @@ namespace Physics
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; // Implemented by sole owner of materials, e.g. class MaterialManager in PhysX gem.
- /// Get default material
+ /// Get default material.
virtual AZStd::shared_ptr GetGenericDefaultMaterial() = 0;
/// Returns weak pointers to physics materials.
/// Connect to PhysicsMaterialNotifications::MaterialsReleased to be informed when material pointers are deleted by owner.
virtual void GetMaterials(const MaterialSelection& materialSelection
- , AZStd::vector>& outMaterials) = 0;
+ , AZStd::vector>& outMaterials) = 0;
+
+ /// Returns a weak pointer to physics material with the given id.
+ virtual AZStd::shared_ptr GetMaterialById(Physics::MaterialId id) = 0;
/// Returns a weak pointer to physics material with the given name.
- virtual AZStd::weak_ptr GetMaterialByName(const AZStd::string& name) = 0;
+ virtual AZStd::shared_ptr GetMaterialByName(const AZStd::string& name) = 0;
- /// Returns index of the first selected material in MaterialSelection's material library.
- /// A MaterialSelection can contain multiple material selections.
- /// Returned index is 0-based where 0 is the Default material, and materials from the material library are 1 and onwards.
- virtual AZ::u32 GetFirstSelectedMaterialIndex(const MaterialSelection& materialSelection) = 0;
+ /// Updates the material selection from the physics asset or sets it to default if there's no asset provided.
+ /// @param shapeConfiguration The shape information that contains the physics asset.
+ /// @param materialSelection The material selection to update.
+ virtual void UpdateMaterialSelectionFromPhysicsAsset(
+ const ShapeConfiguration& shapeConfiguration,
+ MaterialSelection& materialSelection) = 0;
};
using PhysicsMaterialRequestBus = AZ::EBus;
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/PhysicsSystem.h b/Code/Framework/AzFramework/AzFramework/Physics/PhysicsSystem.h
index e3ed449046..36ae4dbecb 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/PhysicsSystem.h
+++ b/Code/Framework/AzFramework/AzFramework/Physics/PhysicsSystem.h
@@ -130,13 +130,6 @@ namespace AzPhysics
//! @param forceReinitialization Flag to force a reinitialization of the physics system. Default false.
virtual void UpdateConfiguration(const SystemConfiguration* newConfig, bool forceReinitialization = false) = 0;
- //! Update the default material library.
- //! @param materialLibrary The new material library asset to use.
- virtual void UpdateDefaultMaterialLibrary(const AZ::Data::Asset& materialLibrary) = 0;
-
- //! Accessor to get the current Material Library. This is also available in the PhysXSystemConfiguration.
- virtual const AZ::Data::Asset& GetDefaultMaterialLibrary() const = 0;
-
//! Update the current default scene configuration.
//! This is the configuration used to to create scenes without a custom configuration.
//! @param sceneConfiguration The new configuration to apply.
@@ -169,9 +162,12 @@ namespace AzPhysics
//! Register to receive notifications when the SystemConfiguration changes.
//! @param handler The handler to receive the event.
void RegisterSystemConfigurationChangedEvent(SystemEvents::OnConfigurationChangedEvent::Handler& handler) { handler.Connect(m_configChangeEvent); }
- //! Register a handler to receive an event when the default material library changes.
+ //! Register a handler to receive an event when the material library changes.
//! @param handler The handler to receive the event.
- void RegisterOnDefaultMaterialLibraryChangedEventHandler(SystemEvents::OnDefaultMaterialLibraryChangedEvent::Handler& handler) { handler.Connect(m_onDefaultMaterialLibraryChangedEvent); }
+ void RegisterOnMaterialLibraryChangedEventHandler(SystemEvents::OnMaterialLibraryChangedEvent::Handler& handler) { handler.Connect(m_onMaterialLibraryChangedEvent); }
+ //! Register a handler to receive an event when the material library fails to load on startup.
+ //! @param handler The handler to receive the event.
+ void RegisterOnMaterialLibraryLoadErrorEventHandler(SystemEvents::OnMaterialLibraryLoadErrorEvent::Handler& handler) { handler.Connect(m_onMaterialLibraryLoadErrorEvent); }
//! Register a handler to receive an event when the default SceneConfiguration changes.
//! @param handler The handler to receive the event.
void RegisterOnDefaultSceneConfigurationChangedEventHandler(SystemEvents::OnDefaultSceneConfigurationChangedEvent::Handler& handler) { handler.Connect(m_onDefaultSceneConfigurationChangedEvent); }
@@ -185,7 +181,8 @@ namespace AzPhysics
SystemEvents::OnSceneAddedEvent m_sceneAddedEvent;
SystemEvents::OnSceneRemovedEvent m_sceneRemovedEvent;
SystemEvents::OnConfigurationChangedEvent m_configChangeEvent;
- SystemEvents::OnDefaultMaterialLibraryChangedEvent m_onDefaultMaterialLibraryChangedEvent;
+ SystemEvents::OnMaterialLibraryChangedEvent m_onMaterialLibraryChangedEvent;
+ SystemEvents::OnMaterialLibraryLoadErrorEvent m_onMaterialLibraryLoadErrorEvent;
SystemEvents::OnDefaultSceneConfigurationChangedEvent m_onDefaultSceneConfigurationChangedEvent;
};
} // namespace AzPhysics
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp
index a535f5f65d..275103bc28 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp
@@ -17,6 +17,21 @@
namespace Physics
{
+ namespace Internal
+ {
+ bool ShapeConfigurationVersionConverter(
+ [[maybe_unused]] AZ::SerializeContext& context,
+ AZ::SerializeContext::DataElementNode& classElement)
+ {
+ if (classElement.GetVersion() <= 1)
+ {
+ classElement.RemoveElementByName(AZ_CRC_CE("UseMaterialsFromAsset"));
+ }
+
+ return true;
+ }
+ }
+
void ShapeConfiguration::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast(context))
@@ -166,10 +181,9 @@ namespace Physics
->RegisterGenericType>();
serializeContext->Class()
- ->Version(1)
+ ->Version(2, &Internal::ShapeConfigurationVersionConverter)
->Field("PhysicsAsset", &PhysicsAssetShapeConfiguration::m_asset)
->Field("AssetScale", &PhysicsAssetShapeConfiguration::m_assetScale)
- ->Field("UseMaterialsFromAsset", &PhysicsAssetShapeConfiguration::m_useMaterialsFromAsset)
->Field("SubdivisionLevel", &PhysicsAssetShapeConfiguration::m_subdivisionLevel)
;
@@ -182,7 +196,6 @@ namespace Physics
->DataElement(AZ::Edit::UIHandlers::Default, &PhysicsAssetShapeConfiguration::m_assetScale, "Asset Scale", "The scale of the asset shape")
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Step, 0.01f)
- ->DataElement(AZ::Edit::UIHandlers::Default, &PhysicsAssetShapeConfiguration::m_useMaterialsFromAsset, "Physics Materials from Mesh", "Auto-set physics materials using Mesh's material surfaces names")
;
}
}
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h
index b3d04a10c9..8234ef9173 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h
+++ b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h
@@ -140,7 +140,7 @@ namespace Physics
AZ::Data::Asset m_asset{ AZ::Data::AssetLoadBehavior::PreLoad };
AZ::Vector3 m_assetScale = AZ::Vector3::CreateOne();
- bool m_useMaterialsFromAsset = true;
+ bool m_useMaterialsFromAsset = false; // Not reflected or exposed to the user until there is a way to auto-match mesh's materials with physics materials
AZ::u8 m_subdivisionLevel = 4; ///< The level of subdivision if a primitive shape is replaced with a convex mesh due to scaling.
};
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h b/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h
index f198551148..8cdd0e0cf0 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h
+++ b/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h
@@ -142,24 +142,12 @@ namespace Physics
virtual AZStd::shared_ptr CreateShape(const ColliderConfiguration& colliderConfiguration, const ShapeConfiguration& configuration) = 0;
+ virtual AZStd::shared_ptr CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) = 0;
+
/// Releases the mesh object created by the physics backend.
/// @param nativeMeshObject Pointer to the mesh object.
virtual void ReleaseNativeMeshObject(void* nativeMeshObject) = 0;
- //////////////////////////////////////////////////////////////////////////
- //// Physics Materials
-
- virtual AZStd::shared_ptr CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) = 0;
- virtual AZStd::shared_ptr GetDefaultMaterial() = 0;
- virtual AZStd::vector> CreateMaterialsFromLibrary(const Physics::MaterialSelection& materialSelection) = 0;
-
-
- /// Updates the collider material selection from the physics asset or sets it to default if there's no asset provided.
- /// @param shapeConfiguration The shape information
- /// @param colliderConfiguration The collider information
- virtual bool UpdateMaterialSelection(const Physics::ShapeConfiguration& shapeConfiguration,
- Physics::ColliderConfiguration& colliderConfiguration) = 0;
-
//////////////////////////////////////////////////////////////////////////
//// Joints
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Utils.cpp b/Code/Framework/AzFramework/AzFramework/Physics/Utils.cpp
index b5f113582b..2c3b62bb88 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/Utils.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Physics/Utils.cpp
@@ -119,8 +119,7 @@ namespace Physics
AzPhysics::SceneConfiguration::Reflect(context);
MaterialConfiguration::Reflect(context);
MaterialLibraryAsset::Reflect(context);
- MaterialLibraryAssetReflectionWrapper::Reflect(context);
- DefaultMaterialLibraryAssetReflectionWrapper::Reflect(context);
+ MaterialInfoReflectionWrapper::Reflect(context);
JointLimitConfiguration::Reflect(context);
AzPhysics::SimulatedBodyConfiguration::Reflect(context);
AzPhysics::RigidBodyConfiguration::Reflect(context);
diff --git a/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h b/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h
index ba1d2d1e06..749f457286 100644
--- a/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h
+++ b/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h
@@ -12,6 +12,7 @@
#pragma once
#include
+#include
#include
namespace AzFramework
@@ -35,12 +36,12 @@ namespace AzFramework
AzFramework::EntityContextId m_contextId;
};
- //! Interface for intersection requests, implement this interface for making your component
- //! render geometry intersectable.
+ //! Interface for intersection requests.
+ //! Implement this interface to make your component 'intersectable'.
class IntersectionRequests
: public AZ::EBusTraits
{
- //! Policy for notifying the Intersector bus of entities connected/disconnected to this ebus
+ //! Policy for notifying the Intersector bus of entities connected/disconnected to this EBus
//! so it updates the internal data of the entities
template
struct IntersectionRequestsConnectionPolicy
diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.cpp
index b3ba1568bd..da046ff172 100644
--- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.cpp
@@ -10,6 +10,7 @@
*
*/
+#include
#include
#include
#include
@@ -88,4 +89,10 @@ namespace AzFramework
{
extensions.push_back(Spawnable::FileExtension);
}
+
+ uint32_t SpawnableAssetHandler::BuildSubId(AZStd::string_view id)
+ {
+ AZ::Uuid subIdHash = AZ::Uuid::CreateData(id.data(), id.size());
+ return azlossy_caster(subIdHash.GetHash());
+ }
} // namespace AzFramework
diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.h
index deef314955..78268bf71a 100644
--- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.h
+++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableAssetHandler.h
@@ -47,6 +47,7 @@ namespace AzFramework
const char* GetGroup() const override;
const char* GetBrowserIcon() const override;
void GetAssetTypeExtensions(AZStd::vector& extensions) override;
+ static uint32_t BuildSubId(AZStd::string_view id);
protected:
LoadResult LoadAssetData(
diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp
index e4833ccb3c..559f7ce460 100644
--- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp
@@ -29,7 +29,7 @@ namespace AzFramework
AZ_CVAR(float, ed_cameraSystemOrbitDollyScrollSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemOrbitDollyCursorSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemScrollTranslateSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
- AZ_CVAR(float, ed_cameraSystemMinOrbitDistance, 6.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
+ AZ_CVAR(float, ed_cameraSystemMinOrbitDistance, 10.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemMaxOrbitDistance, 50.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemLookSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemTranslateSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
@@ -37,7 +37,6 @@ namespace AzFramework
AZ_CVAR(float, ed_cameraSystemPanSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(bool, ed_cameraSystemPanInvertX, true, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(bool, ed_cameraSystemPanInvertY, true, nullptr, AZ::ConsoleFunctorFlags::Null, "");
- AZ_CVAR(float, ed_cameraSystemLookDeadzone, 2.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(
AZ::CVarFixedString, ed_cameraSystemTranslateForwardKey, "keyboard_key_alphanumeric_W", nullptr, AZ::ConsoleFunctorFlags::Null, "");
@@ -144,7 +143,7 @@ namespace AzFramework
z = AZStd::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1));
}
- return {x, y, z};
+ return { x, y, z };
}
void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform)
@@ -179,7 +178,7 @@ namespace AzFramework
{
const auto nextCamera = m_cameras.StepCamera(targetCamera, m_motionDelta, m_scrollDelta, deltaTime);
- m_motionDelta = ScreenVector{0, 0};
+ m_motionDelta = ScreenVector{ 0, 0 };
m_scrollDelta = 0.0f;
return nextCamera;
@@ -213,7 +212,10 @@ namespace AzFramework
auto& cameraInput = m_idleCameraInputs[i];
const bool canBegin = cameraInput->Beginning() &&
AZStd::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(),
- [](const auto& input) { return !input->Exclusive(); }) &&
+ [](const auto& input)
+ {
+ return !input->Exclusive();
+ }) &&
(!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty()));
if (canBegin)
@@ -231,7 +233,8 @@ namespace AzFramework
const Camera nextCamera = AZStd::accumulate(
AZStd::begin(m_activeCameraInputs), AZStd::end(m_activeCameraInputs), targetCamera,
- [cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera) {
+ [cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera)
+ {
acc = camera->StepCamera(acc, cursorDelta, scrollDelta, deltaTime);
return acc;
});
@@ -284,7 +287,8 @@ namespace AzFramework
bool RotateCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
{
- const ClickDetector::ClickEvent clickEvent = [&event, this] {
+ const ClickDetector::ClickEvent clickEvent = [&event, this]
+ {
if (const auto& input = AZStd::get_if(&event))
{
if (input->m_channelId == m_rotateChannelId)
@@ -330,7 +334,10 @@ namespace AzFramework
nextCamera.m_pitch -= float(cursorDelta.m_y) * ed_cameraSystemRotateSpeed;
nextCamera.m_yaw -= float(cursorDelta.m_x) * ed_cameraSystemRotateSpeed;
- const auto clampRotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
+ const auto clampRotation = [](const float angle)
+ {
+ return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi);
+ };
nextCamera.m_yaw = clampRotation(nextCamera.m_yaw);
// clamp pitch to be +-90 degrees
@@ -377,9 +384,10 @@ namespace AzFramework
const auto deltaPanX = float(cursorDelta.m_x) * panAxes.m_horizontalAxis * ed_cameraSystemPanSpeed;
const auto deltaPanY = float(cursorDelta.m_y) * panAxes.m_verticalAxis * ed_cameraSystemPanSpeed;
- const auto inv = [](const bool invert) {
- constexpr float Dir[] = {1.0f, -1.0f};
- return Dir[static_cast(invert)];
+ const auto inv = [](const bool invert)
+ {
+ constexpr float Dir[] = { 1.0f, -1.0f };
+ return Dir[aznumeric_cast(invert)];
};
nextCamera.m_lookAt += deltaPanX * inv(ed_cameraSystemPanInvertX);
@@ -475,7 +483,8 @@ namespace AzFramework
const auto axisY = translationBasis.GetBasisY();
const auto axisZ = translationBasis.GetBasisZ();
- const float speed = [boost = m_boost]() {
+ const float speed = [boost = m_boost]()
+ {
return ed_cameraSystemTranslateSpeed * (boost ? ed_cameraSystemBoostMultiplier : 1.0f);
}();
@@ -555,10 +564,12 @@ namespace AzFramework
if (Beginning())
{
- const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn] {
+ const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn]
+ {
if (lookAtFn)
{
- if (const auto lookAt = lookAtFn())
+ // pass through the camera's position and look vector for use in the lookAt function
+ if (const auto lookAt = lookAtFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY()))
{
auto transform = AZ::Transform::CreateLookAt(targetCamera.m_lookAt, *lookAt);
nextCamera.m_lookDist = -lookAt->GetDistance(targetCamera.m_lookAt);
@@ -692,14 +703,20 @@ namespace AzFramework
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const float deltaTime)
{
- const auto clamp_rotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
+ const auto clamp_rotation = [](const float angle)
+ {
+ return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi);
+ };
// keep yaw in 0 - 360 range
float targetYaw = clamp_rotation(targetCamera.m_yaw);
const float currentYaw = clamp_rotation(currentCamera.m_yaw);
// return the sign of the float input (-1, 0, 1)
- const auto sign = [](const float value) { return aznumeric_cast((0.0f < value) - (value < 0.0f)); };
+ const auto sign = [](const float value)
+ {
+ return aznumeric_cast((0.0f < value) - (value < 0.0f));
+ };
// ensure smooth transition when moving across 0 - 360 boundary
const float yawDelta = targetYaw - currentYaw;
@@ -727,26 +744,28 @@ namespace AzFramework
const auto& inputChannelId = inputChannel.GetInputChannelId();
const auto& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId();
- const bool wasMouseButton =
- AZStd::any_of(InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(), [inputChannelId](const auto& button) {
+ const bool wasMouseButton = AZStd::any_of(
+ InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(),
+ [inputChannelId](const auto& button)
+ {
return button == inputChannelId;
});
if (inputChannelId == InputDeviceMouse::Movement::X)
{
- return HorizontalMotionEvent{(int)inputChannel.GetValue()};
+ return HorizontalMotionEvent{ aznumeric_cast(inputChannel.GetValue()) };
}
else if (inputChannelId == InputDeviceMouse::Movement::Y)
{
- return VerticalMotionEvent{(int)inputChannel.GetValue()};
+ return VerticalMotionEvent{ aznumeric_cast(inputChannel.GetValue()) };
}
else if (inputChannelId == InputDeviceMouse::Movement::Z)
{
- return ScrollEvent{inputChannel.GetValue()};
+ return ScrollEvent{ inputChannel.GetValue() };
}
else if (wasMouseButton || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId))
{
- return DiscreteInputEvent{inputChannelId, inputChannel.GetState()};
+ return DiscreteInputEvent{ inputChannelId, inputChannel.GetState() };
}
return AZStd::monostate{};
diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h
index ec70fc00de..a02f796899 100644
--- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h
+++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h
@@ -34,9 +34,9 @@ namespace AzFramework
AZ::Vector3 m_lookAt = AZ::Vector3::CreateZero(); //!< Position of camera when m_lookDist is zero,
//!< or position of m_lookAt when m_lookDist is greater
//!< than zero.
- float m_yaw{0.0};
- float m_pitch{0.0};
- float m_lookDist{0.0}; //!< Zero gives first person free look, otherwise orbit about m_lookAt
+ float m_yaw{ 0.0 };
+ float m_pitch{ 0.0 };
+ float m_lookDist{ 0.0 }; //!< Zero gives first person free look, otherwise orbit about m_lookAt
//! View camera transform (v in MVP).
AZ::Transform View() const;
@@ -195,7 +195,11 @@ namespace AzFramework
inline bool Cameras::Exclusive() const
{
return AZStd::any_of(
- m_activeCameraInputs.begin(), m_activeCameraInputs.end(), [](const auto& cameraInput) { return cameraInput->Exclusive(); });
+ m_activeCameraInputs.begin(), m_activeCameraInputs.end(),
+ [](const auto& cameraInput)
+ {
+ return cameraInput->Exclusive();
+ });
}
//! Responsible for updating a series of cameras given various inputs.
@@ -209,7 +213,7 @@ namespace AzFramework
private:
ScreenVector m_motionDelta; //!< The delta used for look/orbit/pan (rotation + translation) - two dimensional.
- float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional.
+ float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional.
};
class RotateCameraInput : public CameraInput
@@ -237,7 +241,7 @@ namespace AzFramework
inline PanAxes LookPan(const Camera& camera)
{
const AZ::Matrix3x3 orientation = camera.Rotation();
- return {orientation.GetBasisX(), orientation.GetBasisZ()};
+ return { orientation.GetBasisX(), orientation.GetBasisZ() };
}
inline PanAxes OrbitPan(const Camera& camera)
@@ -245,12 +249,13 @@ namespace AzFramework
const AZ::Matrix3x3 orientation = camera.Rotation();
const auto basisX = orientation.GetBasisX();
- const auto basisY = [&orientation] {
+ const auto basisY = [&orientation]
+ {
const auto forward = orientation.GetBasisY();
return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized();
}();
- return {basisX, basisY};
+ return { basisX, basisY };
}
class PanCameraInput : public CameraInput
@@ -285,7 +290,8 @@ namespace AzFramework
const AZ::Matrix3x3 orientation = camera.Rotation();
const auto basisX = orientation.GetBasisX();
- const auto basisY = [&orientation] {
+ const auto basisY = [&orientation]
+ {
const auto forward = orientation.GetBasisY();
return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized();
}();
@@ -398,7 +404,7 @@ namespace AzFramework
class OrbitCameraInput : public CameraInput
{
public:
- using LookAtFn = AZStd::function()>;
+ using LookAtFn = AZStd::function(const AZ::Vector3& position, const AZ::Vector3& direction)>;
// CameraInput overrides ...
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp
index 1ae3945bd6..d501271f59 100644
--- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp
+++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp
@@ -35,7 +35,8 @@ namespace AzFramework::AssetSystem::Platform
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
{
// Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure.
- assetProcessorPath = AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor";
+ assetProcessorPath =
+ AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_TRAIT_OS_PLATFORM_NAME / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor";
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
{
diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp
index 6f1f860932..890b6b32c3 100644
--- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp
+++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp
@@ -34,7 +34,8 @@ namespace AzFramework::AssetSystem::Platform
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
{
// Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure.
- assetProcessorPath = AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor.app";
+ assetProcessorPath =
+ AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_TRAIT_OS_PLATFORM_NAME / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor.app";
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
{
diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp
index b716778cf4..b0debfd3b0 100644
--- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp
+++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp
@@ -71,7 +71,8 @@ namespace AzFramework::AssetSystem::Platform
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
{
// Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure.
- assetProcessorPath = AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor.exe";
+ assetProcessorPath =
+ AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_TRAIT_OS_PLATFORM_NAME / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor.exe";
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
{
diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h
index 884562d7e8..28971dc779 100644
--- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h
+++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h
@@ -41,6 +41,7 @@ namespace AzManipulatorTestFramework
AZStd::optional ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) override;
AZStd::optional ViewportScreenToWorldRay(
const AzFramework::ScreenPoint& screenPosition) override;
+ float DeviceScalingFactor() override;
private:
// ViewportInteractionRequestBus ...
bool GridSnappingEnabled();
diff --git a/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp b/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp
index ebef9dea30..7d32187a74 100644
--- a/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp
+++ b/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp
@@ -127,4 +127,9 @@ namespace AzManipulatorTestFramework
{
return {};
}
-} // namespace AzManipulatorTestFramework
+
+ float ViewportInteraction::DeviceScalingFactor()
+ {
+ return 1.0f;
+ }
+}// namespace AzManipulatorTestFramework
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Menu.qss b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Menu.qss
index af9c675f23..7f48637cc8 100644
--- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Menu.qss
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Menu.qss
@@ -49,7 +49,7 @@ QMenu::right-arrow
QMenu::icon
{
- right: 8px;
+ right: 20px;
}
QMenu::indicator:checked
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/link.svg b/Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/link.svg
new file mode 100644
index 0000000000..dfd21d157f
--- /dev/null
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/link.svg
@@ -0,0 +1,4 @@
+
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc b/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc
index dbbf0e78e2..7b0c6530ab 100644
--- a/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc
@@ -13,5 +13,6 @@
Notifications/checkmark.svg
Notifications/download.svg
+ Notifications/link.svg
diff --git a/Code/Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h b/Code/Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h
index 0090ce066b..855b4fe416 100644
--- a/Code/Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h
+++ b/Code/Framework/AzTest/AzTest/Platform/Linux/AzTest_Traits_Linux.h
@@ -39,4 +39,3 @@
#define AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_EDITOR_TESTS true
#define AZ_TRAIT_DISABLE_FAILED_METRICS_TESTS true
-#define AZ_TRAIT_DISABLE_ASSET_JOB_PARALLEL_TESTS true
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp
index 706d8243e2..a59b29ddf8 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp
@@ -483,6 +483,8 @@ namespace AzToolsFramework
}
}
+ m_dirty = false;
+
AddRecentPath(targetFilePath);
SetStatusText(Status::assetCreated);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp
index 439789f11b..7fd11ff9bf 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp
@@ -57,7 +57,6 @@ namespace AzToolsFramework
"Couldn't get prefab loader interface, it's a requirement for PrefabEntityOwnership system to work");
m_rootInstance = AZStd::unique_ptr(m_prefabSystemComponent->CreatePrefab({}, {}, "NewLevel.prefab"));
-
m_sliceOwnershipService.BusConnect(m_entityContextId);
m_sliceOwnershipService.m_shouldAssertForLegacySlicesUsage = m_shouldAssertForLegacySlicesUsage;
m_editorSliceOwnershipService.BusConnect();
@@ -91,14 +90,17 @@ namespace AzToolsFramework
void PrefabEditorEntityOwnershipService::Reset()
{
- Prefab::TemplateId templateId = m_rootInstance->GetTemplateId();
- if (templateId != Prefab::InvalidTemplateId)
+ if (m_rootInstance)
{
- m_rootInstance->SetTemplateId(Prefab::InvalidTemplateId);
- m_prefabSystemComponent->RemoveTemplate(templateId);
+ Prefab::TemplateId templateId = m_rootInstance->GetTemplateId();
+ if (templateId != Prefab::InvalidTemplateId)
+ {
+ m_rootInstance->SetTemplateId(Prefab::InvalidTemplateId);
+ m_prefabSystemComponent->RemoveTemplate(templateId);
+ }
+ m_rootInstance->Reset();
+ m_rootInstance->SetContainerEntityName("Level");
}
- m_rootInstance->Reset();
- m_rootInstance->SetContainerEntityName("Level");
AzFramework::EntityOwnershipServiceNotificationBus::Event(
m_entityContextId, &AzFramework::EntityOwnershipServiceNotificationBus::Events::OnEntityOwnershipServiceReset);
@@ -202,7 +204,7 @@ namespace AzToolsFramework
}
m_rootInstance->SetTemplateId(templateId);
- m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GetRelativePathToProject(filename));
+ m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GenerateRelativePath(filename));
m_rootInstance->SetContainerEntityName("Level");
m_prefabSystemComponent->PropagateTemplateChanges(templateId);
@@ -220,7 +222,7 @@ namespace AzToolsFramework
bool PrefabEditorEntityOwnershipService::SaveToStream(AZ::IO::GenericStream& stream, AZStd::string_view filename)
{
- AZ::IO::Path relativePath = m_loaderInterface->GetRelativePathToProject(filename);
+ AZ::IO::Path relativePath = m_loaderInterface->GenerateRelativePath(filename);
AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath);
m_rootInstance->SetTemplateSourcePath(relativePath);
@@ -267,7 +269,7 @@ namespace AzToolsFramework
void PrefabEditorEntityOwnershipService::CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename)
{
- AZ::IO::Path relativePath = m_loaderInterface->GetRelativePathToProject(filename);
+ AZ::IO::Path relativePath = m_loaderInterface->GenerateRelativePath(filename);
AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath);
m_rootInstance->SetTemplateSourcePath(relativePath);
@@ -378,7 +380,12 @@ namespace AzToolsFramework
Prefab::InstanceOptionalReference PrefabEditorEntityOwnershipService::GetRootPrefabInstance()
{
AZ_Assert(m_rootInstance, "A valid root prefab instance couldn't be found in PrefabEditorEntityOwnershipService.");
- return *m_rootInstance;
+ if (m_rootInstance)
+ {
+ return *m_rootInstance;
+ }
+
+ return AZStd::nullopt;
}
const AZStd::vector>& PrefabEditorEntityOwnershipService::GetPlayInEditorAssetData()
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSpace.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSpace.cpp
index cd08a95af7..b3f691a62f 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSpace.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/ManipulatorSpace.cpp
@@ -39,7 +39,7 @@ namespace AzToolsFramework
AZ::Transform result;
result.SetRotation(m_space.GetRotation() * localTransform.GetRotation());
result.SetTranslation(m_space.TransformPoint(m_nonUniformScale * localTransform.GetTranslation()));
- result.SetScale(m_space.GetScale() * localTransform.GetUniformScale());
+ result.SetUniformScale(m_space.GetUniformScale() * localTransform.GetUniformScale());
return result;
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp
index 836140eb74..39351df486 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceSerializer.cpp
@@ -124,7 +124,7 @@ namespace AzToolsFramework
"PrefabLoaderInterface could not be found. It is required to load Prefab Instances");
// Make sure we have a relative path
- instance->m_templateSourcePath = loaderInterface->GetRelativePathToProject(instance->m_templateSourcePath);
+ instance->m_templateSourcePath = loaderInterface->GenerateRelativePath(instance->m_templateSourcePath);
TemplateId templateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(instance->GetTemplateSourcePath());
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp
index 2965148172..d7de634c11 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp
@@ -18,7 +18,9 @@
#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -112,7 +114,7 @@ namespace AzToolsFramework
return InvalidTemplateId;
}
- AZ::IO::Path relativePath = GetRelativePathToProject(originPath);
+ AZ::IO::Path relativePath = GenerateRelativePath(originPath);
// Cyclical dependency detected if the prefab file is already part of the progressed
// file path set.
@@ -301,6 +303,45 @@ namespace AzToolsFramework
return true;
}
+ bool PrefabLoader::SaveTemplateToFile(TemplateId templateId, AZ::IO::PathView absolutePath)
+ {
+ AZ_Assert(absolutePath.IsAbsolute(), "SaveTemplateToFile requires an absolute path for saving the initial prefab file.");
+
+ const auto& domAndFilepath = StoreTemplateIntoFileFormat(templateId);
+ if (!domAndFilepath)
+ {
+ return false;
+ }
+
+ // Verify that the absolute path provided to this matches the relative path saved in the template.
+ // Otherwise, the saved prefab won't be able to be loaded.
+ auto relativePath = GenerateRelativePath(absolutePath);
+ if (relativePath != domAndFilepath->second)
+ {
+ AZ_Error(
+ "Prefab", false,
+ "PrefabLoader::SaveTemplateToFile - "
+ "Failed to save template '%s' to location '%.*s'."
+ "Error: Relative path '%.*s' for location didn't match template name.",
+ domAndFilepath->second.c_str(), AZ_STRING_ARG(absolutePath.Native()), AZ_STRING_ARG(relativePath.Native()));
+ return false;
+ }
+
+ auto outcome = AzFramework::FileFunc::WriteJsonFile(domAndFilepath->first, absolutePath);
+ if (!outcome.IsSuccess())
+ {
+ AZ_Error(
+ "Prefab", false,
+ "PrefabLoader::SaveTemplateToFile - "
+ "Failed to save template '%s' to location '%.*s'."
+ "Error: %s",
+ domAndFilepath->second.c_str(), AZ_STRING_ARG(absolutePath.Native()), outcome.GetError().c_str());
+ return false;
+ }
+ m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, false);
+ return true;
+ }
+
bool PrefabLoader::SaveTemplateToString(TemplateId templateId, AZStd::string& output)
{
const auto& domAndFilepath = StoreTemplateIntoFileFormat(templateId);
@@ -385,21 +426,100 @@ namespace AzToolsFramework
AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path).MakePreferred();
if (pathWithOSSeparator.IsAbsolute())
{
+ // If an absolute path was passed in, just return it as-is.
return path;
}
- return AZ::IO::Path(m_projectPathWithOsSeparator).Append(pathWithOSSeparator);
+ // A relative path was passed in, so try to turn it back into an absolute path.
+
+ AZ::IO::Path fullPath;
+
+ bool pathFound = false;
+ AZ::Data::AssetInfo assetInfo;
+ AZStd::string rootFolder;
+ AZStd::string inputPath(path.Native());
+
+ // Given an input path that's expected to exist, try to look it up.
+ AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
+ pathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath,
+ inputPath.c_str(), assetInfo, rootFolder);
+
+ if (pathFound)
+ {
+ // The asset system provided us with a valid root folder and relative path, so return it.
+ fullPath = AZ::IO::Path(rootFolder) / assetInfo.m_relativePath;
+ }
+ else
+ {
+ // If for some reason the Asset system couldn't provide a relative path, provide some fallback logic.
+
+ // Check to see if the AssetProcessor is ready. If it *is* and we didn't get a path, print an error then follow
+ // the fallback logic. If it's *not* ready, we're probably either extremely early in a tool startup flow or inside
+ // a unit test, so just execute the fallback logic without an error.
+ [[maybe_unused]] bool assetProcessorReady = false;
+ AzFramework::AssetSystemRequestBus::BroadcastResult(
+ assetProcessorReady, &AzFramework::AssetSystemRequestBus::Events::AssetProcessorIsReady);
+
+ AZ_Error(
+ "Prefab", !assetProcessorReady, "Full source path for '%.*s' could not be determined. Using fallback logic.",
+ AZ_STRING_ARG(path.Native()));
+
+ // If a relative path was passed in, make it relative to the project root.
+ fullPath = AZ::IO::Path(m_projectPathWithOsSeparator).Append(pathWithOSSeparator);
+ }
+
+ return fullPath;
}
- AZ::IO::Path PrefabLoader::GetRelativePathToProject(AZ::IO::PathView path)
+ AZ::IO::Path PrefabLoader::GenerateRelativePath(AZ::IO::PathView path)
{
- AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path.Native()).MakePreferred();
- if (!pathWithOSSeparator.IsAbsolute())
+ bool pathFound = false;
+
+ AZStd::string relativePath;
+ AZStd::string rootFolder;
+ AZ::IO::Path finalPath;
+
+ // The asset system allows for paths to be relative to multiple root folders, using a priority system.
+ // This request will make the input path relative to the most appropriate, highest-priority root folder.
+ AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
+ pathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GenerateRelativeSourcePath, path.Native(),
+ relativePath, rootFolder);
+
+ if (pathFound && !relativePath.empty())
{
- return path;
+ // A relative path was generated successfully, so return it.
+ finalPath = relativePath;
+ }
+ else
+ {
+ // If for some reason the Asset system couldn't provide a relative path, provide some fallback logic.
+
+ // Check to see if the AssetProcessor is ready. If it *is* and we didn't get a path, print an error then follow
+ // the fallback logic. If it's *not* ready, we're probably either extremely early in a tool startup flow or inside
+ // a unit test, so just execute the fallback logic without an error.
+ [[maybe_unused]] bool assetProcessorReady = false;
+ AzFramework::AssetSystemRequestBus::BroadcastResult(
+ assetProcessorReady, &AzFramework::AssetSystemRequestBus::Events::AssetProcessorIsReady);
+
+ AZ_Error("Prefab", !assetProcessorReady,
+ "Relative source path for '%.*s' could not be determined. Using project path as relative root.",
+ AZ_STRING_ARG(path.Native()));
+
+ AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path.Native()).MakePreferred();
+
+ if (pathWithOSSeparator.IsAbsolute())
+ {
+ // If an absolute path was passed in, make it relative to the project path.
+ finalPath = AZ::IO::Path(path.Native(), '/').MakePreferred().LexicallyRelative(m_projectPathWithSlashSeparator);
+ }
+ else
+ {
+ // If a relative path was passed in, just return it.
+ finalPath = path;
+ }
}
- return AZ::IO::Path(path.Native(), '/').MakePreferred().LexicallyRelative(m_projectPathWithSlashSeparator);
+ return finalPath;
}
AZ::IO::Path PrefabLoaderInterface::GeneratePath()
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h
index d11cb62ca3..3722e14a97 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h
@@ -72,6 +72,16 @@ namespace AzToolsFramework
*/
bool SaveTemplate(TemplateId templateId) override;
+ /**
+ * Saves a Prefab Template to the provided absolute source path, which needs to match the relative path in the template.
+ * Converts Prefab Template form into .prefab form by collapsing nested Template info
+ * into a source path and patches.
+ * @param templateId Id of the template to be saved
+ * @param absolutePath Absolute path to save the file to
+ * @return bool on whether the operation succeeded or not
+ */
+ bool SaveTemplateToFile(TemplateId templateId, AZ::IO::PathView absolutePath) override;
+
/**
* Saves a Prefab Template into the provided output string.
* Converts Prefab Template form into .prefab form by collapsing nested Template info
@@ -91,9 +101,11 @@ namespace AzToolsFramework
//! The path will always have the correct separator for the current OS
AZ::IO::Path GetFullPath(AZ::IO::PathView path) override;
- //! Converts path into a relative path to the project, this will be the paths in .prefab file.
- //! The path will always have '/' separator.
- AZ::IO::Path GetRelativePathToProject(AZ::IO::PathView path) override;
+ //! Converts path into a path that's relative to the highest-priority containing folder of all the folders registered
+ //! with the engine.
+ //! This path will be the path that appears in the .prefab file.
+ //! The path will always use the '/' separator.
+ AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) override;
//! Returns if the path is a valid path for a prefab
static bool IsValidPrefabPath(AZ::IO::PathView path);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
index a4055fb15a..0e551cee6b 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
@@ -60,6 +60,16 @@ namespace AzToolsFramework
*/
virtual bool SaveTemplate(TemplateId templateId) = 0;
+ /**
+ * Saves a Prefab Template to the provided absolute source path, which needs to match the relative path in the template.
+ * Converts Prefab Template form into .prefab form by collapsing nested Template info
+ * into a source path and patches.
+ * @param templateId Id of the template to be saved
+ * @param absolutePath Absolute path to save the file to
+ * @return bool on whether the operation succeeded or not
+ */
+ virtual bool SaveTemplateToFile(TemplateId templateId, AZ::IO::PathView absolutePath) = 0;
+
/**
* Saves a Prefab Template into the provided output string.
* Converts Prefab Template form into .prefab form by collapsing nested Template info
@@ -74,9 +84,11 @@ namespace AzToolsFramework
//! The path will always have the correct separator for the current OS
virtual AZ::IO::Path GetFullPath(AZ::IO::PathView path) = 0;
- //! Converts path into a relative path to the current project, this will be the paths in .prefab file.
- //! The path will always have '/' separator.
- virtual AZ::IO::Path GetRelativePathToProject(AZ::IO::PathView path) = 0;
+ //! Converts path into a path that's relative to the highest-priority containing folder of all the folders registered
+ //! with the engine.
+ //! This path will be the path that appears in the .prefab file.
+ //! The path will always use the '/' separator.
+ virtual AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) = 0;
protected:
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
index 0181050a32..fadcc1b81f 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
@@ -64,7 +64,7 @@ namespace AzToolsFramework
m_prefabUndoCache.Destroy();
}
- PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath)
+ PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView absolutePath)
{
EntityList inputEntityList, topLevelEntities;
AZ::EntityId commonRootEntityId;
@@ -76,6 +76,8 @@ namespace AzToolsFramework
return findCommonRootOutcome;
}
+ AZ_Assert(absolutePath.IsAbsolute(), "CreatePrefab requires an absolute path for saving the initial prefab file.");
+
InstanceOptionalReference instanceToCreate;
{
// Initialize Undo Batch object
@@ -144,7 +146,8 @@ namespace AzToolsFramework
// Create the Prefab
instanceToCreate = prefabEditorEntityOwnershipInterface->CreatePrefab(
- entities, AZStd::move(instancePtrs), filePath, commonRootEntityOwningInstance);
+ entities, AZStd::move(instancePtrs), m_prefabLoaderInterface->GenerateRelativePath(absolutePath),
+ commonRootEntityOwningInstance);
if (!instanceToCreate)
{
@@ -254,7 +257,7 @@ namespace AzToolsFramework
}
// Save Template to file
- m_prefabLoaderInterface->SaveTemplate(instanceToCreate->get().GetTemplateId());
+ m_prefabLoaderInterface->SaveTemplateToFile(instanceToCreate->get().GetTemplateId(), absolutePath);
return AZ::Success();
}
@@ -318,7 +321,7 @@ namespace AzToolsFramework
}
//Detect whether this instantiation would produce a cyclical dependency
- auto relativePath = m_prefabLoaderInterface->GetRelativePathToProject(filePath);
+ auto relativePath = m_prefabLoaderInterface->GenerateRelativePath(filePath);
Prefab::TemplateId templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(relativePath);
if (templateId == InvalidTemplateId)
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h
index 7e2357dd44..e68a3e0b1e 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h
@@ -46,7 +46,7 @@ namespace AzToolsFramework
void UnregisterPrefabPublicHandlerInterface();
// PrefabPublicInterface...
- PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath) override;
+ PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView absolutePath) override;
PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) override;
PrefabOperationResult SavePrefab(AZ::IO::Path filePath) override;
PrefabEntityResult CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position) override;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h
index 0750c4d264..2e9152fd1b 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h
@@ -46,10 +46,10 @@ namespace AzToolsFramework
* Create a prefab out of the entities provided, at the path provided.
* Automatically detects descendants of entities, and discerns between entities and child instances.
* @param entityIds The entities that should form the new prefab (along with their descendants).
- * @param filePath The path for the new prefab file.
+ * @param filePath The absolute path for the new prefab file.
* @return An outcome object; on failure, it comes with an error message detailing the cause of the error.
*/
- virtual PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath) = 0;
+ virtual PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView absolutePath) = 0;
/**
* Instantiate a prefab from a prefab file.
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp
index c4e6415b02..0136f791b3 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp
@@ -95,7 +95,7 @@ namespace AzToolsFramework
const AZStd::vector& entities, AZStd::vector>&& instancesToConsume,
AZ::IO::PathView filePath, AZStd::unique_ptr containerEntity, bool shouldCreateLinks)
{
- AZ::IO::Path relativeFilePath = m_prefabLoader.GetRelativePathToProject(filePath);
+ AZ::IO::Path relativeFilePath = m_prefabLoader.GenerateRelativePath(filePath);
if (GetTemplateIdFromFilePath(relativeFilePath) != InvalidTemplateId)
{
AZ_Error("Prefab", false,
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/ProcesedObjectStore.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/ProcesedObjectStore.cpp
index 78d1332a71..050afd813d 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/ProcesedObjectStore.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/ProcesedObjectStore.cpp
@@ -10,7 +10,7 @@
*
*/
-#include
+#include
#include
namespace AzToolsFramework::Prefab::PrefabConversionUtils
@@ -73,8 +73,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
uint32_t ProcessedObjectStore::BuildSubId(AZStd::string_view id)
{
- AZ::Uuid subIdHash = AZ::Uuid::CreateData(id.data(), id.size());
- return azlossy_caster(subIdHash.GetHash());
+ return AzFramework::SpawnableAssetHandler::BuildSubId(id);
}
const AZStd::string& ProcessedObjectStore::GetId() const
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponentMode.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponentMode.cpp
index 97e27ac748..497bcf15d7 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponentMode.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponentMode.cpp
@@ -28,7 +28,7 @@ namespace AzToolsFramework
AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(worldFromLocal, m_entityComponentIdPair.GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
- worldFromLocal.ExtractScale();
+ worldFromLocal.ExtractUniformScale();
m_manipulators = AZStd::make_unique(worldFromLocal);
m_manipulators->Register(g_mainManipulatorManagerId);
m_manipulators->SetAxes(AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ());
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp
index 285d962b46..3e13e6226b 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp
@@ -32,7 +32,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -50,10 +49,10 @@ namespace AzToolsFramework
{
const AZ::u32 ParentEntityCRC = AZ_CRC("Parent Entity", 0x5b1b276c);
- // Decompose a transform into euler angles in degrees, scale (along basis, any shear will be dropped), and translation.
- void DecomposeTransform(const AZ::Transform& transform, AZ::Vector3& translation, AZ::Vector3& rotation, AZ::Vector3& scale)
+ // Decompose a transform into euler angles in degrees, uniform scale, and translation.
+ void DecomposeTransform(const AZ::Transform& transform, AZ::Vector3& translation, AZ::Vector3& rotation, float& scale)
{
- scale = transform.GetScale();
+ scale = transform.GetUniformScale();
translation = transform.GetTranslation();
rotation = transform.GetRotation().GetEulerDegrees();
}
@@ -120,7 +119,7 @@ namespace AzToolsFramework
// Decompose the old slice-relative transform and set it as a our editor transform,
// since the entity is now our parent.
EditorTransform editorTransform;
- DecomposeTransform(sliceRelTransform, editorTransform.m_translate, editorTransform.m_rotate, editorTransform.m_scale);
+ DecomposeTransform(sliceRelTransform, editorTransform.m_translate, editorTransform.m_rotate, editorTransform.m_uniformScale);
editorTransformElement.Convert(context);
editorTransformElement.SetData(context, editorTransform);
}
@@ -170,6 +169,23 @@ namespace AzToolsFramework
return true;
}
+
+ bool EditorTransformDataConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
+ {
+ if (classElement.GetVersion() < 3)
+ {
+ // version 3 replaces vector scale with uniform scale but does not yet delete the legacy scale data
+ // in order to allow for migration
+ AZ::Vector3 vectorScale;
+ if (classElement.FindSubElementAndGetData(AZ_CRC_CE("Scale"), vectorScale))
+ {
+ const float uniformScale = vectorScale.GetMaxElement();
+ classElement.AddElementWithData(context, "UniformScale", uniformScale);
+ }
+ }
+
+ return true;
+ }
} // namespace Internal
TransformComponent::TransformComponent()
@@ -357,7 +373,7 @@ namespace AzToolsFramework
AZ::Transform TransformComponent::GetLocalScaleTM() const
{
- return AZ::Transform::CreateUniformScale(m_editorTransform.m_scale.GetMaxElement());
+ return AZ::Transform::CreateUniformScale(m_editorTransform.m_uniformScale);
}
const AZ::Transform& TransformComponent::GetLocalTM()
@@ -374,12 +390,13 @@ namespace AzToolsFramework
// given a local transform, update local transform.
void TransformComponent::SetLocalTM(const AZ::Transform& finalTx)
{
- AZ::Vector3 tx, rot, scale;
- Internal::DecomposeTransform(finalTx, tx, rot, scale);
+ AZ::Vector3 tx, rot;
+ float uniformScale;
+ Internal::DecomposeTransform(finalTx, tx, rot, uniformScale);
m_editorTransform.m_translate = tx;
m_editorTransform.m_rotate = rot;
- m_editorTransform.m_scale = scale;
+ m_editorTransform.m_uniformScale = uniformScale;
TransformChanged();
}
@@ -599,31 +616,21 @@ namespace AzToolsFramework
return result;
}
- void TransformComponent::SetLocalScale(const AZ::Vector3& scale)
- {
- m_editorTransform.m_scale = scale;
- TransformChanged();
- }
-
AZ::Vector3 TransformComponent::GetLocalScale()
{
- return m_editorTransform.m_scale;
- }
-
- AZ::Vector3 TransformComponent::GetWorldScale()
- {
- return GetWorldTM().GetScale();
+ AZ_WarningOnce("TransformComponent", false, "GetLocalScale is deprecated, please use GetLocalUniformScale instead");
+ return m_editorTransform.m_legacyScale;
}
void TransformComponent::SetLocalUniformScale(float scale)
{
- m_editorTransform.m_scale = AZ::Vector3(scale);
+ m_editorTransform.m_uniformScale = scale;
TransformChanged();
}
float TransformComponent::GetLocalUniformScale()
{
- return m_editorTransform.m_scale.GetMaxElement();
+ return m_editorTransform.m_uniformScale;
}
float TransformComponent::GetWorldUniformScale()
@@ -1141,9 +1148,10 @@ namespace AzToolsFramework
serializeContext->Class()->
Field("Translate", &EditorTransform::m_translate)->
Field("Rotate", &EditorTransform::m_rotate)->
- Field("Scale", &EditorTransform::m_scale)->
+ Field("Scale", &EditorTransform::m_legacyScale)->
Field("Locked", &EditorTransform::m_locked)->
- Version(2);
+ Field("UniformScale", &EditorTransform::m_uniformScale)->
+ Version(3, &Internal::EditorTransformDataConverter);
serializeContext->Class()->
Field("Parent Entity", &TransformComponent::m_parentEntityId)->
@@ -1202,7 +1210,7 @@ namespace AzToolsFramework
Attribute(AZ::Edit::Attributes::Suffix, " deg")->
Attribute(AZ::Edit::Attributes::ReadOnly, &EditorTransform::m_locked)->
Attribute(AZ::Edit::Attributes::SliceFlags, AZ::Edit::SliceFlags::NotPushableOnSliceRoot)->
- DataElement(TransformScaleHandler, &EditorTransform::m_scale, "Scale", "Local Scale")->
+ DataElement(AZ::Edit::UIHandlers::Default, &EditorTransform::m_uniformScale, "Uniform Scale", "Local Uniform Scale")->
Attribute(AZ::Edit::Attributes::Step, 0.1f)->
Attribute(AZ::Edit::Attributes::ReadOnly, &EditorTransform::m_locked)
;
@@ -1230,7 +1238,8 @@ namespace AzToolsFramework
{
AzToolsFramework::ScopedUndoBatch undo("Reset transform values");
m_editorTransform.m_translate = AZ::Vector3::CreateZero();
- m_editorTransform.m_scale = AZ::Vector3::CreateOne();
+ m_editorTransform.m_legacyScale = AZ::Vector3::CreateOne();
+ m_editorTransform.m_uniformScale = 1.0f;
m_editorTransform.m_rotate = AZ::Vector3::CreateZero();
OnTransformChanged();
SetDirty();
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h
index f772b608c1..80db5e10fb 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.h
@@ -115,9 +115,7 @@ namespace AzToolsFramework
AZ::Quaternion GetLocalRotationQuaternion() override;
// Scale Modifiers
- void SetLocalScale(const AZ::Vector3& scale) override;
AZ::Vector3 GetLocalScale() override;
- AZ::Vector3 GetWorldScale() override;
void SetLocalUniformScale(float scale) override;
float GetLocalUniformScale() override;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponentBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponentBus.h
index 437a39b1a0..26fa4d758e 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponentBus.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponentBus.h
@@ -30,7 +30,8 @@ namespace AzToolsFramework
EditorTransform()
{
m_translate = AZ::Vector3::CreateZero();
- m_scale = AZ::Vector3::CreateOne();
+ m_legacyScale = AZ::Vector3::CreateOne();
+ m_uniformScale = 1.0f;
m_rotate = AZ::Vector3::CreateZero();
m_locked = false;
}
@@ -40,9 +41,10 @@ namespace AzToolsFramework
return EditorTransform();
}
- AZ::Vector3 m_translate; //! Translation in engine units (meters)
- AZ::Vector3 m_scale;
- AZ::Vector3 m_rotate; //! Rotation in degrees
+ AZ::Vector3 m_translate; //!< Translation in engine units (meters)
+ AZ::Vector3 m_legacyScale; //!< Legacy vector scale value, retained only for migration.
+ float m_uniformScale; //!< Single scale value applied uniformly.
+ AZ::Vector3 m_rotate; //!< Rotation in degrees
bool m_locked;
};
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.cpp
deleted file mode 100644
index 94d0113bcf..0000000000
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-
-#include "AzToolsFramework_precompiled.h"
-#include
-#include
-#include
-
-namespace AzToolsFramework
-{
- void RegisterTransformScaleHandler()
- {
- PropertyTypeRegistrationMessages::Bus::Broadcast(&PropertyTypeRegistrationMessages::RegisterPropertyType, aznew Components::TransformScalePropertyHandler());
- }
-
- namespace Components
- {
- AZ::u32 TransformScalePropertyHandler::GetHandlerName(void) const
- {
- return TransformScaleHandler;
- }
-
- QWidget* TransformScalePropertyHandler::CreateGUI(QWidget* parent)
- {
- AzQtComponents::DoubleSpinBox* newCtrl = new AzQtComponents::DoubleSpinBox(parent);
- connect(newCtrl, QOverload::of(&AzQtComponents::DoubleSpinBox::valueChanged), newCtrl, [newCtrl]()
- {
- AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestWrite, newCtrl);
- });
-
- newCtrl->setMinimum(AZ::MinTransformScale);
- newCtrl->setMaximum(AZ::MaxTransformScale);
-
- return newCtrl;
- }
-
- void TransformScalePropertyHandler::ConsumeAttribute(AzQtComponents::DoubleSpinBox* GUI, AZ::u32 attrib,
- AzToolsFramework::PropertyAttributeReader* attrValue, [[maybe_unused]] const char* debugName)
- {
- if (attrib == AZ::Edit::Attributes::Suffix)
- {
- AZStd::string label;
- if (attrValue->Read(label))
- {
- GUI->setSuffix(label.c_str());
- }
- }
- }
-
- void TransformScalePropertyHandler::WriteGUIValuesIntoProperty([[maybe_unused]] size_t index, AzQtComponents::DoubleSpinBox* GUI,
- AZ::Vector3& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
- {
- const float value = aznumeric_cast(GUI->value());
- const float currentMaxElement = instance.GetMaxElement();
- if (currentMaxElement != 0.0f)
- {
- instance *= value / currentMaxElement;
- }
- else
- {
- instance = AZ::Vector3(value);
- }
- }
-
- bool TransformScalePropertyHandler::ReadValuesIntoGUI([[maybe_unused]] size_t index, AzQtComponents::DoubleSpinBox* GUI,
- const AZ::Vector3& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
- {
- QSignalBlocker signalBlocker(GUI);
- GUI->setValue(instance.GetMaxElement());
- return true;
- }
- } // namespace Components
-} // namespace AzToolsFramework
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.h
deleted file mode 100644
index f13aa37904..0000000000
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-* its licensors.
-*
-* For complete copyright and license terms please see the LICENSE at the root of this
-* distribution (the "License"). All use of this software is governed by the License,
-* or, if provided, by the license below or the license accompanying this file. Do not
-* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-*
-*/
-
-#pragma once
-
-#if !defined(Q_MOC_RUN)
-#include
-#include
-#include
-#endif
-
-namespace AzToolsFramework
-{
- namespace Components
- {
- static const AZ::Crc32 TransformScaleHandler = AZ_CRC_CE("TransformScale");
-
- //! Handler to allow the scale field inside the Transform Component to be represented as a single value in
- //! the editor, but stored internally as a Vector3.
- //! The purpose for this is to prevent any new entities being created with non-uniform scale on the Transform
- //! Component, but preserve the data required for migrating any existing entities to use the Non-Uniform Scale
- //! Component, until all migration work is completed.
- //! The value shown in the editor will be the maximum value from the scale vector, and changing the value in
- //! the editor will update the vector so that its maximum value matches the newly edited value, but its
- //! components retain their existing proportion.
- //! For example, if the current vector scale is (2, 3, 4), the value in the editor will appear as 4. If the value
- //! in the editor is updated to 2, then the vector scale will update to (1, 1.5, 2), keeping the same proportion
- //! between the x, y and z components.
- class TransformScalePropertyHandler
- : public QObject
- , public AzToolsFramework::PropertyHandler
- {
- Q_OBJECT //AUTOMOC
- public:
- AZ_CLASS_ALLOCATOR(TransformScalePropertyHandler, AZ::SystemAllocator, 0);
-
- AZ::u32 GetHandlerName(void) const override;
- QWidget* CreateGUI(QWidget* parent) override;
- void ConsumeAttribute(AzQtComponents::DoubleSpinBox* GUI, AZ::u32 attrib,
- AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override;
- void WriteGUIValuesIntoProperty(size_t index, AzQtComponents::DoubleSpinBox* GUI,
- AZ::Vector3& instance, AzToolsFramework::InstanceDataNode* node) override;
- bool ReadValuesIntoGUI(size_t index, AzQtComponents::DoubleSpinBox* GUI,
- const AZ::Vector3& instance, AzToolsFramework::InstanceDataNode* node) override;
- };
- } // namespace Components
-} // namespace AzToolsFramework
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
index cc65b61908..8293614525 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
@@ -172,7 +172,7 @@ namespace AzToolsFramework
const int autoExpandDelayMilliseconds = 2500;
m_gui->m_objectTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
- m_gui->m_objectTree->setEditTriggers(QAbstractItemView::EditKeyPressed);
+ SetDefaultTreeViewEditTriggers();
m_gui->m_objectTree->setAutoExpandDelay(autoExpandDelayMilliseconds);
m_gui->m_objectTree->setDragEnabled(true);
m_gui->m_objectTree->setDropIndicatorShown(true);
@@ -850,6 +850,11 @@ namespace AzToolsFramework
addAction(m_actionGoToEntitiesInViewport);
}
+ void EntityOutlinerWidget::SetDefaultTreeViewEditTriggers()
+ {
+ m_gui->m_objectTree->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::EditKeyPressed);
+ }
+
void EntityOutlinerWidget::OnEntityPickModeStarted()
{
m_gui->m_objectTree->setDragEnabled(false);
@@ -862,7 +867,7 @@ namespace AzToolsFramework
{
m_gui->m_objectTree->setDragEnabled(true);
m_gui->m_objectTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
- m_gui->m_objectTree->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
+ SetDefaultTreeViewEditTriggers();
m_inObjectPickMode = false;
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx
index 9a02febab2..6e3979a21e 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx
@@ -166,6 +166,8 @@ namespace AzToolsFramework
// to a given entity
void QueueScrollToNewContent(const AZ::EntityId& entityId) override;
+ void SetDefaultTreeViewEditTriggers();
+
void ScrollToNewContent();
bool m_scrollToNewContentQueued;
bool m_scrollToSelectedEntity;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
index 3edc190fb7..021b97a7dd 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
@@ -333,7 +333,7 @@ namespace AzToolsFramework
}
}
- auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, s_prefabLoaderInterface->GetRelativePathToProject(prefabFilePath.data()));
+ auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, prefabFilePath.data());
if (!createPrefabOutcome.IsSuccess())
{
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp
index 23f8378df5..169a90497b 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp
@@ -777,6 +777,23 @@ namespace AzToolsFramework
selection.SetDefaultDirectory(defaultDirectory);
}
+ if (m_hideProductFilesInAssetPicker)
+ {
+ FilterConstType displayFilter = selection.GetDisplayFilter();
+
+ EntryTypeFilter* productsFilter = new EntryTypeFilter();
+ productsFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Product);
+
+ InverseFilter* noProductsFilter = new InverseFilter();
+ noProductsFilter->SetFilter(FilterConstType(productsFilter));
+
+ CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
+ compFilter->AddFilter(FilterConstType(displayFilter));
+ compFilter->AddFilter(FilterConstType(noProductsFilter));
+
+ selection.SetDisplayFilter(FilterConstType(compFilter));
+ }
+
AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, parentWidget());
if (selection.IsValid())
{
@@ -936,11 +953,16 @@ namespace AzToolsFramework
return;
}
- const AZ::Data::AssetId assetID = GetCurrentAssetID();
- m_currentAssetHint = "";
-
- if (!m_unnamedType)
+ const AZStd::string& folderPath = GetFolderSelection();
+ if (!folderPath.empty())
{
+ m_currentAssetHint = folderPath;
+ }
+ else
+ {
+ const AZ::Data::AssetId assetID = GetCurrentAssetID();
+ m_currentAssetHint = "";
+
AZ::Outcome jobOutcome = AZ::Failure();
AssetSystemJobRequestBus::BroadcastResult(jobOutcome, &AssetSystemJobRequestBus::Events::GetAssetJobsInfoByAssetID, assetID, false, false);
@@ -954,7 +976,7 @@ namespace AzToolsFramework
if (!jobs.empty())
{
- // The default behavior is show to the source filename.
+ // The default behavior is to show the source filename.
assetPath = jobs[0].m_sourceFile;
AZStd::string errorLog;
@@ -1172,6 +1194,16 @@ namespace AzToolsFramework
return m_showProductAssetName;
}
+ void PropertyAssetCtrl::SetHideProductFilesInAssetPicker(bool hide)
+ {
+ m_hideProductFilesInAssetPicker = hide;
+ }
+
+ bool PropertyAssetCtrl::GetHideProductFilesInAssetPicker() const
+ {
+ return m_hideProductFilesInAssetPicker;
+ }
+
void PropertyAssetCtrl::SetShowThumbnail(bool enable)
{
m_showThumbnail = enable;
@@ -1297,6 +1329,14 @@ namespace AzToolsFramework
GUI->SetShowProductAssetName(showProductAssetName);
}
}
+ else if(attrib == AZ::Edit::Attributes::HideProductFilesInAssetPicker)
+ {
+ bool hideProductFilesInAssetPicker = false;
+ if (attrValue->Read(hideProductFilesInAssetPicker))
+ {
+ GUI->SetHideProductFilesInAssetPicker(hideProductFilesInAssetPicker);
+ }
+ }
else if (attrib == AZ::Edit::Attributes::ClearNotify)
{
PropertyAssetCtrl::ClearCallbackType* func = azdynamic_cast(attrValue->GetAttribute());
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx
index 37af3d0594..5a6310eb35 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx
@@ -158,6 +158,10 @@ namespace AzToolsFramework
//! Assets can be either source or product assets generated from source assets. By default, source assets are shown in the property asset. You can override that with this flag.
bool m_showProductAssetName = true;
+ //! Assets can be either source or product assets generated from source assets.
+ //! By default the asset picker shows both on an AZ::Asset<> property. You can hide product assets with this flag.
+ bool m_hideProductFilesInAssetPicker = false;
+
bool m_showThumbnail = false;
bool m_showThumbnailDropDownButton = false;
EditCallbackType* m_thumbnailCallback = nullptr;
@@ -211,6 +215,9 @@ namespace AzToolsFramework
void SetShowProductAssetName(bool enable);
bool GetShowProductAssetName() const;
+ void SetHideProductFilesInAssetPicker(bool hide);
+ bool GetHideProductFilesInAssetPicker() const;
+
void SetShowThumbnail(bool enable);
bool GetShowThumbnail() const;
void SetShowThumbnailDropDownButton(bool enable);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.cpp
index bd61e6ceed..6dc5bdd001 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.cpp
@@ -16,7 +16,6 @@
#include
#include
#include
-#include
namespace AzToolsFramework
{
@@ -38,7 +37,6 @@ namespace AzToolsFramework
void RegisterButtonPropertyHandlers();
void RegisterMultiLineEditHandler();
void RegisterCrcHandler();
- void RegisterTransformScaleHandler();
void ReflectPropertyEditor(AZ::ReflectContext* context);
namespace Components
@@ -192,7 +190,6 @@ namespace AzToolsFramework
RegisterVectorHandlers();
RegisterButtonPropertyHandlers();
RegisterMultiLineEditHandler();
- RegisterTransformScaleHandler();
// GenericComboBoxHandlers
RegisterGenericComboBoxHandler();
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h
index 8e91dc945d..91eee18cb7 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h
@@ -165,15 +165,18 @@ namespace AzToolsFramework
virtual bool AngleSnappingEnabled() = 0;
/// Return the angle snapping/step size.
virtual float AngleStep() = 0;
- /// Transform a point in world space to screen space coordinates.
+ /// Transform a point in world space to screen space coordinates in Qt Widget space.
+ /// Multiply by DeviceScalingFactor to get the position in viewport pixel space.
virtual AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition) = 0;
- /// Transform a point in screen space coordinates to a vector in world space based on clip space depth.
+ /// Transform a point from Qt widget screen space to world space based on the given clip space depth.
/// Depth specifies a relative camera depth to project in the range of [0.f, 1.f].
/// Returns the world space position if successful.
virtual AZStd::optional ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) = 0;
/// Casts a point in screen space to a ray in world space originating from the viewport camera frustum's near plane.
/// Returns a ray containing the ray's origin and a direction normal, if successful.
virtual AZStd::optional ViewportScreenToWorldRay(const AzFramework::ScreenPoint& screenPosition) = 0;
+ /// Gets the DPI scaling factor that translates Qt widget space into viewport pixel space.
+ virtual float DeviceScalingFactor() = 0;
protected:
~ViewportInteractionRequests() = default;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake
index aaf5c86d33..8d0180f6ce 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake
@@ -293,8 +293,6 @@ set(FILES
ToolsComponents/TransformComponent.h
ToolsComponents/TransformComponent.cpp
ToolsComponents/TransformComponentBus.h
- ToolsComponents/TransformScalePropertyHandler.cpp
- ToolsComponents/TransformScalePropertyHandler.h
ToolsComponents/ScriptEditorComponent.cpp
ToolsComponents/ScriptEditorComponent.h
ToolsComponents/ToolsAssetCatalogComponent.cpp
diff --git a/Code/Framework/AzToolsFramework/Tests/SliceStabilityTests/SliceStabilityTestFramework.cpp b/Code/Framework/AzToolsFramework/Tests/SliceStabilityTests/SliceStabilityTestFramework.cpp
index 8455e6d669..5dcdaa045c 100644
--- a/Code/Framework/AzToolsFramework/Tests/SliceStabilityTests/SliceStabilityTestFramework.cpp
+++ b/Code/Framework/AzToolsFramework/Tests/SliceStabilityTests/SliceStabilityTestFramework.cpp
@@ -141,7 +141,7 @@ namespace UnitTest
// Set the new entity's transform to non zero values
// This helps validate in comparison tests that the transform values of created entities persist during slice operations
- entityTransform->SetLocalScale(AZ::Vector3(5, 5, 5));
+ entityTransform->SetLocalUniformScale(5);
entityTransform->SetLocalRotation(AZ::Vector3RadToDeg(AZ::Vector3(90, 90, 90)));
entityTransform->SetLocalTranslation(AZ::Vector3(100, 100, 100));
diff --git a/Code/LauncherUnified/Launcher.cpp b/Code/LauncherUnified/Launcher.cpp
index 1f29478399..922397c325 100644
--- a/Code/LauncherUnified/Launcher.cpp
+++ b/Code/LauncherUnified/Launcher.cpp
@@ -488,8 +488,8 @@ namespace O3DELauncher
const AZStd::string_view buildTargetName = GetBuildTargetName();
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddBuildSystemTargetSpecialization(*settingsRegistry, buildTargetName);
- AZ_TracePrintf("Launcher", R"(Running project "%.*s.)" "\n"
- R"(The project name value has been successfully set in the Settings Registry at key "%s/project_name)"
+ AZ_TracePrintf("Launcher", R"(Running project "%.*s")" "\n"
+ R"(The project name has been successfully set in the Settings Registry at key "%s/project_name")"
R"( for Launcher target "%.*s")" "\n",
aznumeric_cast(launcherProjectName.size()), launcherProjectName.data(),
AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey,
@@ -643,7 +643,8 @@ namespace O3DELauncher
if (gEnv && gEnv->pConsole)
{
// Execute autoexec.cfg to load the initial level
- AZ::Interface::Get()->ExecuteConfigFile("autoexec.cfg");
+ auto autoExecFile = AZ::IO::FixedMaxPath{pathToAssets} / "autoexec.cfg";
+ AZ::Interface::Get()->ExecuteConfigFile(autoExecFile.Native());
// Find out if console command file was passed
// via --console-command-file=%filename% and execute it
diff --git a/Code/LauncherUnified/Platform/Windows/launcher_project_windows.cmake b/Code/LauncherUnified/Platform/Windows/launcher_project_windows.cmake
index bcef59ec5a..35c89caf15 100644
--- a/Code/LauncherUnified/Platform/Windows/launcher_project_windows.cmake
+++ b/Code/LauncherUnified/Platform/Windows/launcher_project_windows.cmake
@@ -10,6 +10,11 @@
#
set(ICON_FILE ${project_real_path}/Gem/Resources/GameSDK.ico)
+if(NOT EXISTS ${ICON_FILE})
+ # Try another project-relative path
+ set(ICON_FILE ${project_real_path}/Resources/GameSDK.ico)
+endif()
+
if(NOT EXISTS ${ICON_FILE})
# Try the common LauncherUnified icon instead
set(ICON_FILE Resources/GameSDK.ico)
diff --git a/Code/LauncherUnified/launcher_generator.cmake b/Code/LauncherUnified/launcher_generator.cmake
index edb6655411..c5d60eb29e 100644
--- a/Code/LauncherUnified/launcher_generator.cmake
+++ b/Code/LauncherUnified/launcher_generator.cmake
@@ -179,6 +179,7 @@ function(ly_delayed_generate_static_modules_inl)
${launcher_unified_binary_dir}/${project_name}.GameLauncher/Includes/StaticModules.inl
)
+ ly_target_link_libraries(${project_name}.GameLauncher PRIVATE ${all_game_gem_dependencies})
if(PAL_TRAIT_BUILD_SERVER_SUPPORTED)
get_property(server_gem_dependencies GLOBAL PROPERTY LY_STATIC_MODULE_PROJECTS_DEPENDENCIES_${project_name}.ServerLauncher)
@@ -204,6 +205,7 @@ function(ly_delayed_generate_static_modules_inl)
${launcher_unified_binary_dir}/${project_name}.ServerLauncher/Includes/StaticModules.inl
)
+ ly_target_link_libraries(${project_name}.ServerLauncher PRIVATE ${all_server_gem_dependencies})
endif()
endforeach()
endif()
diff --git a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp
index c8bd157b65..e0ba106875 100644
--- a/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp
+++ b/Code/Sandbox/Editor/AzAssetBrowser/AzAssetBrowserRequestHandler.cpp
@@ -137,8 +137,20 @@ namespace AzAssetBrowserRequestHandlerPrivate
entityName = AZStd::string::format("Entity%d", GetIEditor()->GetObjectManager()->GetObjectCount());
}
- AZ::Entity* newEntity = aznew AZ::Entity(entityName.c_str());
- EditorEntityContextRequestBus::Broadcast(&EditorEntityContextRequests::AddRequiredComponents, *newEntity);
+ AZ::EntityId targetEntityId;
+ EditorRequests::Bus::BroadcastResult(targetEntityId, &EditorRequests::CreateNewEntityAtPosition, worldTransform.GetTranslation(), AZ::EntityId());
+
+ AZ::Entity* newEntity = nullptr;
+ AZ::ComponentApplicationBus::BroadcastResult(newEntity, &AZ::ComponentApplicationRequests::FindEntity, targetEntityId);
+
+ if (newEntity == nullptr)
+ {
+ return;
+ }
+
+ newEntity->SetName(entityName);
+
+ newEntity->Deactivate();
// Create component.
AZ::Component* newComponent = newEntity->CreateComponent(componentTypeId);
@@ -151,15 +163,7 @@ namespace AzAssetBrowserRequestHandlerPrivate
newEntity->AddComponent(newComponent);
}
- // Set entity position.
- auto* transformComponent = newEntity->FindComponent();
- if (transformComponent)
- {
- transformComponent->SetWorldTM(worldTransform);
- }
-
- // Add the entity to the editor context, which activates it and creates the sandbox object.
- EditorEntityContextRequestBus::Broadcast(&EditorEntityContextRequests::AddEditorEntity, newEntity);
+ newEntity->Activate();
// set asset after components have been activated in AddEditorEntity method
if (newComponent)
diff --git a/Code/Sandbox/Editor/CMakeLists.txt b/Code/Sandbox/Editor/CMakeLists.txt
index 4706a61d08..7be9947e99 100644
--- a/Code/Sandbox/Editor/CMakeLists.txt
+++ b/Code/Sandbox/Editor/CMakeLists.txt
@@ -129,6 +129,8 @@ ly_add_target(
3rdParty::AWSNativeSDK::Core
3rdParty::Qt::Network
Legacy::EditorCore
+ RUNTIME_DEPENDENCIES
+ Gem::AtomViewportDisplayInfo
)
ly_add_source_properties(
SOURCES CryEdit.cpp
@@ -244,7 +246,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
Legacy::CryCommon
AZ::AzToolsFramework
Legacy::EditorLib
- Gem::LmbrCentral
+ RUNTIME_DEPENDENCIES
+ Gem::LmbrCentral
)
ly_add_googletest(
NAME Legacy::EditorLib.Tests
diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp
index ecd11da817..989d6e407d 100644
--- a/Code/Sandbox/Editor/EditorViewportWidget.cpp
+++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp
@@ -1221,50 +1221,73 @@ void EditorViewportWidget::SetViewportId(int id)
AzFramework::ReloadCameraKeyBindings();
auto controller = AZStd::make_shared();
- controller->SetCameraListBuilderCallback([](AzFramework::Cameras& cameras)
- {
- auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::CameraFreeLookButton);
- auto firstPersonPanCamera =
- AZStd::make_shared(AzFramework::CameraFreePanButton, AzFramework::LookPan);
- auto firstPersonTranslateCamera = AZStd::make_shared(AzFramework::LookTranslation);
- auto firstPersonWheelCamera = AZStd::make_shared();
+ controller->SetCameraListBuilderCallback(
+ [](AzFramework::Cameras& cameras)
+ {
+ auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::CameraFreeLookButton);
+ auto firstPersonPanCamera =
+ AZStd::make_shared(AzFramework::CameraFreePanButton, AzFramework::LookPan);
+ auto firstPersonTranslateCamera = AZStd::make_shared(AzFramework::LookTranslation);
+ auto firstPersonWheelCamera = AZStd::make_shared();
- auto orbitCamera = AZStd::make_shared();
- orbitCamera->SetLookAtFn([]() -> AZStd::optional {
- AZStd::optional manipulatorTransform;
- AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
- manipulatorTransform, AzToolsFramework::GetEntityContextId(),
- &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
+ auto orbitCamera = AZStd::make_shared();
+ orbitCamera->SetLookAtFn(
+ [](const AZ::Vector3& position, const AZ::Vector3& direction) -> AZStd::optional
+ {
+ AZStd::optional manipulatorTransform;
+ AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
+ manipulatorTransform, AzToolsFramework::GetEntityContextId(),
+ &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
- if (manipulatorTransform)
- {
- return manipulatorTransform->GetTranslation();
- }
+ // initially attempt to use manipulator transform if one exists (there is a selection)
+ if (manipulatorTransform)
+ {
+ return manipulatorTransform->GetTranslation();
+ }
- return {};
+ const float RayDistance = 1000.0f;
+ AzFramework::RenderGeometry::RayRequest ray;
+ ray.m_startWorldPosition = position;
+ ray.m_endWorldPosition = position + direction * RayDistance;
+ ray.m_onlyVisible = true;
+
+ AzFramework::RenderGeometry::RayResult renderGeometryIntersectionResult;
+ AzFramework::RenderGeometry::IntersectorBus::EventResult(
+ renderGeometryIntersectionResult, AzToolsFramework::GetEntityContextId(),
+ &AzFramework::RenderGeometry::IntersectorInterface::RayIntersect, ray);
+
+ // attempt a ray intersection with any visible mesh and return the intersection position if successful
+ if (renderGeometryIntersectionResult)
+ {
+ return renderGeometryIntersectionResult.m_worldPosition;
+ }
+
+ // if there is no selection or no intersection, fallback to default camera orbit behavior (ground plane
+ // intersection)
+ return {};
+ });
+
+ auto orbitRotateCamera = AZStd::make_shared(AzFramework::CameraOrbitLookButton);
+ auto orbitTranslateCamera = AZStd::make_shared(AzFramework::OrbitTranslation);
+ auto orbitDollyWheelCamera = AZStd::make_shared();
+ auto orbitDollyMoveCamera =
+ AZStd::make_shared(AzFramework::CameraOrbitDollyButton);
+ auto orbitPanCamera =
+ AZStd::make_shared(AzFramework::CameraOrbitPanButton, AzFramework::OrbitPan);
+
+ orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
+ orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
+ orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera);
+ orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera);
+ orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera);
+
+ cameras.AddCamera(firstPersonRotateCamera);
+ cameras.AddCamera(firstPersonPanCamera);
+ cameras.AddCamera(firstPersonTranslateCamera);
+ cameras.AddCamera(firstPersonWheelCamera);
+ cameras.AddCamera(orbitCamera);
});
- auto orbitRotateCamera = AZStd::make_shared(AzFramework::CameraOrbitLookButton);
- auto orbitTranslateCamera = AZStd::make_shared(AzFramework::OrbitTranslation);
- auto orbitDollyWheelCamera = AZStd::make_shared();
- auto orbitDollyMoveCamera =
- AZStd::make_shared(AzFramework::CameraOrbitDollyButton);
- auto orbitPanCamera =
- AZStd::make_shared(AzFramework::CameraOrbitPanButton, AzFramework::OrbitPan);
-
- orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
- orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
- orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera);
- orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera);
- orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera);
-
- cameras.AddCamera(firstPersonRotateCamera);
- cameras.AddCamera(firstPersonPanCamera);
- cameras.AddCamera(firstPersonTranslateCamera);
- cameras.AddCamera(firstPersonWheelCamera);
- cameras.AddCamera(orbitCamera);
- });
-
m_renderViewport->GetControllerList()->Add(controller);
}
else
diff --git a/Code/Sandbox/Editor/RenderViewport.cpp b/Code/Sandbox/Editor/RenderViewport.cpp
index f199590e4f..8cef9e802c 100644
--- a/Code/Sandbox/Editor/RenderViewport.cpp
+++ b/Code/Sandbox/Editor/RenderViewport.cpp
@@ -1259,9 +1259,6 @@ CBaseObject* CRenderViewport::GetCameraObject() const
//////////////////////////////////////////////////////////////////////////
void CRenderViewport::OnEditorNotifyEvent(EEditorNotifyEvent event)
{
- static ICVar* outputToHMD = gEnv->pConsole->GetCVar("output_to_hmd");
- AZ_Assert(outputToHMD, "cvar output_to_hmd is undeclared");
-
switch (event)
{
case eNotify_OnBeginGameMode:
@@ -1282,7 +1279,6 @@ void CRenderViewport::OnEditorNotifyEvent(EEditorNotifyEvent event)
if (deviceInfo)
{
- outputToHMD->Set(1);
m_previousContext = SetCurrentContext(deviceInfo->renderWidth, deviceInfo->renderHeight);
if (m_renderer->GetIStereoRenderer())
{
@@ -1313,10 +1309,6 @@ void CRenderViewport::OnEditorNotifyEvent(EEditorNotifyEvent event)
// failed to set the context back when done, or set it back to the wrong one.
CryWarning(VALIDATOR_MODULE_3DENGINE, VALIDATOR_WARNING, "RenderViewport render context was not correctly restored by someone else.");
}
- if (gSettings.bEnableGameModeVR)
- {
- outputToHMD->Set(0);
- }
RestorePreviousContext(m_previousContext);
m_bInRotateMode = false;
m_bInMoveMode = false;
diff --git a/Code/Sandbox/Editor/RenderViewport.h b/Code/Sandbox/Editor/RenderViewport.h
index d70dd59b98..b45c92b1c8 100644
--- a/Code/Sandbox/Editor/RenderViewport.h
+++ b/Code/Sandbox/Editor/RenderViewport.h
@@ -200,6 +200,7 @@ public:
{
return {};
}
+ float DeviceScalingFactor() override { return 1.0f; }
// AzToolsFramework::ViewportFreezeRequestBus
bool IsViewportInputFrozen() override;
diff --git a/Code/Sandbox/Editor/TrackView/TrackViewAnimNode.cpp b/Code/Sandbox/Editor/TrackView/TrackViewAnimNode.cpp
index ae7077b4fc..35306b9535 100644
--- a/Code/Sandbox/Editor/TrackView/TrackViewAnimNode.cpp
+++ b/Code/Sandbox/Editor/TrackView/TrackViewAnimNode.cpp
@@ -2012,9 +2012,9 @@ void CTrackViewAnimNode::SetPosRotScaleTracksDefaultValues(bool positionAllowed,
}
if (scaleAllowed)
{
- AZ::Vector3 scale = AZ::Vector3::CreateOne();
- AZ::TransformBus::EventResult(scale, entityId, &AZ::TransformBus::Events::GetWorldScale);
- m_animNode->SetScale(time, AZVec3ToLYVec3(scale));
+ float scale = 1.0f;
+ AZ::TransformBus::EventResult(scale, entityId, &AZ::TransformBus::Events::GetWorldUniformScale);
+ m_animNode->SetScale(time, Vec3(scale, scale, scale));
}
}
}
diff --git a/Code/Sandbox/Editor/TrackView/TrackViewSequence.cpp b/Code/Sandbox/Editor/TrackView/TrackViewSequence.cpp
index f915c804f8..d26c8fd973 100644
--- a/Code/Sandbox/Editor/TrackView/TrackViewSequence.cpp
+++ b/Code/Sandbox/Editor/TrackView/TrackViewSequence.cpp
@@ -828,7 +828,7 @@ void CTrackViewSequence::SyncSelectedTracksToBase()
const Vec3 scale = pAnimNode->GetScale();
AZ::Transform transform = AZ::Transform::CreateIdentity();
- transform.SetScale(LYVec3ToAZVec3(scale));
+ transform.SetUniformScale(LYVec3ToAZVec3(scale).GetMaxElement());
transform.SetRotation(LYQuaternionToAZQuaternion(rotation));
transform.SetTranslation(LYVec3ToAZVec3(position));
@@ -870,7 +870,7 @@ void CTrackViewSequence::SyncSelectedTracksFromBase()
pAnimNode->SetPos(AZVec3ToLYVec3(transform.GetTranslation()));
pAnimNode->SetRotation(AZQuaternionToLYQuaternion(transform.GetRotation()));
- pAnimNode->SetScale(AZVec3ToLYVec3(transform.GetScale()));
+ pAnimNode->SetScale(AZVec3ToLYVec3(AZ::Vector3(transform.GetUniformScale())));
bNothingWasSynced = false;
}
diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/CMakeLists.txt b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/CMakeLists.txt
index d02c656b8f..53e04e1dee 100644
--- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/CMakeLists.txt
+++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/CMakeLists.txt
@@ -35,10 +35,12 @@ ly_add_target(
AZ::AzToolsFramework
Legacy::CryCommon
Legacy::EditorLib
- Gem::LmbrCentral
AZ::AtomCore
Gem::Atom_RPI.Public
Gem::AtomToolsFramework.Static
+ Gem::LmbrCentral.Editor
+ RUNTIME_DEPENDENCIES
+ Gem::LmbrCentral.Editor
)
ly_add_dependencies(Editor ComponentEntityEditorPlugin)
@@ -68,7 +70,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
AZ::AzToolsFrameworkTestCommon
Legacy::CryCommon
Legacy::EditorLib
- Gem::LmbrCentral
+ Gem::LmbrCentral.Editor
+ RUNTIME_DEPENDENCIES
+ Gem::LmbrCentral.Editor
)
ly_add_googletest(
NAME Legacy::ComponentEntityEditorPlugin.Tests
diff --git a/Code/Tools/Android/ProjectBuilder/build.gradle.in b/Code/Tools/Android/ProjectBuilder/build.gradle.in
index 66f58294ab..5980984516 100644
--- a/Code/Tools/Android/ProjectBuilder/build.gradle.in
+++ b/Code/Tools/Android/ProjectBuilder/build.gradle.in
@@ -15,14 +15,14 @@ android {
${SIGNING_CONFIGS}
compileSdkVersion sdkVer
buildToolsVersion buildToolsVer
-
+ ndkVersion ndkPlatformVer
lintOptions {
abortOnError false
checkReleaseBuilds false
}
defaultConfig {
- minSdkVersion ndkPlatformVer
+ minSdkVersion minSdkVer
targetSdkVersion sdkVer
${NATIVE_CMAKE_SECTION_DEFAULT_CONFIG}
}
diff --git a/Code/Tools/Android/ProjectBuilder/local.properties.in b/Code/Tools/Android/ProjectBuilder/local.properties.in
index 559ea67bcb..4e82cb2940 100644
--- a/Code/Tools/Android/ProjectBuilder/local.properties.in
+++ b/Code/Tools/Android/ProjectBuilder/local.properties.in
@@ -16,6 +16,5 @@
# For customization when using a Version Control System, please read the
# header note.
# ${GENERATION_TIMESTAMP}
-ndk.dir=${ANDROID_NDK_PATH}
sdk.dir=${ANDROID_SDK_PATH}
${CMAKE_DIR_LINE}
diff --git a/Code/Tools/Android/ProjectBuilder/root.build.gradle.in b/Code/Tools/Android/ProjectBuilder/root.build.gradle.in
index 782a1f26b5..dfce99c3c7 100644
--- a/Code/Tools/Android/ProjectBuilder/root.build.gradle.in
+++ b/Code/Tools/Android/ProjectBuilder/root.build.gradle.in
@@ -12,10 +12,9 @@ buildscript {
repositories {
google()
jcenter()
-
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.6.4'
+ classpath 'com.android.tools.build:gradle:${ANDROID_GRADLE_PLUGIN_VERSION}'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -26,14 +25,14 @@ allprojects {
repositories {
google()
jcenter()
-
}
}
subprojects {
ext {
+ minSdkVer = ${MIN_SDK_VER}
sdkVer = ${SDK_VER}
- ndkPlatformVer = ${NDK_PLATFORM_VER}
+ ndkPlatformVer = '${NDK_VERSION}'
buildToolsVer = '${SDK_BUILD_TOOL_VER}'
lyEngineRoot = '${LY_ENGINE_ROOT}'
}
diff --git a/Code/Tools/AssetProcessor/native/ui/ProductAssetTreeModel.cpp b/Code/Tools/AssetProcessor/native/ui/ProductAssetTreeModel.cpp
index 5efef8166c..68ba64ea1a 100644
--- a/Code/Tools/AssetProcessor/native/ui/ProductAssetTreeModel.cpp
+++ b/Code/Tools/AssetProcessor/native/ui/ProductAssetTreeModel.cpp
@@ -14,6 +14,7 @@
#include "ProductAssetTreeItemData.h"
#include
+#include
#include
namespace AssetProcessor
@@ -159,31 +160,33 @@ namespace AssetProcessor
return;
}
+ AZ::IO::Path productNamePath(product.m_productName, AZ::IO::PosixPathSeparator);
- AZStd::vector tokens;
- AzFramework::StringFunc::Tokenize(product.m_productName.c_str(), tokens, AZ_CORRECT_DATABASE_SEPARATOR, false, true);
-
- if (tokens.empty())
+ if (productNamePath.empty())
{
AZ_Warning("AssetProcessor", false, "Product id %d has an invalid name: %s", product.m_productID, product.m_productName.c_str());
return;
}
AssetTreeItem* parentItem = m_root.get();
- AZStd::string fullFolderName;
- for (int i = 0; i < tokens.size() - 1; ++i)
+ AZ::IO::Path currentFullFolderPath;
+ const AZ::IO::PathView filename = productNamePath.Filename();
+ const AZ::IO::PathView fullPathWithoutFilename = productNamePath.RemoveFilename();
+ AZStd::fixed_string currentPath;
+ for (auto pathIt = fullPathWithoutFilename.begin(); pathIt != fullPathWithoutFilename.end(); ++pathIt)
{
- AzFramework::StringFunc::AssetDatabasePath::Join(fullFolderName.c_str(), tokens[i].c_str(), fullFolderName);
- AssetTreeItem* nextParent = parentItem->GetChildFolder(tokens[i].c_str());
+ currentPath = pathIt->FixedMaxPathString();
+ currentFullFolderPath /= currentPath;
+ AssetTreeItem* nextParent = parentItem->GetChildFolder(currentPath.c_str());
if (!nextParent)
{
if (!modelIsResetting)
{
- QModelIndex parentIndex = parentItem == m_root.get() ? QModelIndex() : createIndex(parentItem->GetRow(), 0, parentItem);
+ QModelIndex parentIndex = createIndex(parentItem->GetRow(), 0, parentItem);
beginInsertRows(parentIndex, parentItem->getChildCount(), parentItem->getChildCount());
}
- nextParent = parentItem->CreateChild(ProductAssetTreeItemData::MakeShared(nullptr, fullFolderName, tokens[i].c_str(), true, AZ::Uuid::CreateNull()));
- m_productToTreeItem[fullFolderName] = nextParent;
+ nextParent = parentItem->CreateChild(ProductAssetTreeItemData::MakeShared(nullptr, currentFullFolderPath.Native(), currentPath.c_str(), true, AZ::Uuid::CreateNull()));
+ m_productToTreeItem[currentFullFolderPath.Native()] = nextParent;
// m_productIdToTreeItem is not used for folders, folders don't have product IDs.
if (!modelIsResetting)
@@ -205,12 +208,12 @@ namespace AssetProcessor
if (!modelIsResetting)
{
- QModelIndex parentIndex = parentItem == m_root.get() ? QModelIndex() : createIndex(parentItem->GetRow(), 0, parentItem);
+ QModelIndex parentIndex = createIndex(parentItem->GetRow(), 0, parentItem);
beginInsertRows(parentIndex, parentItem->getChildCount(), parentItem->getChildCount());
}
AZStd::shared_ptr productItemData =
- ProductAssetTreeItemData::MakeShared(&product, product.m_productName, tokens[tokens.size() - 1].c_str(), false, sourceId);
+ ProductAssetTreeItemData::MakeShared(&product, product.m_productName, AZStd::fixed_string(filename.Native()).c_str(), false, sourceId);
m_productToTreeItem[product.m_productName] =
parentItem->CreateChild(productItemData);
m_productIdToTreeItem[product.m_productID] = m_productToTreeItem[product.m_productName];
diff --git a/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp b/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp
index dda0a58837..69e60f6733 100644
--- a/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp
+++ b/Code/Tools/AssetProcessor/native/ui/SourceAssetTreeModel.cpp
@@ -63,8 +63,7 @@ namespace AssetProcessor
}
- auto fullPath = AZ::IO::Path(scanFolder.m_scanFolder) / source.m_sourceName;
-
+ AZ::IO::Path fullPath = AZ::IO::Path(scanFolder.m_scanFolder, AZ::IO::PosixPathSeparator) / source.m_sourceName;
// It's common for Open 3D Engine game projects and scan folders to be in a subfolder
// of the engine install. To improve readability of the source files, strip out
@@ -78,34 +77,35 @@ namespace AssetProcessor
AzFramework::StringFunc::Replace(fullPath.Native(), m_assetRoot.absolutePath().toUtf8(), "");
}
-
- AZStd::vector tokens;
- AzFramework::StringFunc::Tokenize(fullPath.c_str(), tokens, AZ_CORRECT_DATABASE_SEPARATOR, false, true);
-
- if (tokens.empty())
+ if (fullPath.empty())
{
- AZ_Warning("AssetProcessor", false, "Source id %s has an invalid name: %s",
- source.m_sourceGuid.ToString().c_str(), source.m_sourceName.c_str());
+ AZ_Warning(
+ "AssetProcessor", false, "Source id %s has an invalid name: %s", source.m_sourceGuid.ToString().c_str(),
+ source.m_sourceName.c_str());
return;
}
QModelIndex newIndicesStart;
AssetTreeItem* parentItem = m_root.get();
- AZStd::string fullFolderName;
- for (int i = 0; i < tokens.size() - 1; ++i)
+ AZ::IO::Path currentFullFolderPath;
+ const AZ::IO::PathView filename = fullPath.Filename();
+ const AZ::IO::PathView fullPathWithoutFilename = fullPath.RemoveFilename();
+ AZStd::fixed_string currentPath;
+ for (auto pathIt = fullPathWithoutFilename.begin(); pathIt != fullPathWithoutFilename.end(); ++pathIt)
{
- AzFramework::StringFunc::AssetDatabasePath::Join(fullFolderName.c_str(), tokens[i].c_str(), fullFolderName);
- AssetTreeItem* nextParent = parentItem->GetChildFolder(tokens[i].c_str());
+ currentPath = pathIt->FixedMaxPathString();
+ currentFullFolderPath /= currentPath;
+ AssetTreeItem* nextParent = parentItem->GetChildFolder(currentPath.c_str());
if (!nextParent)
{
if (!modelIsResetting)
{
- QModelIndex parentIndex = parentItem == m_root.get() ? QModelIndex() : createIndex(parentItem->GetRow(), 0, parentItem);
+ QModelIndex parentIndex = createIndex(parentItem->GetRow(), 0, parentItem);
beginInsertRows(parentIndex, parentItem->getChildCount(), parentItem->getChildCount());
}
- nextParent = parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(nullptr, nullptr, fullFolderName, tokens[i].c_str(), true));
- m_sourceToTreeItem[fullFolderName] = nextParent;
+ nextParent = parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(nullptr, nullptr, currentFullFolderPath.Native(), currentPath.c_str(), true));
+ m_sourceToTreeItem[currentFullFolderPath.Native()] = nextParent;
// Folders don't have source IDs, don't add to m_sourceIdToTreeItem
if (!modelIsResetting)
{
@@ -117,12 +117,12 @@ namespace AssetProcessor
if (!modelIsResetting)
{
- QModelIndex parentIndex = parentItem == m_root.get() ? QModelIndex() : createIndex(parentItem->GetRow(), 0, parentItem);
+ QModelIndex parentIndex = createIndex(parentItem->GetRow(), 0, parentItem);
beginInsertRows(parentIndex, parentItem->getChildCount(), parentItem->getChildCount());
}
m_sourceToTreeItem[source.m_sourceName] =
- parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(&source, &scanFolder, source.m_sourceName, tokens[tokens.size() - 1].c_str(), false));
+ parentItem->CreateChild(SourceAssetTreeItemData::MakeShared(&source, &scanFolder, source.m_sourceName, AZStd::fixed_string(filename.Native()).c_str(), false));
m_sourceIdToTreeItem[source.m_sourceID] = m_sourceToTreeItem[source.m_sourceName];
if (!modelIsResetting)
{
diff --git a/Code/Tools/ProjectManager/CMakeLists.txt b/Code/Tools/ProjectManager/CMakeLists.txt
index e2b5aaf696..a655600325 100644
--- a/Code/Tools/ProjectManager/CMakeLists.txt
+++ b/Code/Tools/ProjectManager/CMakeLists.txt
@@ -37,11 +37,8 @@ ly_add_target(
PRIVATE
PY_PACKAGE="${python_package_name}"
INCLUDE_DIRECTORIES
- PUBLIC
- .
PRIVATE
Source
-
BUILD_DEPENDENCIES
PRIVATE
3rdParty::Qt::Core
diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss
index 5eb92964dd..a85b911c15 100644
--- a/Code/Tools/ProjectManager/Resources/ProjectManager.qss
+++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qss
@@ -336,4 +336,31 @@ QTabBar::tab:pressed
max-width:210px;;
min-height:278px;
max-height:278px;
-}
\ No newline at end of file
+}
+
+/************** Gem Catalog **************/
+
+#GemCatalogTitle {
+ font-size: 18px;
+}
+
+/************** Gem Catalog (Inspector) **************/
+
+#GemCatalogInspector {
+ background-color: #444444;
+}
+
+/************** Gem Catalog (Filter/left pane) **************/
+
+#GemCatalogFilterWidget {
+ background-color: #444444;
+}
+
+#GemCatalogHeaderWidget {
+ background-color: #1E252F;
+}
+
+#GemCatalogFilterCategoryTitle {
+ font-size: 12px;
+ font-weight: 600;
+}
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp
index 6e9ad42017..6402121e4a 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp
@@ -25,10 +25,12 @@ namespace O3DE::ProjectManager
hLayout->setMargin(0);
setLayout(hLayout);
- setStyleSheet("background-color: #1E252F;");
+ setObjectName("GemCatalogHeaderWidget");
+
+ hLayout->addSpacing(7);
QLabel* titleLabel = new QLabel(tr("Gem Catalog"));
- titleLabel->setStyleSheet("font-size: 21px;");
+ titleLabel->setObjectName("GemCatalogTitle");
hLayout->addWidget(titleLabel);
hLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
@@ -42,7 +44,7 @@ namespace O3DE::ProjectManager
hLayout->addWidget(filterLineEdit);
hLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
- hLayout->addSpacerItem(new QSpacerItem(220, 0, QSizePolicy::Fixed));
+ hLayout->addSpacerItem(new QSpacerItem(140, 0, QSizePolicy::Fixed));
setFixedHeight(60);
}
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp
index 3ece7760cf..a6a4e95ff9 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp
@@ -43,7 +43,6 @@ namespace O3DE::ProjectManager
m_collapseButton->setFlat(true);
m_collapseButton->setFocusPolicy(Qt::NoFocus);
m_collapseButton->setFixedWidth(s_collapseButtonSize);
- m_collapseButton->setStyleSheet("border: 0px; border-radius: 0px;");
connect(m_collapseButton, &QPushButton::clicked, this, [=]()
{
UpdateCollapseState();
@@ -52,7 +51,7 @@ namespace O3DE::ProjectManager
// Category title
QLabel* headerLabel = new QLabel(header);
- headerLabel->setStyleSheet("font-size: 11pt;");
+ headerLabel->setObjectName("GemCatalogFilterCategoryTitle");
collapseLayout->addWidget(headerLabel);
vLayout->addLayout(collapseLayout);
@@ -79,14 +78,14 @@ namespace O3DE::ProjectManager
elementWidget->setLayout(elementLayout);
QCheckBox* checkbox = new QCheckBox(elementNames[i]);
- checkbox->setStyleSheet("font-size: 11pt;");
+ checkbox->setStyleSheet("font-size: 12px;");
m_buttonGroup->addButton(checkbox);
elementLayout->addWidget(checkbox);
elementLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
QLabel* countLabel = new QLabel(QString::number(elementCounts[i]));
- countLabel->setStyleSheet("font-size: 11pt; background-color: #333333; border-radius: 3px; color: #94D2FF;");
+ countLabel->setStyleSheet("font-size: 12px; background-color: #333333; border-radius: 3px; color: #94D2FF;");
elementLayout->addWidget(countLabel);
m_elementWidgets.push_back(elementWidget);
@@ -110,6 +109,8 @@ namespace O3DE::ProjectManager
}
}
+ vLayout->addSpacing(5);
+
// Separating line
QFrame* hLine = new QFrame();
hLine->setFrameShape(QFrame::HLine);
@@ -181,6 +182,8 @@ namespace O3DE::ProjectManager
: QScrollArea(parent)
, m_filterProxyModel(filterProxyModel)
{
+ setObjectName("GemCatalogFilterWidget");
+
m_gemModel = m_filterProxyModel->GetSourceModel();
setWidgetResizable(true);
@@ -195,7 +198,7 @@ namespace O3DE::ProjectManager
mainWidget->setLayout(m_mainLayout);
QLabel* filterByLabel = new QLabel("Filter by");
- filterByLabel->setStyleSheet("font-size: 15pt;");
+ filterByLabel->setStyleSheet("font-size: 16px;");
m_mainLayout->addWidget(filterByLabel);
AddGemOriginFilter();
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.cpp
index 791085f47a..bc44928868 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.cpp
@@ -25,7 +25,7 @@ namespace O3DE::ProjectManager
bool GemInfo::IsValid() const
{
- return !m_path.isEmpty() && !m_uuid.IsNull();
+ return !m_name.isEmpty() && !m_path.isEmpty();
}
QString GemInfo::GetPlatformString(Platform platform)
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h
index 06b0adad32..1032ca5eaf 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h
@@ -64,7 +64,6 @@ namespace O3DE::ProjectManager
QString m_path;
QString m_name = "Unknown Gem Name";
QString m_displayName = "Unknown Gem Name";
- AZ::Uuid m_uuid;
QString m_creator = "Unknown Creator";
GemOrigin m_gemOrigin = Local;
bool m_isAdded = false; //! Is the gem currently added and enabled in the project?
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp
index 6276ddc996..3ecc18231e 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInspector.cpp
@@ -23,6 +23,7 @@ namespace O3DE::ProjectManager
: QScrollArea(parent)
, m_model(model)
{
+ setObjectName("GemCatalogInspector");
setWidgetResizable(true);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
@@ -85,7 +86,7 @@ namespace O3DE::ProjectManager
QLabel* GemInspector::CreateStyledLabel(QLayout* layout, int fontSize, const QString& colorCodeString)
{
QLabel* result = new QLabel();
- result->setStyleSheet(QString("font-size: %1pt; color: %2;").arg(QString::number(fontSize), colorCodeString));
+ result->setStyleSheet(QString("font-size: %1px; color: %2;").arg(QString::number(fontSize), colorCodeString));
layout->addWidget(result);
return result;
}
@@ -93,13 +94,13 @@ namespace O3DE::ProjectManager
void GemInspector::InitMainWidget()
{
// Gem name, creator and summary
- m_nameLabel = CreateStyledLabel(m_mainLayout, 17, s_headerColor);
+ m_nameLabel = CreateStyledLabel(m_mainLayout, 18, s_headerColor);
m_creatorLabel = CreateStyledLabel(m_mainLayout, 12, s_creatorColor);
m_mainLayout->addSpacing(5);
// TODO: QLabel seems to have issues determining the right sizeHint() for our font with the given font size.
// This results into squeezed elements in the layout in case the text is a little longer than a sentence.
- m_summaryLabel = new QLabel();//CreateLabel(m_mainLayout, 12, s_textColor);
+ m_summaryLabel = CreateStyledLabel(m_mainLayout, 12, s_textColor);
m_mainLayout->addWidget(m_summaryLabel);
m_summaryLabel->setWordWrap(true);
m_mainLayout->addSpacing(5);
@@ -146,9 +147,9 @@ namespace O3DE::ProjectManager
QLabel* additionalInfoLabel = CreateStyledLabel(m_mainLayout, 14, s_headerColor);
additionalInfoLabel->setText("Additional Information");
- m_versionLabel = CreateStyledLabel(m_mainLayout, 11, s_textColor);
- m_lastUpdatedLabel = CreateStyledLabel(m_mainLayout, 11, s_textColor);
- m_binarySizeLabel = CreateStyledLabel(m_mainLayout, 11, s_textColor);
+ m_versionLabel = CreateStyledLabel(m_mainLayout, 12, s_textColor);
+ m_lastUpdatedLabel = CreateStyledLabel(m_mainLayout, 12, s_textColor);
+ m_binarySizeLabel = CreateStyledLabel(m_mainLayout, 12, s_textColor);
}
GemInspector::GemsSubWidget::GemsSubWidget(QWidget* parent)
@@ -159,8 +160,8 @@ namespace O3DE::ProjectManager
m_layout->setMargin(0);
setLayout(m_layout);
- m_titleLabel = GemInspector::CreateStyledLabel(m_layout, 15, s_headerColor);
- m_textLabel = GemInspector::CreateStyledLabel(m_layout, 9, s_textColor);
+ m_titleLabel = GemInspector::CreateStyledLabel(m_layout, 16, s_headerColor);
+ m_textLabel = GemInspector::CreateStyledLabel(m_layout, 10, s_textColor);
m_textLabel->setWordWrap(true);
m_tagWidget = new TagContainerWidget();
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp
index a40e5eb447..57200e3b36 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp
@@ -49,7 +49,7 @@ namespace O3DE::ProjectManager
painter->setRenderHint(QPainter::Antialiasing);
QRect fullRect, itemRect, contentRect;
- CalcRects(options, modelIndex, fullRect, itemRect, contentRect);
+ CalcRects(options, fullRect, itemRect, contentRect);
QFont standardFont(options.font);
standardFont.setPixelSize(s_fontSize);
@@ -99,7 +99,7 @@ namespace O3DE::ProjectManager
painter->drawText(gemCreatorRect, Qt::TextSingleLine, gemCreator);
// Gem summary
- const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - s_itemMargins.right() * 4, contentRect.height());
+ const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - s_itemMargins.right() * 3, contentRect.height());
const QRect summaryRect = QRect(/*topLeft=*/QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), summarySize);
painter->setFont(standardFont);
@@ -134,12 +134,10 @@ namespace O3DE::ProjectManager
return QStyledItemDelegate::editorEvent(event, model, option, modelIndex);
}
- void GemItemDelegate::CalcRects(const QStyleOptionViewItem& option, const QModelIndex& modelIndex, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const
+ void GemItemDelegate::CalcRects(const QStyleOptionViewItem& option, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const
{
- const bool isFirst = modelIndex.row() == 0;
-
outFullRect = QRect(option.rect);
- outItemRect = QRect(outFullRect.adjusted(s_itemMargins.left(), isFirst ? s_itemMargins.top() * 2 : s_itemMargins.top(), -s_itemMargins.right(), -s_itemMargins.bottom()));
+ outItemRect = QRect(outFullRect.adjusted(s_itemMargins.left(), s_itemMargins.top(), -s_itemMargins.right(), -s_itemMargins.bottom()));
outContentRect = QRect(outItemRect.adjusted(s_contentMargins.left(), s_contentMargins.top(), -s_contentMargins.right(), -s_contentMargins.bottom()));
}
@@ -194,12 +192,12 @@ namespace O3DE::ProjectManager
painter->setBrush(m_buttonEnabledColor);
painter->setPen(m_buttonEnabledColor);
- circleCenter = buttonRect.center() + QPoint(buttonRect.width() / 2 - s_buttonBorderRadius, 1);
+ circleCenter = buttonRect.center() + QPoint(buttonRect.width() / 2 - s_buttonBorderRadius + 1, 1);
buttonText = "Added";
}
else
{
- circleCenter = buttonRect.center() + QPoint(-buttonRect.width() / 2 + s_buttonBorderRadius + 1, 1);
+ circleCenter = buttonRect.center() + QPoint(-buttonRect.width() / 2 + s_buttonBorderRadius, 1);
buttonText = "Get";
}
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h
index d43b5d15f6..48f173ec3f 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h
@@ -45,25 +45,25 @@ namespace O3DE::ProjectManager
const QColor m_buttonEnabledColor = QColor("#00B931");
// Item
- inline constexpr static int s_height = 135; // Gem item total height
- inline constexpr static qreal s_gemNameFontSize = 16.0;
- inline constexpr static qreal s_fontSize = 15.0;
- inline constexpr static int s_summaryStartX = 200;
+ inline constexpr static int s_height = 105; // Gem item total height
+ inline constexpr static qreal s_gemNameFontSize = 13.0;
+ inline constexpr static qreal s_fontSize = 12.0;
+ inline constexpr static int s_summaryStartX = 150;
// Margin and borders
- inline constexpr static QMargins s_itemMargins = QMargins(/*left=*/20, /*top=*/10, /*right=*/20, /*bottom=*/10); // Item border distances
- inline constexpr static QMargins s_contentMargins = QMargins(/*left=*/15, /*top=*/12, /*right=*/12, /*bottom=*/12); // Distances of the elements within an item to the item borders
+ inline constexpr static QMargins s_itemMargins = QMargins(/*left=*/16, /*top=*/8, /*right=*/16, /*bottom=*/8); // Item border distances
+ inline constexpr static QMargins s_contentMargins = QMargins(/*left=*/20, /*top=*/12, /*right=*/15, /*bottom=*/12); // Distances of the elements within an item to the item borders
inline constexpr static int s_borderWidth = 4;
// Button
- inline constexpr static int s_buttonWidth = 70;
- inline constexpr static int s_buttonHeight = 24;
- inline constexpr static int s_buttonBorderRadius = 12;
- inline constexpr static int s_buttonCircleRadius = s_buttonBorderRadius - 3;
- inline constexpr static qreal s_buttonFontSize = 12.0;
+ inline constexpr static int s_buttonWidth = 55;
+ inline constexpr static int s_buttonHeight = 18;
+ inline constexpr static int s_buttonBorderRadius = 9;
+ inline constexpr static int s_buttonCircleRadius = s_buttonBorderRadius - 2;
+ inline constexpr static qreal s_buttonFontSize = 10.0;
private:
- void CalcRects(const QStyleOptionViewItem& option, const QModelIndex& modelIndex, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const;
+ void CalcRects(const QStyleOptionViewItem& option, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const;
QRect GetTextRect(QFont& font, const QString& text, qreal fontSize) const;
QRect CalcButtonRect(const QRect& contentRect) const;
void DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
@@ -73,7 +73,7 @@ namespace O3DE::ProjectManager
// Platform icons
void AddPlatformIcon(GemInfo::Platform platform, const QString& iconPath);
- inline constexpr static int s_platformIconSize = 16;
+ inline constexpr static int s_platformIconSize = 12;
QHash m_platformIcons;
};
} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp
index 128fb93345..bc287e3c61 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp
@@ -35,7 +35,7 @@ namespace O3DE::ProjectManager
topLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
QLabel* showCountLabel = new QLabel();
- showCountLabel->setStyleSheet("font-size: 11pt; font: italic;");
+ showCountLabel->setStyleSheet("font-size: 12px; font: italic;");
topLayout->addWidget(showCountLabel);
connect(proxyModel, &GemSortFilterProxyModel::OnInvalidated, this, [=]
{
@@ -61,16 +61,17 @@ namespace O3DE::ProjectManager
QHBoxLayout* columnHeaderLayout = new QHBoxLayout();
columnHeaderLayout->setAlignment(Qt::AlignLeft);
- columnHeaderLayout->addSpacing(31);
+ const int gemNameStartX = GemItemDelegate::s_itemMargins.left() + GemItemDelegate::s_contentMargins.left() - 3;
+ columnHeaderLayout->addSpacing(gemNameStartX);
QLabel* gemNameLabel = new QLabel(tr("Gem Name"));
- gemNameLabel->setStyleSheet("font-size: 11pt;");
+ gemNameLabel->setStyleSheet("font-size: 12px;");
columnHeaderLayout->addWidget(gemNameLabel);
- columnHeaderLayout->addSpacing(111);
+ columnHeaderLayout->addSpacing(77);
QLabel* gemSummaryLabel = new QLabel(tr("Gem Summary"));
- gemSummaryLabel->setStyleSheet("font-size: 11pt;");
+ gemSummaryLabel->setStyleSheet("font-size: 12px;");
columnHeaderLayout->addWidget(gemSummaryLabel);
vLayout->addLayout(columnHeaderLayout);
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp
index 724a8fa630..df11c4c7a6 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp
@@ -33,8 +33,6 @@ namespace O3DE::ProjectManager
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
item->setData(gemInfo.m_name, RoleName);
- const QString uuidString = gemInfo.m_uuid.ToString().c_str();
- item->setData(uuidString, RoleUuid);
item->setData(gemInfo.m_creator, RoleCreator);
item->setData(gemInfo.m_gemOrigin, RoleGemOrigin);
item->setData(aznumeric_cast(gemInfo.m_platforms), RolePlatforms);
@@ -53,7 +51,7 @@ namespace O3DE::ProjectManager
appendRow(item);
const QModelIndex modelIndex = index(rowCount()-1, 0);
- m_uuidToIndexMap[uuidString] = modelIndex;
+ m_nameToIndexMap[gemInfo.m_name] = modelIndex;
}
void GemModel::Clear()
@@ -76,11 +74,6 @@ namespace O3DE::ProjectManager
return static_cast(modelIndex.data(RoleGemOrigin).toInt());
}
- QString GemModel::GetUuidString(const QModelIndex& modelIndex)
- {
- return modelIndex.data(RoleUuid).toString();
- }
-
GemInfo::Platforms GemModel::GetPlatforms(const QModelIndex& modelIndex)
{
return static_cast(modelIndex.data(RolePlatforms).toInt());
@@ -111,10 +104,10 @@ namespace O3DE::ProjectManager
return modelIndex.data(RoleDocLink).toString();
}
- QModelIndex GemModel::FindIndexByUuidString(const QString& uuidString) const
+ QModelIndex GemModel::FindIndexByNameString(const QString& nameString) const
{
- const auto iterator = m_uuidToIndexMap.find(uuidString);
- if (iterator != m_uuidToIndexMap.end())
+ const auto iterator = m_nameToIndexMap.find(nameString);
+ if (iterator != m_nameToIndexMap.end())
{
return iterator.value();
}
@@ -122,11 +115,11 @@ namespace O3DE::ProjectManager
return {};
}
- void GemModel::FindGemNamesByUuidStrings(QStringList& inOutGemNames)
+ void GemModel::FindGemNamesByNameStrings(QStringList& inOutGemNames)
{
for (QString& dependingGemString : inOutGemNames)
{
- QModelIndex modelIndex = FindIndexByUuidString(dependingGemString);
+ QModelIndex modelIndex = FindIndexByNameString(dependingGemString);
if (modelIndex.isValid())
{
dependingGemString = GetName(modelIndex);
@@ -147,7 +140,7 @@ namespace O3DE::ProjectManager
return {};
}
- FindGemNamesByUuidStrings(result);
+ FindGemNamesByNameStrings(result);
return result;
}
@@ -164,7 +157,7 @@ namespace O3DE::ProjectManager
return {};
}
- FindGemNamesByUuidStrings(result);
+ FindGemNamesByNameStrings(result);
return result;
}
diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h
index 480f4c74d3..0caa399b58 100644
--- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h
+++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h
@@ -33,8 +33,8 @@ namespace O3DE::ProjectManager
void AddGem(const GemInfo& gemInfo);
void Clear();
- QModelIndex FindIndexByUuidString(const QString& uuidString) const;
- void FindGemNamesByUuidStrings(QStringList& inOutGemNames);
+ QModelIndex FindIndexByNameString(const QString& nameString) const;
+ void FindGemNamesByNameStrings(QStringList& inOutGemNames);
QStringList GetDependingGemUuids(const QModelIndex& modelIndex);
QStringList GetDependingGemNames(const QModelIndex& modelIndex);
QStringList GetConflictingGemUuids(const QModelIndex& modelIndex);
@@ -43,7 +43,6 @@ namespace O3DE::ProjectManager
static QString GetName(const QModelIndex& modelIndex);
static QString GetCreator(const QModelIndex& modelIndex);
static GemInfo::GemOrigin GetGemOrigin(const QModelIndex& modelIndex);
- static QString GetUuidString(const QModelIndex& modelIndex);
static GemInfo::Platforms GetPlatforms(const QModelIndex& modelIndex);
static GemInfo::Types GetTypes(const QModelIndex& modelIndex);
static QString GetSummary(const QModelIndex& modelIndex);
@@ -59,7 +58,6 @@ namespace O3DE::ProjectManager
enum UserRole
{
RoleName = Qt::UserRole,
- RoleUuid,
RoleCreator,
RoleGemOrigin,
RolePlatforms,
@@ -76,7 +74,7 @@ namespace O3DE::ProjectManager
RoleTypes
};
- QHash m_uuidToIndexMap;
+ QHash m_nameToIndexMap;
QItemSelectionModel* m_selectionModel = nullptr;
};
} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Source/LinkWidget.cpp b/Code/Tools/ProjectManager/Source/LinkWidget.cpp
index a6308f6c62..160d9cf7c7 100644
--- a/Code/Tools/ProjectManager/Source/LinkWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/LinkWidget.cpp
@@ -37,7 +37,7 @@ namespace O3DE::ProjectManager
void LinkLabel::enterEvent([[maybe_unused]] QEvent* event)
{
- setStyleSheet("font-size: 9pt; color: #94D2FF; text-decoration: underline;");
+ setStyleSheet("font-size: 10px; color: #94D2FF; text-decoration: underline;");
}
void LinkLabel::leaveEvent([[maybe_unused]] QEvent* event)
@@ -52,6 +52,6 @@ namespace O3DE::ProjectManager
void LinkLabel::SetDefaultStyle()
{
- setStyleSheet("font-size: 9pt; color: #94D2FF;");
+ setStyleSheet("font-size: 10px; color: #94D2FF;");
}
} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp
index 4be876e79f..72ffa686c1 100644
--- a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp
+++ b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.cpp
@@ -12,6 +12,7 @@
#include
+
#include
#include
#include
@@ -58,19 +59,15 @@ namespace O3DE::ProjectManager
m_overlayLabel->setText(text);
}
- ProjectButton::ProjectButton(const QString& projectName, QWidget* parent)
+ ProjectButton::ProjectButton(const ProjectInfo& projectInfo, QWidget* parent)
: QFrame(parent)
- , m_projectName(projectName)
- , m_projectImagePath(":/Resources/DefaultProjectImage.png")
+ , m_projectInfo(projectInfo)
{
- Setup();
- }
+ if (m_projectInfo.m_imagePath.isEmpty())
+ {
+ m_projectInfo.m_imagePath = ":/DefaultProjectImage.png";
+ }
- ProjectButton::ProjectButton(const QString& projectName, const QString& projectImage, QWidget* parent)
- : QFrame(parent)
- , m_projectName(projectName)
- , m_projectImagePath(projectImage)
- {
Setup();
}
@@ -85,20 +82,22 @@ namespace O3DE::ProjectManager
m_projectImageLabel = new LabelButton(this);
m_projectImageLabel->setFixedSize(s_projectImageWidth, s_projectImageHeight);
+ m_projectImageLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
vLayout->addWidget(m_projectImageLabel);
- m_projectImageLabel->setPixmap(QPixmap(m_projectImagePath).scaled(m_projectImageLabel->size(), Qt::KeepAspectRatioByExpanding));
+ m_projectImageLabel->setPixmap(
+ QPixmap(m_projectInfo.m_imagePath).scaled(m_projectImageLabel->size(), Qt::KeepAspectRatioByExpanding));
QMenu* newProjectMenu = new QMenu(this);
m_editProjectAction = newProjectMenu->addAction(tr("Edit Project Settings..."));
-
-#ifdef SHOW_ALL_PROJECT_ACTIONS
- m_editProjectGemsAction = newProjectMenu->addAction(tr("Cutomize Gems..."));
newProjectMenu->addSeparator();
m_copyProjectAction = newProjectMenu->addAction(tr("Duplicate"));
newProjectMenu->addSeparator();
m_removeProjectAction = newProjectMenu->addAction(tr("Remove from O3DE"));
- m_deleteProjectAction = newProjectMenu->addAction(tr("Delete the Project"));
+ m_deleteProjectAction = newProjectMenu->addAction(tr("Delete this Project"));
+
+#ifdef SHOW_ALL_PROJECT_ACTIONS
+ m_editProjectGemsAction = newProjectMenu->addAction(tr("Cutomize Gems..."));
#endif
QFrame* footer = new QFrame(this);
@@ -106,7 +105,7 @@ namespace O3DE::ProjectManager
hLayout->setContentsMargins(0, 0, 0, 0);
footer->setLayout(hLayout);
{
- QLabel* projectNameLabel = new QLabel(m_projectName, this);
+ QLabel* projectNameLabel = new QLabel(m_projectInfo.m_displayName, this);
hLayout->addWidget(projectNameLabel);
QPushButton* projectMenuButton = new QPushButton(this);
@@ -117,14 +116,14 @@ namespace O3DE::ProjectManager
vLayout->addWidget(footer);
- connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectName); });
- connect(m_editProjectAction, &QAction::triggered, [this]() { emit EditProject(m_projectName); });
+ connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectInfo.m_path); });
+ connect(m_editProjectAction, &QAction::triggered, [this]() { emit EditProject(m_projectInfo.m_path); });
+ connect(m_copyProjectAction, &QAction::triggered, [this]() { emit CopyProject(m_projectInfo.m_path); });
+ connect(m_removeProjectAction, &QAction::triggered, [this]() { emit RemoveProject(m_projectInfo.m_path); });
+ connect(m_deleteProjectAction, &QAction::triggered, [this]() { emit DeleteProject(m_projectInfo.m_path); });
#ifdef SHOW_ALL_PROJECT_ACTIONS
- connect(m_editProjectGemsAction, &QAction::triggered, [this]() { emit EditProjectGems(m_projectName); });
- connect(m_copyProjectAction, &QAction::triggered, [this]() { emit CopyProject(m_projectName); });
- connect(m_removeProjectAction, &QAction::triggered, [this]() { emit RemoveProject(m_projectName); });
- connect(m_deleteProjectAction, &QAction::triggered, [this]() { emit DeleteProject(m_projectName); });
+ connect(m_editProjectGemsAction, &QAction::triggered, [this]() { emit EditProjectGems(m_projectInfo.m_path); });
#endif
}
diff --git a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h
index 671debf6d0..e82b56b3fa 100644
--- a/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h
+++ b/Code/Tools/ProjectManager/Source/ProjectButtonWidget.h
@@ -13,7 +13,8 @@
#pragma once
#if !defined(Q_MOC_RUN)
-#include
+#include
+
#include
#endif
@@ -52,8 +53,7 @@ namespace O3DE::ProjectManager
Q_OBJECT // AUTOMOC
public:
- explicit ProjectButton(const QString& projectName, QWidget* parent = nullptr);
- explicit ProjectButton(const QString& projectName, const QString& projectImage, QWidget* parent = nullptr);
+ explicit ProjectButton(const ProjectInfo& m_projectInfo, QWidget* parent = nullptr);
~ProjectButton() = default;
void SetButtonEnabled(bool enabled);
@@ -70,8 +70,7 @@ namespace O3DE::ProjectManager
private:
void Setup();
- QString m_projectName;
- QString m_projectImagePath;
+ ProjectInfo m_projectInfo;
LabelButton* m_projectImageLabel;
QAction* m_editProjectAction;
QAction* m_editProjectGemsAction;
diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp
new file mode 100644
index 0000000000..526e745d82
--- /dev/null
+++ b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp
@@ -0,0 +1,196 @@
+/*
+ * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+ * its licensors.
+ *
+ * For complete copyright and license terms please see the LICENSE at the root of this
+ * distribution (the "License"). All use of this software is governed by the License,
+ * or, if provided, by the license below or the license accompanying this file. Do not
+ * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+namespace O3DE::ProjectManager
+{
+ namespace ProjectUtils
+ {
+ static bool WarnDirectoryOverwrite(const QString& path, QWidget* parent)
+ {
+ if (!QDir(path).isEmpty())
+ {
+ QMessageBox::StandardButton warningResult = QMessageBox::warning(
+ parent,
+ QObject::tr("Overwrite Directory"),
+ QObject::tr("Directory is not empty! Are you sure you want to overwrite it?"),
+ QMessageBox::No | QMessageBox::Yes
+ );
+
+ if (warningResult != QMessageBox::Yes)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ static bool IsDirectoryDescedent(const QString& possibleAncestorPath, const QString& possibleDecedentPath)
+ {
+ QDir ancestor(possibleAncestorPath);
+ QDir descendent(possibleDecedentPath);
+
+ do
+ {
+ if (ancestor == descendent)
+ {
+ return false;
+ }
+
+ descendent.cdUp();
+ }
+ while (!descendent.isRoot());
+
+ return true;
+ }
+
+ static bool CopyDirectory(const QString& origPath, const QString& newPath)
+ {
+ QDir original(origPath);
+ if (!original.exists())
+ {
+ return false;
+ }
+
+ for (QString directory : original.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
+ {
+ QString newDirectoryPath = newPath + QDir::separator() + directory;
+ original.mkpath(newDirectoryPath);
+
+ if (!CopyDirectory(origPath + QDir::separator() + directory, newDirectoryPath))
+ {
+ return false;
+ }
+ }
+
+ for (QString file : original.entryList(QDir::Files))
+ {
+ if (!QFile::copy(origPath + QDir::separator() + file, newPath + QDir::separator() + file))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool AddProjectDialog(QWidget* parent)
+ {
+ QString path = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(parent, QObject::tr("Select Project Directory")));
+ if (!path.isEmpty())
+ {
+ return RegisterProject(path);
+ }
+
+ return false;
+ }
+
+ bool RegisterProject(const QString& path)
+ {
+ return PythonBindingsInterface::Get()->AddProject(path);
+ }
+
+ bool UnregisterProject(const QString& path)
+ {
+ return PythonBindingsInterface::Get()->RemoveProject(path);
+ }
+
+ bool CopyProjectDialog(const QString& origPath, QWidget* parent)
+ {
+ bool copyResult = false;
+
+ QDir parentOrigDir(origPath);
+ parentOrigDir.cdUp();
+ QString newPath = QDir::toNativeSeparators(
+ QFileDialog::getExistingDirectory(parent, QObject::tr("Select New Project Directory"), parentOrigDir.path()));
+ if (!newPath.isEmpty())
+ {
+ if (!WarnDirectoryOverwrite(newPath, parent))
+ {
+ return false;
+ }
+
+ // TODO: Block UX and Notify User they need to wait
+
+ copyResult = CopyProject(origPath, newPath);
+ }
+
+ return copyResult;
+ }
+
+ bool CopyProject(const QString& origPath, const QString& newPath)
+ {
+ // Disallow copying from or into subdirectory
+ if (!IsDirectoryDescedent(origPath, newPath) || !IsDirectoryDescedent(newPath, origPath))
+ {
+ return false;
+ }
+
+ if (!CopyDirectory(origPath, newPath))
+ {
+ // Cleanup whatever mess was made
+ DeleteProjectFiles(newPath, true);
+ return false;
+ }
+
+ if (!RegisterProject(newPath))
+ {
+ DeleteProjectFiles(newPath, true);
+ }
+
+ return true;
+ }
+
+ bool DeleteProjectFiles(const QString& path, bool force)
+ {
+ QDir projectDirectory(path);
+ if (projectDirectory.exists())
+ {
+ // Check if there is an actual project hereor just force it
+ if (force || PythonBindingsInterface::Get()->GetProject(path).IsSuccess())
+ {
+ return projectDirectory.removeRecursively();
+ }
+ }
+
+ return false;
+ }
+
+ bool MoveProject(const QString& origPath, const QString& newPath, QWidget* parent)
+ {
+ if (!WarnDirectoryOverwrite(newPath, parent) || !UnregisterProject(origPath))
+ {
+ return false;
+ }
+
+ QDir directory;
+ if (directory.rename(origPath, newPath))
+ {
+ return directory.rename(origPath, newPath);
+ }
+
+ if (!RegisterProject(newPath))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ } // namespace ProjectUtils
+} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.h b/Code/Tools/ProjectManager/Source/ProjectUtils.h
new file mode 100644
index 0000000000..5982bff634
--- /dev/null
+++ b/Code/Tools/ProjectManager/Source/ProjectUtils.h
@@ -0,0 +1,28 @@
+/*
+ * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+ * its licensors.
+ *
+ * For complete copyright and license terms please see the LICENSE at the root of this
+ * distribution (the "License"). All use of this software is governed by the License,
+ * or, if provided, by the license below or the license accompanying this file. Do not
+ * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ */
+#pragma once
+
+#include
+
+namespace O3DE::ProjectManager
+{
+ namespace ProjectUtils
+ {
+ bool AddProjectDialog(QWidget* parent = nullptr);
+ bool RegisterProject(const QString& path);
+ bool UnregisterProject(const QString& path);
+ bool CopyProjectDialog(const QString& origPath, QWidget* parent = nullptr);
+ bool CopyProject(const QString& origPath, const QString& newPath);
+ bool DeleteProjectFiles(const QString& path, bool force = false);
+ bool MoveProject(const QString& origPath, const QString& newPath, QWidget* parent = nullptr);
+ } // namespace ProjectUtils
+} // namespace O3DE::ProjectManager
diff --git a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp
index 5f1c0e2b36..dd2e411ec5 100644
--- a/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp
+++ b/Code/Tools/ProjectManager/Source/ProjectsScreen.cpp
@@ -14,6 +14,7 @@
#include
#include
+#include
#include
#include
@@ -65,9 +66,6 @@ namespace O3DE::ProjectManager
m_stack->addWidget(m_projectsContent);
vLayout->addWidget(m_stack);
-
- connect(m_createNewProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleNewProjectButton);
- connect(m_addExistingProjectAction, &QAction::triggered, this, &ProjectsScreen::HandleAddProjectButton);
}
QFrame* ProjectsScreen::CreateFirstTimeContent()
@@ -167,28 +165,27 @@ namespace O3DE::ProjectManager
#endif
{
ProjectButton* projectButton;
+
QString projectPreviewPath = project.m_path + m_projectPreviewImagePath;
QFileInfo doesPreviewExist(projectPreviewPath);
if (doesPreviewExist.exists() && doesPreviewExist.isFile())
{
- projectButton = new ProjectButton(project.m_projectName, projectPreviewPath, this);
- }
- else
- {
- projectButton = new ProjectButton(project.m_projectName, this);
+ project.m_imagePath = projectPreviewPath;
}
+ projectButton = new ProjectButton(project, this);
+
flowLayout->addWidget(projectButton);
connect(projectButton, &ProjectButton::OpenProject, this, &ProjectsScreen::HandleOpenProject);
connect(projectButton, &ProjectButton::EditProject, this, &ProjectsScreen::HandleEditProject);
-
- #ifdef DISPLAY_PROJECT_DEV_DATA
- connect(projectButton, &ProjectButton::EditProjectGems, this, &ProjectsScreen::HandleEditProjectGems);
connect(projectButton, &ProjectButton::CopyProject, this, &ProjectsScreen::HandleCopyProject);
connect(projectButton, &ProjectButton::RemoveProject, this, &ProjectsScreen::HandleRemoveProject);
connect(projectButton, &ProjectButton::DeleteProject, this, &ProjectsScreen::HandleDeleteProject);
- #endif
+
+#ifdef SHOW_ALL_PROJECT_ACTIONS
+ connect(projectButton, &ProjectButton::EditProjectGems, this, &ProjectsScreen::HandleEditProjectGems);
+#endif
}
layout->addWidget(projectsScrollArea);
@@ -242,7 +239,11 @@ namespace O3DE::ProjectManager
}
void ProjectsScreen::HandleAddProjectButton()
{
- // Do nothing for now
+ if (ProjectUtils::AddProjectDialog(this))
+ {
+ emit ResetScreenRequest(ProjectManagerScreen::Projects);
+ emit ChangeScreenRequest(ProjectManagerScreen::Projects);
+ }
}
void ProjectsScreen::HandleOpenProject(const QString& projectPath)
{
@@ -300,18 +301,36 @@ namespace O3DE::ProjectManager
emit NotifyCurrentProject(projectPath);
emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog);
}
- void ProjectsScreen::HandleCopyProject([[maybe_unused]] const QString& projectPath)
+ void ProjectsScreen::HandleCopyProject(const QString& projectPath)
{
// Open file dialog and choose location for copied project then register copy with O3DE
+ if (ProjectUtils::CopyProjectDialog(projectPath, this))
+ {
+ emit ResetScreenRequest(ProjectManagerScreen::Projects);
+ emit ChangeScreenRequest(ProjectManagerScreen::Projects);
+ }
}
- void ProjectsScreen::HandleRemoveProject([[maybe_unused]] const QString& projectPath)
+ void ProjectsScreen::HandleRemoveProject(const QString& projectPath)
{
- // Unregister Project from O3DE
+ // Unregister Project from O3DE and reload projects
+ if (ProjectUtils::UnregisterProject(projectPath))
+ {
+ emit ResetScreenRequest(ProjectManagerScreen::Projects);
+ emit ChangeScreenRequest(ProjectManagerScreen::Projects);
+ }
}
- void ProjectsScreen::HandleDeleteProject([[maybe_unused]] const QString& projectPath)
+ void ProjectsScreen::HandleDeleteProject(const QString& projectPath)
{
- // Remove project from 03DE and delete from disk
- ProjectsScreen::HandleRemoveProject(projectPath);
+ QMessageBox::StandardButton warningResult = QMessageBox::warning(
+ this, tr("Delete Project"), tr("Are you sure?\nProject will be removed from O3DE and directory will be deleted!"),
+ QMessageBox::No | QMessageBox::Yes);
+
+ if (warningResult == QMessageBox::Yes)
+ {
+ // Remove project from O3DE and delete from disk
+ HandleRemoveProject(projectPath);
+ ProjectUtils::DeleteProjectFiles(projectPath);
+ }
}
void ProjectsScreen::NotifyCurrentScreen()
diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp
index 8c79a153c8..8db8492cae 100644
--- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp
+++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp
@@ -220,7 +220,7 @@ namespace RedirectOutput
}
} // namespace RedirectOutput
-namespace O3DE::ProjectManager
+namespace O3DE::ProjectManager
{
PythonBindings::PythonBindings(const AZ::IO::PathView& enginePath)
: m_enginePath(enginePath)
@@ -283,8 +283,11 @@ namespace O3DE::ProjectManager
AZ_Warning("ProjectManagerWindow", result != -1, "Append to sys path failed");
// import required modules
- m_registration = pybind11::module::import("cmake.Tools.registration");
- m_engineTemplate = pybind11::module::import("cmake.Tools.engine_template");
+ m_register = pybind11::module::import("o3de.register");
+ m_manifest = pybind11::module::import("o3de.manifest");
+ m_engineTemplate = pybind11::module::import("o3de.engine_template");
+ m_enableGemProject = pybind11::module::import("o3de.enable_gem");
+ m_disableGemProject = pybind11::module::import("o3de.disable_gem");
return result == 0 && !PyErr_Occurred();
} catch ([[maybe_unused]] const std::exception& e)
@@ -326,30 +329,30 @@ namespace O3DE::ProjectManager
}
}
- AZ::Outcome PythonBindings::GetEngineInfo()
+ AZ::Outcome PythonBindings::GetEngineInfo()
{
EngineInfo engineInfo;
bool result = ExecuteWithLock([&] {
- pybind11::str enginePath = m_registration.attr("get_this_engine_path")();
+ pybind11::str enginePath = m_manifest.attr("get_this_engine_path")();
- auto o3deData = m_registration.attr("load_o3de_manifest")();
+ auto o3deData = m_manifest.attr("load_o3de_manifest")();
if (pybind11::isinstance(o3deData))
{
- engineInfo.m_path = Py_To_String(enginePath);
- engineInfo.m_defaultGemsFolder = Py_To_String(o3deData["default_gems_folder"]);
- engineInfo.m_defaultProjectsFolder = Py_To_String(o3deData["default_projects_folder"]);
- engineInfo.m_defaultRestrictedFolder = Py_To_String(o3deData["default_restricted_folder"]);
- engineInfo.m_defaultTemplatesFolder = Py_To_String(o3deData["default_templates_folder"]);
- engineInfo.m_thirdPartyPath = Py_To_String_Optional(o3deData,"third_party_path","");
+ engineInfo.m_path = Py_To_String(enginePath);
+ engineInfo.m_defaultGemsFolder = Py_To_String(o3deData["default_gems_folder"]);
+ engineInfo.m_defaultProjectsFolder = Py_To_String(o3deData["default_projects_folder"]);
+ engineInfo.m_defaultRestrictedFolder = Py_To_String(o3deData["default_restricted_folder"]);
+ engineInfo.m_defaultTemplatesFolder = Py_To_String(o3deData["default_templates_folder"]);
+ engineInfo.m_thirdPartyPath = Py_To_String_Optional(o3deData,"third_party_path","");
}
- auto engineData = m_registration.attr("get_engine_data")(pybind11::none(), enginePath);
+ auto engineData = m_manifest.attr("get_engine_json_data")(pybind11::none(), enginePath);
if (pybind11::isinstance(engineData))
{
try
{
- engineInfo.m_version = Py_To_String_Optional(engineData,"O3DEVersion","0.0.0.0");
- engineInfo.m_name = Py_To_String_Optional(engineData,"engine_name","O3DE");
+ engineInfo.m_version = Py_To_String_Optional(engineData,"O3DEVersion","0.0.0.0");
+ engineInfo.m_name = Py_To_String_Optional(engineData,"engine_name","O3DE");
}
catch ([[maybe_unused]] const std::exception& e)
{
@@ -364,13 +367,13 @@ namespace O3DE::ProjectManager
}
else
{
- return AZ::Success(AZStd::move(engineInfo));
+ return AZ::Success(AZStd::move(engineInfo));
}
return AZ::Failure();
}
- bool PythonBindings::SetEngineInfo(const EngineInfo& engineInfo)
+ bool PythonBindings::SetEngineInfo(const EngineInfo& engineInfo)
{
bool result = ExecuteWithLock([&] {
pybind11::str enginePath = engineInfo.m_path.toStdString();
@@ -378,17 +381,18 @@ namespace O3DE::ProjectManager
pybind11::str defaultGemsFolder = engineInfo.m_defaultGemsFolder.toStdString();
pybind11::str defaultTemplatesFolder = engineInfo.m_defaultTemplatesFolder.toStdString();
- auto registrationResult = m_registration.attr("register")(
+ auto registrationResult = m_register.attr("register")(
enginePath, // engine_path
pybind11::none(), // project_path
- pybind11::none(), // gem_path
+ pybind11::none(), // gem_path
+ pybind11::none(), // external_subdir_path
pybind11::none(), // template_path
pybind11::none(), // restricted_path
pybind11::none(), // repo_uri
pybind11::none(), // default_engines_folder
defaultProjectsFolder,
- defaultGemsFolder,
- defaultTemplatesFolder
+ defaultGemsFolder,
+ defaultTemplatesFolder
);
if (registrationResult.cast() != 0)
@@ -396,13 +400,13 @@ namespace O3DE::ProjectManager
result = false;
}
- auto manifest = m_registration.attr("load_o3de_manifest")();
+ auto manifest = m_manifest.attr("load_o3de_manifest")();
if (pybind11::isinstance(manifest))
{
try
{
manifest["third_party_path"] = engineInfo.m_thirdPartyPath.toStdString();
- m_registration.attr("save_o3de_manifest")(manifest);
+ m_manifest.attr("save_o3de_manifest")(manifest);
}
catch ([[maybe_unused]] const std::exception& e)
{
@@ -415,12 +419,12 @@ namespace O3DE::ProjectManager
return result;
}
- AZ::Outcome PythonBindings::GetGem(const QString& path)
+ AZ::Outcome PythonBindings::GetGem(const QString& path)
{
GemInfo gemInfo = GemInfoFromPath(pybind11::str(path.toStdString()));
if (gemInfo.IsValid())
{
- return AZ::Success(AZStd::move(gemInfo));
+ return AZ::Success(AZStd::move(gemInfo));
}
else
{
@@ -428,19 +432,19 @@ namespace O3DE::ProjectManager
}
}
- AZ::Outcome> PythonBindings::GetGems()
+ AZ::Outcome> PythonBindings::GetGems()
{
QVector