Merge branch 'main' into Atom/dmcdiar/ATOM-15517

This commit is contained in:
Doug McDiarmid
2021-05-28 13:43:26 -07:00
778 changed files with 14621 additions and 15273 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ SortIncludes: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
+2
View File
@@ -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/
File diff suppressed because it is too large Load Diff
+36 -18
View File
@@ -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()
+33 -22
View File
@@ -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()
@@ -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
)
@@ -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
)
@@ -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
)
@@ -31,13 +31,13 @@ class TestPythonAssetProcessing(object):
unexpected_lines = []
expected_lines = [
'Mock asset exists',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel) found',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel) found',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel) found',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel) found',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel) found',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel) found',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel) found'
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive.azmodel) found',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative.azmodel) found',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive.azmodel) found',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative.azmodel) found',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive.azmodel) found',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative.azmodel) found',
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found'
]
timeout = 180
halt_on_unexpected = False
@@ -38,16 +38,16 @@ def test_azmodel_product(generatedModelAssetPath, expectedSubId):
assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', generatedModelAssetPath, azModelAssetType, False)
assetIdString = assetId.to_string()
if (assetIdString.endswith(':' + expectedSubId) is False):
raise_and_stop(f'Asset has unexpected asset ID ({assetIdString}) for ({generatedModelAssetPath})!')
raise_and_stop(f'Asset at path {generatedModelAssetPath} has unexpected asset ID ({assetIdString}) for ({generatedModelAssetPath}), expected {expectedSubId}!')
else:
print(f'Expected subId for asset ({generatedModelAssetPath}) found')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel', '10315ae0')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel', '10661093')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel', '10af8810')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel', '10f8c263')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel', '100ac47f')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel', '105d8e0c')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel', '1002d464')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive.azmodel', '1024be55')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative.azmodel', '1052c94e')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive.azmodel', '10130556')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative.azmodel', '1065724d')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive.azmodel', '10d16e68')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative.azmodel', '10a71973')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel', '10412075')
azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt')
@@ -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
@@ -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 = []
@@ -23,6 +23,25 @@ class TestSurfaceMaskFilter_BasicSurfaceTagCreation(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="TestSurfaceMaskFilter_BasicSurfaceTagCreation", args=["level"])
def run_test(self):
"""
Summary:
Verifies basic surface tag value equality
Expected Behavior:
Surface tags of the same name are equal, and different names aren't.
Test Steps:
1) Open level
2) Create 2 new surface tags of identical names and verify they resolve as equal.
3) Create another new tag of a different name and verify they resolve as different.
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
self.log("SurfaceTag test started")
# Create a level
@@ -33,6 +33,25 @@ class TestVegetationInstances_DespawnWhenOutOfRange(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix='VegetationInstances_DespawnWhenOutOfRange', args=['level'])
def run_test(self):
"""
Summary:
Verifies that vegetation instances properly spawn/despawn based on camera range.
Expected Behavior:
Vegetation instances despawn when out of camera range.
Test Steps:
1) Create a new level
2) Create a simple vegetation area, and set the view position near the spawner. Verify instances plant.
3) Move the view position away from the spawner. Verify instances despawn.
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
# Create a new level
self.test_success = self.create_level(
@@ -28,8 +28,21 @@ class TestGradientGeneratorIncompatibilities(EditorTestHelper):
def run_test(self):
"""
Summary:
Verify that Entities are not active when a Gradient Generator and incompatible component are both present
on the same Entity.
This test verifies that components are disabled when conflicting components are present on the same entity.
Expected Behavior:
Gradient Generator components are incompatible with Vegetation area components.
Test Steps:
1) Create a new level
2) Create a new entity in the level
3) Add each Gradient Generator component to an entity, and add a Vegetation Area component to the same entity
4) Verify that components are only enabled when entity is free of a conflicting component
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
@@ -28,8 +28,21 @@ class TestGradientModifiersIncompatibilities(EditorTestHelper):
def run_test(self):
"""
Summary:
Verify that Entities are not active when a Gradient Modifier and incompatible component are both present
on the same Entity.
This test verifies that components are disabled when conflicting components are present on the same entity.
Expected Behavior:
Gradient Modifier components are incompatible with Vegetation area components.
Test Steps:
1) Create a new level
2) Create a new entity in the level
3) Add each Gradient Modifier component to an entity, and add a Vegetation Area component to the same entity
4) Verify that components are only enabled when entity is free of a conflicting component
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
@@ -9,19 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
"""
The below cases are combined in this script
C2676829
C3961326
C3980659
C3980664
C3980669
C3416548
C2676823
C3961321
C2676826
"""
import os
import sys
@@ -44,7 +44,21 @@ class TestGradientPreviewSettings(EditorTestHelper):
def run_test(self):
"""
Summary:
Verify if the current entity is set to the pin preview to shape entity by default for several components.
This test verifies default values for the pinned entity for Gradient Preview settings.
Expected Behavior:
Pinned entity is self for all gradient generator/modifiers.
Test Steps:
1) Create a new level
2) Create a new entity in the level
3) Add each Gradient Generator component to an entity, and verify the Pin Preview to Shape property is set to
self
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
@@ -31,11 +31,21 @@ class TestGradientSurfaceTagEmitterDependencies(EditorTestHelper):
def run_test(self):
"""
Summary:
Component has a dependency on a Gradient component
This test verifies that the Gradient Surface Tag Emitter component is dependent on a gradient component.
Expected Result:
Component is disabled until a Gradient Generator, Modifier or Gradient Reference component
(and any sub-dependencies) is added to the entity.
Gradient Surface Tag Emitter component is disabled until a Gradient Generator, Modifier or Gradient Reference
component (and any sub-dependencies) is added to the entity.
Test Steps:
1) Open level
2) Create a new entity with a Gradient Surface Tag Emitter component
3) Verify the component is disabled until a dependent component is also added to the entity
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
@@ -28,8 +28,20 @@ class TestGradientTransformRequiresShape(EditorTestHelper):
def run_test(self):
"""
Summary:
Verify that Gradient Transform Modifier component requires a
Shape component before the Entity can become active.
This test verifies that the Gradient Transform Modifier component is dependent on a shape component.
Expected Result:
Gradient Transform Modifier component is disabled until a shape component is added to the entity.
Test Steps:
1) Open level
2) Create a new entity with a Gradient Transform Modifier component
3) Verify the component is disabled until a shape component is also added to the entity
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
@@ -28,8 +28,20 @@ class TestImageGradientRequiresShape(EditorTestHelper):
def run_test(self):
"""
Summary:
Verify that Image Gradient component requires a
Shape component before the Entity can become active.
This test verifies that the Image Gradient component is dependent on a shape component.
Expected Result:
Gradient Transform Modifier component is disabled until a shape component is added to the entity.
Test Steps:
1) Open level
2) Create a new entity with a Image Gradient component
3) Verify the component is disabled until a shape component is also added to the entity
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
@@ -33,6 +33,26 @@ class TestAreaNodeComponentDependency(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="AreaNodeComponentDependency", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities with
proper dependent components.
Expected Behavior:
All expected component dependencies are met when adding an area node to a graph.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Drag each of the area nodes to the graph area, and ensure the proper dependent components are added
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global newEntityId
@@ -33,7 +33,25 @@ class TestGradientNodeEntityCreate(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="AreaNodeEntityCreate", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
Expected Behavior:
New entities are created when dragging area nodes to graph area.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Drag each of the area nodes to the graph area, and ensure a new entity is created
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global newEntityId
newEntityId = parameters[0]
@@ -34,7 +34,26 @@ class TestAreaNodeEntityDelete(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="AreaNodeEntityDelete", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
Expected Behavior:
Entities are removed when area nodes are deleted from a graph.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Drag each of the area nodes to the graph area, and ensure a new entity is created
4) Delete the nodes, and ensure the newly created entities are removed
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global createdEntityId
createdEntityId = parameters[0]
@@ -9,24 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
"""
C22602072 - Graph is updated when underlying components are added/removed
1. Open Level.
2. Find LandscapeCanvas named entity.
3. Ensure Vegetation Distribution Component is present on the BushSpawner entity.
4. Open graph and ensure Distribution Filter wrapped node is present.
5. Delete the Vegetation Distribution Filter component from the BushSpawner entity via Entity Inspector.
6. Ensure the Vegetation Distribution Filter component was deleted from the BushSpawner entity and node is no longer
present in the graph.
7. Add Vegetation Altitude Filter to the BushSpawner entity through Entity Inspector.
8. Ensure Altitude Filter was added to the BushSpawner node in the open graph.
9. Add a new entity with unique name as a child of the Landscape Canvas entity.
10. Add a Box Shape component to the new child entity.
11. Ensure Box Shape node is present on the open graph.
"""
import os
import sys
@@ -50,6 +32,36 @@ class TestComponentUpdatesUpdateGraph(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="ComponentUpdatesUpdateGraph", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas graphs update properly when components are added/removed outside of
Landscape Canvas.
Expected Behavior:
Graphs properly reflect component changes made to entities outside of Landscape Canvas.
Test Steps:
1. Open Level
2. Find LandscapeCanvas named entity
3. Ensure Vegetation Distribution Component is present on the BushSpawner entity
4. Open graph and ensure Distribution Filter wrapped node is present
5. Delete the Vegetation Distribution Filter component from the BushSpawner entity via Entity Inspector
6. Ensure the Vegetation Distribution Filter component was deleted from the BushSpawner entity and node is
no longer present in the graph
7. Add Vegetation Altitude Filter to the BushSpawner entity through Entity Inspector
8. Ensure Altitude Filter was added to the BushSpawner node in the open graph
9. Add a new entity with unique name as a child of the Landscape Canvas entity
10. Add a Box Shape component to the new child entity
11. Ensure Box Shape node is present on the open graph
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
# Create a new empty level and instantiate LC_BushFlowerBlender.slice
self.test_success = self.create_level(
self.args["level"],
@@ -37,6 +37,25 @@ class TestCreateNewGraph(EditorTestHelper):
print("New root entity created")
def run_test(self):
"""
Summary:
This test verifies that new graphs can be created in Landscape Canvas.
Expected Behavior:
New graphs can be created, and proper entity is created to hold graph data with a Landscape Canvas component.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Ensures the root entity created contains a Landscape Canvas component
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
self.test_success = self.create_level(
self.args["level"],
heightmap_resolution=128,
@@ -33,7 +33,25 @@ class TestDisabledNodeDuplication(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="DisabledNodeDuplication", args=["level"])
def run_test(self):
"""
Summary:
This test verifies Editor stability after duplicating disabled Landscape Canvas nodes.
Expected Behavior:
Editor remains stable and free of crashes.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Create several new nodes, disable the nodes via disabling/deleting components, and duplicate the nodes
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global newEntityId
newEntityId = parameters[0]
@@ -9,17 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
"""
C30813586 - Editor remains stable after Undoing deletion of a node on a slice entity
1. Open level with instantiated slice.
2. Open the graph.
3. Find the BushSpawner's Vegetation Layer Spawner node.
4. Delete the node.
5. Undo to restore the node.
"""
import os
import sys
@@ -44,7 +33,26 @@ class TestUndoNodeDeleteSlice(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="UndoNodeDeleteSlice", args=["level"])
def run_test(self):
"""
Summary:
This test verifies Editor stability after undoing the deletion of nodes on a slice entity.
Expected Behavior:
Editor remains stable and free of crashes.
Test Steps:
1) Create a new level
2) Instantiate a slice with a Landscape Canvas setup
3) Find a specific node on the graph, and delete it
4) Restore the node with Undo
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
# Create a new empty level and instantiate LC_BushFlowerBlender.slice
self.test_success = self.create_level(
self.args["level"],
@@ -34,6 +34,27 @@ class TestGradientMixerNodeConstruction(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GradientMixerNodeConstruction", args=["level"])
def run_test(self):
"""
Summary:
This test verifies a Gradient Mixer vegetation setup can be constructed through Landscape Canvas.
Expected Behavior:
Entities contain all required components and component references after creating nodes and setting connections
on a Landscape Canvas graph.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Add all necessary nodes to the graph and set connections to form a Gradient Mixer setup
4) Verify all components and component references were properly set during graph construction
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global newEntityId
@@ -33,6 +33,25 @@ class TestGradientModifierNodeEntityCreate(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GradientModifierNodeEntityCreate", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
Expected Behavior:
New entities are created when dragging Gradient Modifier nodes to graph area.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Drag each of the Gradient Modifier nodes to the graph area, and ensure a new entity is created
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global newEntityId
@@ -34,7 +34,26 @@ class TestGradientModifierNodeEntityDelete(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GradientModifierNodeEntityDelete", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
Expected Behavior:
Entities are removed when Gradient Modifier nodes are deleted from a graph.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Drag each of the Gradient Modifier nodes to the graph area, and ensure a new entity is created
4) Delete the nodes, and ensure the newly created entities are removed
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global createdEntityId
createdEntityId = parameters[0]
@@ -33,6 +33,27 @@ class TestGradientNodeComponentDependency(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GradientNodeComponentDependency", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities with
proper dependent components.
Expected Behavior:
All expected component dependencies are met when adding a Gradient Modifier node to a graph.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Drag each of the Gradient Modifier nodes to the graph area, and ensure the proper dependent components are
added
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global newEntityId
@@ -32,6 +32,25 @@ class TestGradientNodeEntityCreate(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GradientNodeEntityCreate", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
Expected Behavior:
New entities are created when dragging Gradient nodes to graph area.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Drag each of the Gradient nodes to the graph area, and ensure a new entity is created
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global newEntityId
@@ -34,6 +34,26 @@ class TestGradientNodeEntityDelete(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GradientNodeEntityDelete", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
Expected Behavior:
Entities are removed when Gradient nodes are deleted from a graph.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Drag each of the Gradient nodes to the graph area, and ensure a new entity is created
4) Delete the nodes, and ensure the newly created entities are removed
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global createdEntityId
@@ -31,6 +31,26 @@ class TestGraphClosedOnEntityDelete(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GraphClosedOnEntityDelete", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that Landscape Canvas graphs are auto-closed when the corresponding entity is deleted.
Expected Behavior:
When a Landscape Canvas root entity is deleted, the corresponding graph automatically closes.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Delete the automatically created entity
4) Verify the open graph is closed
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global newRootEntityId
@@ -29,7 +29,26 @@ class TestGraphClosedOnLevelChange(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GraphClosedOnLevelChange", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that Landscape Canvas graphs are auto-closed when the currently open level changes.
Expected Behavior:
When a new level is loaded in the Editor, open Landscape Canvas graphs are automatically closed.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Open a different level
4) Verify the open graph is closed
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
# Create a new empty level
self.test_success = self.create_level(
self.args["level"],
@@ -29,6 +29,26 @@ class TestGraphClosedTabbedGraph(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GraphClosedTabbedGraph", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that Landscape Canvas tabbed graphs can be independently closed.
Expected Behavior:
Closing a tabbed graph only closes the appropriate graph.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create several new graphs
3) Close one of the open graphs
4) Ensure the graph properly closed, and other open graphs remain open
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
# Create a new empty level
self.test_success = self.create_level(
@@ -9,21 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
"""
C22715182 - Components are updated when nodes are added/removed/updated
1. Open Level.
2. Open the graph on LC_BushFlowerBlender.slice
3. Find the Rotation Modifier node on the BushSpawner entity
4. Delete the Rotation Modifier node
5. Ensure the Vegetation Rotation Modifier component is removed from the BushSpawner entity
6. Delete the Vegetation Layer Spawner node from the graph
7. Ensure BushSpawner entity is deleted
8. Change connection from second Rotation Modifier node to a different Gradient
9. Ensure Gradient reference on component is updated
"""
import os
import sys
@@ -50,6 +35,31 @@ class TestGraphUpdatesUpdateComponents(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="GraphUpdatesUpdateComponents", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that components are properly updated as nodes are added/removed/updated.
Expected Behavior:
Landscape Canvas node CRUD properly updates component entities.
Test Steps:
1. Open Level.
2. Open the graph on LC_BushFlowerBlender.slice
3. Find the Rotation Modifier node on the BushSpawner entity
4. Delete the Rotation Modifier node
5. Ensure the Vegetation Rotation Modifier component is removed from the BushSpawner entity
6. Delete the Vegetation Layer Spawner node from the graph
7. Ensure BushSpawner entity is deleted
8. Change connection from second Rotation Modifier node to a different Gradient
9. Ensure Gradient reference on component is updated
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
# Create a new empty level and instantiate LC_BushFlowerBlender.slice
self.test_success = self.create_level(
self.args["level"],
@@ -30,6 +30,26 @@ class TestLandscapeCanvasComponentAddedRemoved(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="LandscapeCanvasComponentAddedRemoved", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas component can be added to/removed from an entity.
Expected Behavior:
Closing a tabbed graph only closes the appropriate graph.
Test Steps:
1) Create a new level
2) Create a new entity
3) Add a Landscape Canvas component to the entity
4) Remove the Landscape Canvas component from the entity
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
# Create a new empty level
self.test_success = self.create_level(
@@ -30,12 +30,21 @@ class TestLandscapeCanvasSliceCreateInstantiate(EditorTestHelper):
def run_test(self):
"""
Summary:
C22602016 A slice containing the LandscapeCanvas component can be created/instantiated.
A slice containing the LandscapeCanvas component can be created/instantiated.
Expected Result:
Slice is created and processed successfully and free of errors/warnings.
Another copy of the slice is instantiated.
Slice is created/processed/instantiated successfully and free of errors/warnings.
Test Steps:
1) Create a new level
2) Create a new entity with a Landscape Canvas component
3) Create a slice of the new entity
4) Instantiate a new copy of the slice
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
@@ -34,6 +34,27 @@ class TestLayerBlenderNodeConstruction(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="LayerBlenderNodeConstruction", args=["level"])
def run_test(self):
"""
Summary:
This test verifies a Layer Blender vegetation setup can be constructed through Landscape Canvas.
Expected Behavior:
Entities contain all required components and component references after creating nodes and setting connections
on a Landscape Canvas graph.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Add all necessary nodes to the graph and set connections to form a Layer Blender setup
4) Verify all components and component references were properly set during graph construction
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global newEntityId
@@ -34,6 +34,25 @@ class TestLayerExtenderNodeComponentEntitySync(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="LayerExtenderNodeComponentEntitySync", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that all wrapped nodes can be successfully added to/removed from parent nodes.
Expected Behavior:
All wrapped extender nodes can be added to/removed from appropriate parent nodes.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Add Area Blender and Layer Spawner nodes to the graph, and add/remove each extender node to/from each
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global newEntityId
@@ -33,6 +33,25 @@ class TestShapeNodeEntityCreate(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="ShapeNodeEntityCreate", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas nodes can be added to a graph, and correctly create entities.
Expected Behavior:
New entities are created when dragging shape nodes to graph area.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Drag each of the shape nodes to the graph area, and ensure a new entity is created
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global newEntityId
@@ -34,7 +34,27 @@ class TestShapeNodeEntityDelete(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="ShapeNodeEntityDelete", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas node deletion properly cleans up entities in the Editor.
Expected Behavior:
Entities are removed when shape nodes are deleted from a graph.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Drag each of the shape nodes to the graph area, and ensure a new entity is created
4) Delete the nodes, and ensure the newly created entities are removed
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
def onEntityCreated(parameters):
global createdEntityId
createdEntityId = parameters[0]
@@ -33,6 +33,27 @@ class TestSlotConnectionsUpdateComponents(EditorTestHelper):
EditorTestHelper.__init__(self, log_prefix="SlotConnectionsUpdateComponents", args=["level"])
def run_test(self):
"""
Summary:
This test verifies that the Landscape Canvas slot connections properly update component references.
Expected Behavior:
A reference created through slot connections in Landscape Canvas is reflected in the Entity Inspector.
Test Steps:
1) Create a new level
2) Open Landscape Canvas and create a new graph
3) Several nodes are added to a graph, and connections are set between the nodes
4) Component references are verified via Entity Inspector
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
# Retrieve the proper component TypeIds per component name
componentNames = [
'Random Noise Gradient',
@@ -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)
@@ -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)
@@ -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,
)
@@ -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
@@ -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"])
@@ -119,6 +119,9 @@
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
@@ -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"
}
}
}
}
}
}
@@ -107,6 +107,9 @@
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
@@ -119,6 +119,9 @@
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
@@ -119,6 +119,9 @@
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
@@ -119,6 +119,9 @@
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
@@ -101,6 +101,9 @@
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
@@ -1,18 +1,19 @@
<ObjectStream version="3">
<Class name="MaterialLibraryAsset" version="2" type="{9E366D8C-33BB-4825-9A1F-FA3ADBE11D0F}">
<Class name="Physics::MaterialLibraryAsset" version="2" type="{9E366D8C-33BB-4825-9A1F-FA3ADBE11D0F}">
<Class name="AssetData" field="BaseClass1" version="1" type="{AF3F7D32-1536-422A-89F3-A11E1F5B5A9C}"/>
<Class name="AZStd::vector" field="Properties" type="{A8E59F8C-2F9A-525A-B549-A9E197EB9632}">
<Class name="MaterialFromAssetConfiguration" field="element" version="1" type="{FBD76628-DE57-435E-BE00-6FFAE64DDF1D}">
<Class name="MaterialConfiguration" field="Configuration" version="2" type="{8807CAA1-AD08-4238-8FDB-2154ADD084A1}">
<Class name="AZStd::string" field="SurfaceType" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="Physics::MaterialFromAssetConfiguration" field="element" version="1" type="{FBD76628-DE57-435E-BE00-6FFAE64DDF1D}">
<Class name="Physics::MaterialConfiguration" field="Configuration" version="3" type="{8807CAA1-AD08-4238-8FDB-2154ADD084A1}">
<Class name="AZStd::string" field="SurfaceType" value="Debug" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="float" field="DynamicFriction" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
<Class name="float" field="StaticFriction" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
<Class name="float" field="Restitution" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
<Class name="unsigned char" field="FrictionCombine" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/>
<Class name="unsigned char" field="RestitutionCombine" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/>
<Class name="float" field="Density" value="1000.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
<Class name="Color" field="DebugColor" value="1.0000000 1.0000000 1.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
</Class>
<Class name="MaterialId" field="UID" version="1" type="{744CCE6C-9F69-4E2F-B950-DAB8514F870B}">
<Class name="Physics::MaterialId" field="UID" version="1" type="{744CCE6C-9F69-4E2F-B950-DAB8514F870B}">
<Class name="AZ::Uuid" field="MaterialId" value="{B072A405-BAFA-4B0A-9164-B3A424E642A9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
</Class>
</Class>
+63 -69
View File
@@ -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()
@@ -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())
{
-5
View File
@@ -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;
}
@@ -1260,7 +1260,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 +1330,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())
@@ -172,78 +172,10 @@ namespace AZ
//! Rotation modifiers
//! @{
//! @deprecated Use SetLocalRotation()
//! Sets the entity's rotation in the world.
//! The origin of the axes is the entity's position in world space.
//! @param eulerAnglesRadians A three-dimensional vector, containing Euler angles in radians, to rotate the entity by.
virtual void SetRotation([[maybe_unused]] const AZ::Vector3& eulerAnglesRadians) {}
//! @deprecated Use SetLocalRotation()
//! Sets the entity's rotation around the world's X axis.
//! The origin of the axis is the entity's position in world space.
//! @param eulerAngleRadians The X coordinate Euler angle in radians to use for the entity's rotation.
virtual void SetRotationX([[maybe_unused]] float eulerAngleRadian) {}
//! @deprecated Use SetLocalRotation()
//! Sets the entity's rotation around the world's Y axis.
//! The origin of the axis is the entity's position in world space.
//! @param eulerAngleRadians The Y coordinate Euler angle in radians to use for the entity's rotation.
virtual void SetRotationY([[maybe_unused]] float eulerAngleRadian) {}
//! @deprecated Use SetLocalRotation()
//! Sets the entity's rotation around the world's Z axis.
//! The origin of the axis is the entity's position in world space.
//! @param eulerAngleRadians The Z coordinate Euler angle in radians to use for the entity's rotation.
virtual void SetRotationZ([[maybe_unused]] float eulerAngleRadian) {}
//! @deprecated Use SetLocalRotationQuaternion()
//! Sets the entity's rotation in the world in quaternion notation.
//! The origin of the axes is the entity's position in world space.
//! @param quaternion A quaternion that represents the rotation to use for the entity.
virtual void SetRotationQuaternion([[maybe_unused]] const AZ::Quaternion& quaternion) {}
//! @deprecated Use RotateAroundLocalX()
//! Rotates the entity around the world's X axis.
//! The origin of the axis is the entity's position in world space.
//! @param eulerAngleRadians The Euler angle in radians by which to rotate the entity around the X axis.
virtual void RotateByX([[maybe_unused]] float eulerAngleRadian) {}
//! @deprecated Use RotateAroundLocalY()
//! Rotates the entity around the world's Y axis.
//! The origin of the axis is the entity's position in world space.
//! @param eulerAngleRadians The Euler angle in radians by which to rotate the entity around the Y axis.
virtual void RotateByY([[maybe_unused]] float eulerAngleRadian) {}
//! @deprecated Use RotateAroundLocalZ()
//! Rotates the entity around the world's Z axis.
//! The origin of the axis is the entity's position in world space.
//! @param eulerAngleRadians The Euler angle in radians by which to rotate the entity around the Z axis.
virtual void RotateByZ([[maybe_unused]] float eulerAngleRadian) {}
//! @deprecated Use GetLocalRotation()
//! Gets the entity's rotation in the world in Euler angles rotation in radians.
//! @return A three-dimensional vector, containing Euler angles in radians, that represents the entity's rotation.
virtual AZ::Vector3 GetRotationEulerRadians() { return AZ::Vector3(FLT_MAX); }
//! @deprecated Use GetLocalRotationQuaternion()
//! Gets the entity's rotation in the world in quaternion format.
//! @return A quaternion that represents the entity's rotation in world space.
virtual AZ::Quaternion GetRotationQuaternion() { return AZ::Quaternion::CreateZero(); }
//! @deprecated Use GetLocalRotation()
//! Gets the entity's rotation around the world's X axis.
//! @return The Euler angle in radians by which the the entity is rotated around the X axis in world space.
virtual float GetRotationX() { return FLT_MAX; }
//! @deprecated Use GetLocalRotation()
//! Gets the entity's rotation around the world's Y axis.
//! @return The Euler angle in radians by which the the entity is rotated around the Y axis in world space.
virtual float GetRotationY() { return FLT_MAX; }
//! @deprecated Use GetLocalRotation()
//! Gets the entity's rotation around the world's Z axis.
//! @return The Euler angle in radians by which the the entity is rotated around the Z axis in world space.
virtual float GetRotationZ() { return FLT_MAX; }
virtual void SetWorldRotationQuaternion([[maybe_unused]] const AZ::Quaternion& quaternion) {}
//! Get angles in radian for each principle axis around which the world transform is
//! rotated in the order of z-axis and y-axis and then x-axis.
@@ -287,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) {}
@@ -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<MaxPathLength> 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"
@@ -915,6 +915,11 @@ namespace AZ::IO
return compare_string_view(path);
}
constexpr AZStd::fixed_string<MaxPathLength> PathView::FixedMaxPathString() const noexcept
{
return AZStd::fixed_string<MaxPathLength>(m_path.begin(), m_path.end());
}
// decomposition
constexpr auto PathView::RootName() const -> PathView
{
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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()
);
}
}
+40 -19
View File
@@ -130,8 +130,8 @@ namespace AZ
const Transform* transform = reinterpret_cast<const Transform*>(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<float, dataBufferSize> 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<void*>(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<Transform*>(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<Transform*>(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<Transform>()
->Version(1)
->Version(2)
->Serializer<TransformSerializer>();
}
@@ -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<const Vector3&, const Quaternion&, const Vector3&>()->
Constructor<const Vector3&, const Quaternion&, float>()->
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<void (Transform::*)(const Quaternion&)>("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;
+17 -16
View File
@@ -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;
};
+21 -58
View File
@@ -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();
}
@@ -67,7 +67,7 @@ namespace AZ
result.Combine(loadResult);
transformInstance->SetScale(AZ::Vector3(scale));
transformInstance->SetUniformScale(scale);
}
return context.Report(
@@ -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);
@@ -35,7 +35,7 @@ namespace AZ
return "Android";
case AZ::IOS:
return "iOS";
case AZ::MAC:
case AZ::MAC_ID:
return "Mac";
case AZ::PROVO:
return "Provo";
@@ -213,7 +213,7 @@ namespace AZ
case PlatformId::IOS:
platformCodes.emplace_back(PlatformCodeNameiOS);
break;
case PlatformId::MAC:
case PlatformId::MAC_ID:
platformCodes.emplace_back(PlatformCodeNameMac);
break;
case PlatformId::PROVO:
@@ -56,7 +56,7 @@ namespace AZ
PC,
ANDROID_ID,
IOS,
MAC,
MAC_ID,
PROVO,
SALEM,
JASPER,
@@ -75,7 +75,7 @@ namespace AZ
Platform_PC = 1 << PlatformId::PC,
Platform_ANDROID = 1 << PlatformId::ANDROID_ID,
Platform_IOS = 1 << PlatformId::IOS,
Platform_MAC = 1 << PlatformId::MAC,
Platform_MAC = 1 << PlatformId::MAC_ID,
Platform_PROVO = 1 << PlatformId::PROVO,
Platform_SALEM = 1 << PlatformId::SALEM,
Platform_JASPER = 1 << PlatformId::JASPER,
@@ -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);
@@ -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<EngineInfo> m_enginePaths{};
};
@@ -13,5 +13,5 @@
namespace AZ
{
static const PlatformID g_currentPlatform = PlatformID::PLATFORM_APPLE_OSX;
static const PlatformID g_currentPlatform = PlatformID::PLATFORM_APPLE_MAC;
}
@@ -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)
@@ -44,7 +44,7 @@ namespace JsonSerializationTests
AZStd::shared_ptr<AZ::Transform> CreateFullySetInstance() override
{
return AZStd::make_shared<AZ::Transform>(
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 })");
@@ -2008,13 +2008,12 @@ namespace AZ::IO
// if no bind root is specified, compute one:
strBindRoot = !bindRoot.empty() ? bindRoot : szFullPath->ParentPath().Native();
// Check if archive file disk exist on disk or inside of pak.
bool bFileExists = IsFileExist(szFullPath->Native());
if (!bFileExists && (nFactoryFlags & ZipDir::CacheFactory::FLAGS_READ_ONLY))
// Check if archive file disk exist on disk.
const bool pakOnDisk = FileIOBase::GetDirectInstance()->Exists(szFullPath->c_str());
if (!pakOnDisk && (nFactoryFlags & ZipDir::CacheFactory::FLAGS_READ_ONLY))
{
// Archive file not found.
AZ_TracePrintf("Archive", "Cannot open Archive file %s\n", szFullPath->c_str());
AZ_TracePrintf("Archive", "Archive file %s does not exist\n", szFullPath->c_str());
return nullptr;
}
@@ -2492,8 +2491,6 @@ namespace AZ::IO
void Archive::FindCompressionInfo(bool& found, AZ::IO::CompressionInfo& info, const AZStd::string_view filename)
{
constexpr uint32_t s_compressionTag = static_cast<uint32_t>('Z') << 24 | static_cast<uint32_t>('C') << 16 | static_cast<uint32_t>('R') << 8 | static_cast<uint32_t>('Y');
if (!found)
{
auto correctedFilename = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(filename);
@@ -2519,7 +2516,6 @@ namespace AZ::IO
found = true;
info.m_archiveFilename.InitFromRelativePath(archive->GetFilePath());
info.m_compressionTag.m_code = s_compressionTag;
info.m_offset = pFileData->GetFileDataOffset();
info.m_compressedSize = entry->desc.lSizeCompressed;
info.m_uncompressedSize = entry->desc.lSizeUncompressed;
@@ -2539,9 +2535,8 @@ namespace AZ::IO
break;
}
info.m_decompressor = [&s_compressionTag]([[maybe_unused]] const AZ::IO::CompressionInfo& info, const void* compressed, size_t compressedSize, void* uncompressed, size_t uncompressedBufferSize)->bool
info.m_decompressor = []([[maybe_unused]] const AZ::IO::CompressionInfo& info, const void* compressed, size_t compressedSize, void* uncompressed, size_t uncompressedBufferSize)->bool
{
AZ_Assert(info.m_compressionTag.m_code == s_compressionTag, "Provided compression info isn't supported by this decompressor.");
size_t nSizeUncompressed = uncompressedBufferSize;
return ZipDir::ZipRawUncompress(uncompressed, &nSizeUncompressed, compressed, compressedSize) == 0;
};
@@ -50,6 +50,7 @@ namespace AZ::IO
, tWrite{ writeTime }
{
}
ArchiveFileIterator::ArchiveFileIterator(FindData* findData, AZStd::string_view filename, const FileDesc& fileDesc)
: m_findData{ findData }
, m_filename{ filename }
@@ -108,13 +109,10 @@ namespace AZ::IO
AZ::StringFunc::Path::GetFullPath(directory.c_str(), searchDirectory);
AZ::StringFunc::Path::GetFullFileName(directory.c_str(), pattern);
}
AZ::IO::FileIOBase::GetDirectInstance()->FindFiles(searchDirectory.c_str(), pattern.c_str(), [&](const char* filePath) -> bool
{
AZ::IO::FileDesc fileDesc;
AZStd::string fullFilePath;
AZ::StringFunc::Path::GetFullFileName(filePath, fullFilePath);
AZStd::string filePathEntry{filePath};
if (AZ::IO::FileIOBase::GetDirectInstance()->IsDirectory(filePath))
{
@@ -135,9 +133,8 @@ namespace AZ::IO
fileDesc.tAccess = fileDesc.tWrite;
fileDesc.tCreate = fileDesc.tWrite;
}
[[maybe_unused]] auto result = m_mapFiles.emplace(AZStd::move(fullFilePath), fileDesc);
AZ_Assert(result.second, "Failed to insert FindData entry for %s", fullFilePath.c_str());
[[maybe_unused]] auto result = m_mapFiles.emplace(AZStd::move(filePathEntry), fileDesc);
AZ_Assert(result.second, "Failed to insert FindData entry for filePath %s", filePath);
return true;
});
}
@@ -273,7 +270,9 @@ namespace AZ::IO
}
auto pakFileIter = m_mapFiles.begin();
fileIterator.m_filename = pakFileIter->first;
AZStd::string fullFilePath;
AZ::StringFunc::Path::GetFullFileName(pakFileIter->first.c_str(), fullFilePath);
fileIterator.m_filename = AZStd::move(fullFilePath);
fileIterator.m_fileDesc = pakFileIter->second;
fileIterator.m_lastFetchValid = true;
@@ -1,22 +1,22 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/Component.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl>
#include <AzCore/Serialization/SerializeContext.h>
namespace AzFramework
{
@@ -64,15 +64,13 @@ namespace AzFramework
the EditContext. TController can friend itself to the editor component to make this work if required.
*/
template<typename TController, typename TConfiguration = AZ::ComponentConfig>
class ComponentAdapter
: public AZ::Component
class ComponentAdapter : public AZ::Component
{
public:
AZ_RTTI((ComponentAdapter, "{644A9187-4FDB-42C1-9D59-DD75304B551A}", TController, TConfiguration), AZ::Component);
ComponentAdapter() = default;
ComponentAdapter(const TConfiguration& configuration);
explicit ComponentAdapter(const TConfiguration& configuration);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services);
@@ -85,7 +83,6 @@ namespace AzFramework
void Deactivate() override;
protected:
static void Reflect(AZ::ReflectContext* context);
// AZ::Component overrides ...
@@ -1,14 +1,14 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzFramework/Components/ComponentAdapterHelpers.h>
@@ -32,10 +32,12 @@ namespace AzFramework
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
// clang-format off
serializeContext->Class<ComponentAdapter, Component>()
->Version(1)
->Field("Controller", &ComponentAdapter::m_controller)
;
// clang-format on
}
}
@@ -66,9 +68,6 @@ namespace AzFramework
GetDependentServicesHelper<TController>(services, typename AZ::HasComponentDependentServices<TController>::type());
}
//////////////////////////////////////////////////////////////////////////
// AZ::Component interface implementation
template<typename TController, typename TConfiguration>
void ComponentAdapter<TController, TConfiguration>::Init()
{
@@ -78,7 +77,7 @@ namespace AzFramework
template<typename TController, typename TConfiguration>
void ComponentAdapter<TController, TConfiguration>::Activate()
{
m_controller.Activate(GetEntityId());
ComponentActivateHelper<TController>::Activate(m_controller, AZ::EntityComponentIdPair(GetEntityId(), GetId()));
}
template<typename TController, typename TConfiguration>
@@ -13,6 +13,7 @@
#pragma once
#include <AzCore/Component/Component.h>
#include <AzCore/Component/EntityBus.h>
namespace AzFramework
{
@@ -27,18 +28,43 @@ namespace AzFramework
template<typename T, typename = void>
struct ComponentInitHelper
{
static void Init(T& common)
static void Init([[maybe_unused]] T& controller)
{
AZ_UNUSED(common);
}
};
template<typename T>
struct ComponentInitHelper<T, AZStd::void_t<decltype(AZStd::declval<T>().Init())>>
{
static void Init(T& common)
static void Init(T& controller)
{
common.Init();
controller.Init();
}
};
template<typename T, typename = void>
struct ComponentActivateHelper
{
static void Activate([[maybe_unused]] T& controller, [[maybe_unused]] const AZ::EntityComponentIdPair& entityComponentIdPair)
{
}
};
template<typename T>
struct ComponentActivateHelper<T, AZStd::void_t<decltype(AZStd::declval<T>().Activate(AZ::EntityId()))>>
{
static void Activate(T& controller, const AZ::EntityComponentIdPair& entityComponentIdPair)
{
controller.Activate(entityComponentIdPair.GetEntityId());
}
};
template<typename T>
struct ComponentActivateHelper<T, AZStd::void_t<decltype(AZStd::declval<T>().Activate(AZ::EntityComponentIdPair()))>>
{
static void Activate(T& controller, const AZ::EntityComponentIdPair& entityComponentIdPair)
{
controller.Activate(entityComponentIdPair);
}
};
@@ -327,99 +327,13 @@ namespace AzFramework
return localZ;
}
void TransformComponent::SetRotation(const AZ::Vector3& eulerAnglesRadian)
void TransformComponent::SetWorldRotationQuaternion(const AZ::Quaternion& quaternion)
{
AZ_Warning("TransformComponent", false, "SetRotation is deprecated, please use SetLocalRotation");
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetRotation(AZ::ConvertEulerRadiansToQuaternion(eulerAnglesRadian));
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetRotationQuaternion(const AZ::Quaternion& quaternion)
{
AZ_Warning("TransformComponent", false, "SetRotationQuaternion is deprecated, please use SetLocalRotationQuaternion");
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetRotation(quaternion);
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetRotationX(float eulerAngleRadian)
{
AZ_Warning("TransformComponent", false, "SetRotationX is deprecated, please use SetLocalRotation");
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetRotation(AZ::Quaternion::CreateRotationX(eulerAngleRadian));
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetRotationY(float eulerAngleRadian)
{
AZ_Warning("TransformComponent", false, "SetRotationY is deprecated, please use SetLocalRotation");
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetRotation(AZ::Quaternion::CreateRotationY(eulerAngleRadian));
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetRotationZ(float eulerAngleRadian)
{
AZ_Warning("TransformComponent", false, "SetRotationZ is deprecated, please use SetLocalRotation");
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetRotation(AZ::Quaternion::CreateRotationZ(eulerAngleRadian));
SetWorldTM(newWorldTransform);
}
void TransformComponent::RotateByX(float eulerAngleRadian)
{
AZ_Warning("TransformComponent", false, "RotateByX is deprecated, please use RotateAroundLocalX");
RotateAroundLocalX(eulerAngleRadian);
}
void TransformComponent::RotateByY(float eulerAngleRadian)
{
AZ_Warning("TransformComponent", false, "RotateByY is deprecated, please use RotateAroundLocalY");
RotateAroundLocalY(eulerAngleRadian);
}
void TransformComponent::RotateByZ(float eulerAngleRadian)
{
AZ_Warning("TransformComponent", false, "RotateByZ is deprecated, please use RotateAroundLocalZ");
RotateAroundLocalZ(eulerAngleRadian);
}
AZ::Vector3 TransformComponent::GetRotationEulerRadians()
{
AZ_Warning("TransformComponent", false, "GetRotationEulerRadians is deprecated, please use GetWorldRotation");
return m_worldTM.GetRotation().GetEulerRadians();
}
AZ::Quaternion TransformComponent::GetRotationQuaternion()
{
AZ_Warning("TransformComponent", false, "GetRotationQuaternion is deprecated, please use GetWorldRotationQuaternion");
return m_worldTM.GetRotation();
}
float TransformComponent::GetRotationX()
{
AZ_Warning("TransformComponent", false, "GetRotationX is deprecated, please use GetWorldRotation");
return GetRotationEulerRadians().GetX();
}
float TransformComponent::GetRotationY()
{
AZ_Warning("TransformComponent", false, "GetRotationY is deprecated, please use GetWorldRotation");
return GetRotationEulerRadians().GetY();
}
float TransformComponent::GetRotationZ()
{
AZ_Warning("TransformComponent", false, "GetRotationZ is deprecated, please use GetWorldRotation");
return GetRotationEulerRadians().GetZ();
}
AZ::Vector3 TransformComponent::GetWorldRotation()
{
return m_worldTM.GetRotation().GetEulerRadians();
@@ -492,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)
@@ -830,45 +733,7 @@ namespace AzFramework
->Event("GetLocalX", &AZ::TransformBus::Events::GetLocalX)
->Event("GetLocalY", &AZ::TransformBus::Events::GetLocalY)
->Event("GetLocalZ", &AZ::TransformBus::Events::GetLocalZ)
->Event("RotateByX", &AZ::TransformBus::Events::RotateByX)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("RotateByY", &AZ::TransformBus::Events::RotateByY)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("RotateByZ", &AZ::TransformBus::Events::RotateByZ)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetEulerRotation", &AZ::TransformBus::Events::SetRotation)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetRotationQuaternion", &AZ::TransformBus::Events::SetRotationQuaternion)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetRotationX", &AZ::TransformBus::Events::SetRotationX)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetRotationY", &AZ::TransformBus::Events::SetRotationY)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetRotationZ", &AZ::TransformBus::Events::SetRotationZ)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetEulerRotation", &AZ::TransformBus::Events::GetRotationEulerRadians)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetRotationQuaternion", &AZ::TransformBus::Events::GetRotationQuaternion)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetRotationX", &AZ::TransformBus::Events::GetRotationX)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetRotationY", &AZ::TransformBus::Events::GetRotationY)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("GetRotationZ", &AZ::TransformBus::Events::GetRotationZ)
->Attribute(AZ::Script::Attributes::Deprecated, true)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("SetWorldRotationQuaternion", &AZ::TransformBus::Events::SetWorldRotationQuaternion)
->Event("GetWorldRotation", &AZ::TransformBus::Events::GetWorldRotation)
->Event("GetWorldRotationQuaternion", &AZ::TransformBus::Events::GetWorldRotationQuaternion)
->Event("SetLocalRotation", &AZ::TransformBus::Events::SetLocalRotation)
@@ -880,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)
@@ -112,22 +112,7 @@ namespace AzFramework
float GetLocalZ() override;
// Rotation modifiers
void SetRotation(const AZ::Vector3& eulerAnglesRadian) override;
void SetRotationQuaternion(const AZ::Quaternion& quaternion) override;
void SetRotationX(float eulerAngleRadian) override;
void SetRotationY(float eulerAngleRadian) override;
void SetRotationZ(float eulerAngleRadian) override;
void RotateByX(float eulerAngleRadian) override;
void RotateByY(float eulerAngleRadian) override;
void RotateByZ(float eulerAngleRadian) override;
AZ::Vector3 GetRotationEulerRadians() override;
AZ::Quaternion GetRotationQuaternion() override;
float GetRotationX() override;
float GetRotationY() override;
float GetRotationZ() override;
void SetWorldRotationQuaternion(const AZ::Quaternion& quaternion) override;
AZ::Vector3 GetWorldRotation() override;
AZ::Quaternion GetWorldRotationQuaternion() override;
@@ -143,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;
@@ -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<Physics::MaterialId> { 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
@@ -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<AzPhysics::SceneHandle>;
//! 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<const AZ::Data::AssetId&>;
using OnMaterialLibraryChangedEvent = AZ::Event<const AZ::Data::AssetId&>;
enum class MaterialLibraryLoadErrorType : uint8_t
{
InvalidId,
ErrorLoading
};
//! Event that triggers when the default material library has loaded with errors.
using OnMaterialLibraryLoadErrorEvent = AZ::Event<MaterialLibraryLoadErrorType>;
//! Event that triggers when the default scene configuration changes.
//! When triggered the event will send the new default scene configuration.
@@ -18,6 +18,7 @@
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/std/containers/variant.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/limits.h>
#include <AzFramework/Physics/Common/PhysicsSimulatedBodyEvents.h>
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
#include <AzFramework/Physics/Common/PhysicsTypes.h>
@@ -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<uint32_t>::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();
@@ -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
;
}
@@ -13,6 +13,7 @@
#include <AzCore/RTTI/RTTI.h>
#include <AzFramework/Physics/Configuration/CollisionConfiguration.h>
#include <AzFramework/Physics/Material.h>
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<Physics::MaterialLibraryAsset> 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;
@@ -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<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<Physics::MaterialLibraryAssetReflectionWrapper>()
->Version(1)
->Field("Asset", &MaterialLibraryAssetReflectionWrapper::m_asset)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<Physics::MaterialLibraryAssetReflectionWrapper>("", "")
->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<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<Physics::DefaultMaterialLibraryAssetReflectionWrapper>()
serializeContext->Class<Physics::MaterialInfoReflectionWrapper>()
->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<Physics::DefaultMaterialLibraryAssetReflectionWrapper>("", "")
editContext->Class<Physics::MaterialInfoReflectionWrapper>("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<AZ::SerializeContext*>(context))
{
serializeContext->Class<Physics::MaterialSelection>()
->Version(2, &ClassConverters::MaterialSelectionConverter)
->Version(3, &ClassConverters::MaterialSelectionConverter)
->EventHandler<MaterialSelectionEventHandler>()
->Field("Material", &MaterialSelection::m_materialLibrary)
->Field("MaterialIds", &MaterialSelection::m_materialIdsAssignedToSlots)
;
@@ -381,14 +380,8 @@ namespace Physics
editContext->Class<Physics::MaterialSelection>("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<Physics::MaterialLibraryAsset>(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<Physics::MaterialLibraryAsset> MaterialSelection::LoadAsset() const
{
AZ::Data::Asset<MaterialLibraryAsset> asset = AZ::Data::AssetManager::Instance()
.GetAsset<Physics::MaterialLibraryAsset>(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<Physics::MaterialLibraryAsset>(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<Physics::MaterialLibraryAsset>& MaterialSelection::GetMaterialLibraryAsset() const
{
if (IsDefaultMaterialLibraryAsset())
{
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& defaultMaterialLibrary = GetDefaultMaterialLibrary();
return defaultMaterialLibrary;
}
return m_materialLibrary;
}
bool MaterialSelection::IsDefaultMaterialLibraryAsset() const
{
return !m_materialLibrary.GetId().IsValid();
}
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& MaterialSelection::GetDefaultMaterialLibrary()
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& MaterialSelection::GetMaterialLibrary()
{
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::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
@@ -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<Physics::Material> newMaterial = AZ::Interface<Physics::System>::Get()->CreateMaterial(materialProperties);
///
/// To get PxMaterial use GetNativePointer function
///
/// physx::PxMaterial* material = static_cast<physx::PxMaterial*>(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<MaterialFromAssetConfiguration> 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<Physics::MaterialLibraryAsset> m_asset =
Physics::MaterialConfiguration m_defaultMaterialConfiguration;
AZ::Data::Asset<Physics::MaterialLibraryAsset> 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<Physics::MaterialLibraryAsset> 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<Physics::MaterialId>& 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<Physics::MaterialLibraryAsset> m_materialLibrary { AZ::Data::AssetLoadBehavior::NoLoad };
AZStd::vector<Physics::MaterialId> m_materialIdsAssignedToSlots;
SlotsArray m_materialSlots;
bool m_slotsReadOnly = false;
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& GetMaterialLibraryAsset() const;
AZ::Data::Asset<Physics::MaterialLibraryAsset> LoadAsset() const;
bool IsDefaultMaterialLibraryAsset() const;
void SyncSelectionToMaterialLibrary();
static const AZ::Data::Asset<Physics::MaterialLibraryAsset>& GetDefaultMaterialLibrary();
static const AZ::Data::AssetId& GetDefaultMaterialLibraryId();
static const AZ::Data::Asset<Physics::MaterialLibraryAsset>& GetMaterialLibrary();
static const AZ::Data::AssetId& GetMaterialLibraryId();
bool AreMaterialSlotsReadOnly() const;
// EditorContext callbacks
AZ::u32 OnMaterialLibraryChanged();
AZStd::string GetMaterialSlotLabel(int index);
};
@@ -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<Physics::Material> 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<AZStd::weak_ptr<Physics::Material>>& outMaterials) = 0;
, AZStd::vector<AZStd::shared_ptr<Physics::Material>>& outMaterials) = 0;
/// Returns a weak pointer to physics material with the given id.
virtual AZStd::shared_ptr<Physics::Material> GetMaterialById(Physics::MaterialId id) = 0;
/// Returns a weak pointer to physics material with the given name.
virtual AZStd::weak_ptr<Physics::Material> GetMaterialByName(const AZStd::string& name) = 0;
virtual AZStd::shared_ptr<Physics::Material> 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<PhysicsMaterialRequests>;
@@ -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<Physics::MaterialLibraryAsset>& materialLibrary) = 0;
//! Accessor to get the current Material Library. This is also available in the PhysXSystemConfiguration.
virtual const AZ::Data::Asset<Physics::MaterialLibraryAsset>& 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
@@ -102,7 +102,7 @@ namespace Physics
/// Is the ragdoll currently simulated?
/// @result True in case the ragdoll is simulated, false if not.
virtual bool IsSimulated() = 0;
virtual bool IsSimulated() const = 0;
/// Writes the state for all of the bodies in the ragdoll to the provided output.
/// The caller owns the output state and can safely manipulate it without affecting the physics simulation.
@@ -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<AZ::SerializeContext*>(context))
@@ -166,10 +181,9 @@ namespace Physics
->RegisterGenericType<AZStd::shared_ptr<PhysicsAssetShapeConfiguration>>();
serializeContext->Class<PhysicsAssetShapeConfiguration, ShapeConfiguration>()
->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")
;
}
}
@@ -140,7 +140,7 @@ namespace Physics
AZ::Data::Asset<AZ::Data::AssetData> 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.
};
@@ -142,24 +142,12 @@ namespace Physics
virtual AZStd::shared_ptr<Shape> CreateShape(const ColliderConfiguration& colliderConfiguration, const ShapeConfiguration& configuration) = 0;
virtual AZStd::shared_ptr<Material> 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<Material> CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) = 0;
virtual AZStd::shared_ptr<Material> GetDefaultMaterial() = 0;
virtual AZStd::vector<AZStd::shared_ptr<Material>> 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
@@ -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);

Some files were not shown because too many files have changed in this diff Show More