Merge branch 'development' of https://github.com/o3de/o3de into jckand/LCXfailUpdate

monroegm-disable-blank-issue-2
jckand-amzn 4 years ago
commit 52ced4a4ee

@ -1 +0,0 @@
/autooptimizefile=0 /preset=Diffuse_lowQ

@ -1 +0,0 @@
/autooptimizefile=0 /mipmaps=0 /preset=AlbedoWithGenericAlpha /reduce=-1

@ -1 +0,0 @@
/autooptimizefile=0 /dns=1 /preset=Uncompressed

@ -1 +0,0 @@
/autooptimizefile=0 /preset=Uncompressed

@ -1 +0,0 @@
/autooptimizefile=0 /dns=1 /preset=Uncompressed

@ -1 +0,0 @@
/autooptimizefile=0 /dns=1 /preset=Uncompressed

@ -1 +0,0 @@
/autooptimizefile=0 /dns=1 /preset=Uncompressed

@ -1 +0,0 @@
/autooptimizefile=0 /dns=1 /preset=Uncompressed

@ -1 +0,0 @@
/autooptimizefile=0 /dns=1 /preset=Uncompressed

@ -125,17 +125,6 @@
<Class name="AZStd::string" field="Comment" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{941B5626-118F-55BC-925E-6E416A7520E4}">
<Class name="AZStd::string" field="value1" value="@devroot@/*.waf_files" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="FileTagData" field="value2" version="2" type="{5F66E43B-548B-4AA8-8CD8-F6924F6031E6}">
<Class name="unsigned char" field="FilePatternType" value="1" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/>
<Class name="AZStd::set" field="FileTags" type="{166F208E-DE97-53FE-B349-BDD9FE9B8693}">
<Class name="AZStd::string" field="element" value="ignore" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="AZStd::string" field="element" value="productdependency" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="AZStd::string" field="Comment" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{941B5626-118F-55BC-925E-6E416A7520E4}">
<Class name="AZStd::string" field="value1" value="*/editor/leveltemplates.xml" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="FileTagData" field="value2" version="2" type="{5F66E43B-548B-4AA8-8CD8-F6924F6031E6}">
@ -207,27 +196,6 @@
<Class name="AZStd::string" field="Comment" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{941B5626-118F-55BC-925E-6E416A7520E4}">
<Class name="AZStd::string" field="value1" value="@devroot@/*wscript" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="FileTagData" field="value2" version="2" type="{5F66E43B-548B-4AA8-8CD8-F6924F6031E6}">
<Class name="unsigned char" field="FilePatternType" value="1" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/>
<Class name="AZStd::set" field="FileTags" type="{166F208E-DE97-53FE-B349-BDD9FE9B8693}">
<Class name="AZStd::string" field="element" value="ignore" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="AZStd::string" field="element" value="productdependency" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="AZStd::string" field="Comment" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{941B5626-118F-55BC-925E-6E416A7520E4}">
<Class name="AZStd::string" field="value1" value=".*/assetprocessorplatformconfig.ini" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="FileTagData" field="value2" version="2" type="{5F66E43B-548B-4AA8-8CD8-F6924F6031E6}">
<Class name="unsigned char" field="FilePatternType" value="2" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/>
<Class name="AZStd::set" field="FileTags" type="{166F208E-DE97-53FE-B349-BDD9FE9B8693}">
<Class name="AZStd::string" field="element" value="editoronly" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="AZStd::string" field="Comment" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{941B5626-118F-55BC-925E-6E416A7520E4}">
<Class name="AZStd::string" field="value1" value=".*/gems?/?.*/gem.json" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="FileTagData" field="value2" version="2" type="{5F66E43B-548B-4AA8-8CD8-F6924F6031E6}">

@ -1 +0,0 @@
/autooptimizefile=0 /mipmaps=0 /preset=Albedo /reduce=-1 /ser=1

@ -1 +0,0 @@
/autooptimizefile=0 /preset=AlbedoWithGenericAlpha /reduce="android:2,ios:2,mac:0,pc:0,provo:0"

@ -1 +0,0 @@
/autooptimizefile=0 /preset=Albedo /reduce="android:3,ios:3,mac:0,pc:0,provo:0"

@ -3,9 +3,15 @@
"Version": 1,
"ClassName": "GlobalBuildOptions",
"ClassData": {
"ShaderCompilerArguments" : {
"DefaultMatrixOrder" : "Row",
"AzslcAdditionalFreeArguments" : "--strip-unused-srgs"
"ShaderCompilerArguments": {
"DefaultMatrixOrder": "Row",
"AzslcAdditionalFreeArguments": "--strip-unused-srgs"
},
"PreprocessorOptions": {
"predefinedMacros": [ "AZSL=17" ],
"projectIncludePaths": [
"Gems/AtomTressFX/Assets/Shaders"
]
}
}
}

@ -0,0 +1,162 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
import os, traceback, binascii, sys, json, pathlib
import azlmbr.math
import azlmbr.bus
#
# SceneAPI Processor
#
def log_exception_traceback():
exc_type, exc_value, exc_tb = sys.exc_info()
data = traceback.format_exception(exc_type, exc_value, exc_tb)
print(str(data))
def get_mesh_node_names(sceneGraph):
import azlmbr.scene as sceneApi
import azlmbr.scene.graph
from scene_api import scene_data as sceneData
meshDataList = []
node = sceneGraph.get_root()
children = []
paths = []
while node.IsValid():
# store children to process after siblings
if sceneGraph.has_node_child(node):
children.append(sceneGraph.get_node_child(node))
nodeName = sceneData.SceneGraphName(sceneGraph.get_node_name(node))
paths.append(nodeName.get_path())
# store any node that has mesh data content
nodeContent = sceneGraph.get_node_content(node)
if nodeContent.CastWithTypeName('MeshData'):
if sceneGraph.is_node_end_point(node) is False:
if (len(nodeName.get_path())):
meshDataList.append(sceneData.SceneGraphName(sceneGraph.get_node_name(node)))
# advance to next node
if sceneGraph.has_node_sibling(node):
node = sceneGraph.get_node_sibling(node)
elif children:
node = children.pop()
else:
node = azlmbr.scene.graph.NodeIndex()
return meshDataList, paths
def update_manifest(scene):
import json
import uuid, os
import azlmbr.scene as sceneApi
import azlmbr.scene.graph
from scene_api import scene_data as sceneData
graph = sceneData.SceneGraph(scene.graph)
# Get a list of all the mesh nodes, as well as all the nodes
mesh_name_list, all_node_paths = get_mesh_node_names(graph)
scene_manifest = sceneData.SceneManifest()
clean_filename = scene.sourceFilename.replace('.', '_')
# Compute the filename of the scene file
source_basepath = scene.watchFolder
source_relative_path = os.path.dirname(os.path.relpath(clean_filename, source_basepath))
source_filename_only = os.path.basename(clean_filename)
created_entities = []
# Loop every mesh node in the scene
for activeMeshIndex in range(len(mesh_name_list)):
mesh_name = mesh_name_list[activeMeshIndex]
mesh_path = mesh_name.get_path()
# Create a unique mesh group name using the filename + node name
mesh_group_name = '{}_{}'.format(source_filename_only, mesh_name.get_name())
# Remove forbidden filename characters from the name since this will become a file on disk later
mesh_group_name = "".join(char for char in mesh_group_name if char not in "|<>:\"/?*\\")
# Add the MeshGroup to the manifest and give it a unique ID
mesh_group = scene_manifest.add_mesh_group(mesh_group_name)
mesh_group['id'] = '{' + str(uuid.uuid5(uuid.NAMESPACE_DNS, source_filename_only + mesh_path)) + '}'
# Set our current node as the only node that is included in this MeshGroup
scene_manifest.mesh_group_select_node(mesh_group, mesh_path)
# Explicitly remove all other nodes to prevent implicit inclusions
for node in all_node_paths:
if node != mesh_path:
scene_manifest.mesh_group_unselect_node(mesh_group, node)
# Create an editor entity
entity_id = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "CreateEditorReadyEntity", mesh_group_name)
# Add an EditorMeshComponent to the entity
editor_mesh_component = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "GetOrAddComponentByTypeName", entity_id, "AZ::Render::EditorMeshComponent")
# Set the ModelAsset assetHint to the relative path of the input asset + the name of the MeshGroup we just created + the azmodel extension
# The MeshGroup we created will be output as a product in the asset's path named mesh_group_name.azmodel
# The assetHint will be converted to an AssetId later during prefab loading
json_update = json.dumps({
"Controller": { "Configuration": { "ModelAsset": {
"assetHint": os.path.join(source_relative_path, mesh_group_name) + ".azmodel" }}}
});
# Apply the JSON above to the component we created
result = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "UpdateComponentForEntity", entity_id, editor_mesh_component, json_update)
if not result:
raise RuntimeError("UpdateComponentForEntity failed")
# Keep track of the entity we set up, we'll add them all to the prefab we're creating later
created_entities.append(entity_id)
# Create a prefab with all our entities
prefab_filename = source_filename_only + ".prefab"
created_template_id = azlmbr.prefab.PrefabSystemScriptingBus(azlmbr.bus.Broadcast, "CreatePrefab", created_entities, prefab_filename)
if created_template_id == azlmbr.prefab.InvalidTemplateId:
raise RuntimeError("CreatePrefab {} failed".format(prefab_filename))
# Convert the prefab to a JSON string
output = azlmbr.prefab.PrefabLoaderScriptingBus(azlmbr.bus.Broadcast, "SaveTemplateToString", created_template_id)
if output.IsSuccess():
jsonString = output.GetValue()
uuid = azlmbr.math.Uuid_CreateRandom().ToString()
jsonResult = json.loads(jsonString)
# Add a PrefabGroup to the manifest and store the JSON on it
scene_manifest.add_prefab_group(source_filename_only, uuid, jsonResult)
else:
raise RuntimeError("SaveTemplateToString failed for template id {}, prefab {}".format(created_template_id, prefab_filename))
# Convert the manifest to a JSON string and return it
new_manifest = scene_manifest.export()
return new_manifest
sceneJobHandler = None
def on_update_manifest(args):
try:
scene = args[0]
return update_manifest(scene)
except RuntimeError as err:
print (f'ERROR - {err}')
log_exception_traceback()
global sceneJobHandler
sceneJobHandler = None
# try to create SceneAPI handler for processing
try:
import azlmbr.scene as sceneApi
if (sceneJobHandler == None):
sceneJobHandler = sceneApi.ScriptBuildingNotificationBusHandler()
sceneJobHandler.connect()
sceneJobHandler.add_callback('OnUpdateManifest', on_update_manifest)
except:
sceneJobHandler = None

@ -21,9 +21,9 @@ set(ENABLED_GEMS
QtForPython
PythonAssetBuilder
Metastream
Camera
EMotionFX
AtomTressFX
PhysX
CameraFramework
StartingPointMovement
@ -52,9 +52,6 @@ set(ENABLED_GEMS
AWSCore
AWSClientAuth
AWSMetrics
PrefabBuilder
AudioSystem
)

@ -6,12 +6,7 @@
#
#
################################################################################
# Atom Renderer: Automated Tests
# Runs EditorPythonBindings (hydra) scripts inside the Editor to verify test results for the Atom renderer.
################################################################################
if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedTesting IN_LIST LY_PROJECTS)
if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_add_pytest(
NAME AutomatedTesting::Atom_TestSuite_Main
TEST_SUITE main
@ -65,4 +60,18 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT
COMPONENT
Atom
)
ly_add_pytest(
NAME AutomatedTesting::Atom_TestSuite_Main_GPU_Optimized
TEST_SUITE main
TEST_REQUIRES gpu
TEST_SERIAL
TIMEOUT 1200
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main_GPU_Optimized.py
RUNTIME_DEPENDENCIES
AssetProcessor
AutomatedTesting.Assets
Editor
COMPONENT
Atom
)
endif()

@ -3,8 +3,6 @@ Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
Main suite tests for the Atom renderer.
"""
import logging
import os
@ -161,21 +159,6 @@ class TestAtomEditorComponentsMain(object):
"Display Mapper_test: Entity deleted: True",
"Display Mapper_test: UNDO entity deletion works: True",
"Display Mapper_test: REDO entity deletion works: True",
# Reflection Probe Component
"Reflection Probe Entity successfully created",
"Reflection Probe_test: Component added to the entity: True",
"Reflection Probe_test: Component removed after UNDO: True",
"Reflection Probe_test: Component added after REDO: True",
"Reflection Probe_test: Entered game mode: True",
"Reflection Probe_test: Exit game mode: True",
"Reflection Probe_test: Entity disabled initially: True",
"Reflection Probe_test: Entity enabled after adding required components: True",
"Reflection Probe_test: Cubemap is generated: True",
"Reflection Probe_test: Entity is hidden: True",
"Reflection Probe_test: Entity is shown: True",
"Reflection Probe_test: Entity deleted: True",
"Reflection Probe_test: UNDO entity deletion works: True",
"Reflection Probe_test: REDO entity deletion works: True",
]
unexpected_lines = [

@ -220,20 +220,18 @@ class TestPerformanceBenchmarkSuite(object):
@pytest.mark.system
class TestMaterialEditor(object):
@pytest.mark.parametrize("cfg_args", ["-rhi=dx12", "-rhi=Vulkan"])
@pytest.mark.parametrize("cfg_args,expected_lines", [
pytest.param("-rhi=dx12", ["Registering dx12 RHI"]),
pytest.param("-rhi=Vulkan", ["Registering vulkan RHI"])
])
@pytest.mark.parametrize("exe_file_name", ["MaterialEditor"])
def test_MaterialEditorLaunch_AllRHIOptionsSucceed(
self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name, cfg_args):
self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name, cfg_args,
expected_lines):
"""
Tests each valid RHI option (Null RHI excluded) can be launched with the MaterialEditor.
Checks for the "Finished loading viewport configurations." success message post launch.
Checks for the specific expected_lines messaging for each RHI type.
"""
expected_lines = ["Finished loading viewport configurations."]
unexpected_lines = [
# "Trace::Assert",
# "Trace::Error",
"Traceback (most recent call last):",
]
hydra.launch_and_validate_results(
request,
@ -243,7 +241,7 @@ class TestMaterialEditor(object):
run_python="--runpython",
timeout=60,
expected_lines=expected_lines,
unexpected_lines=unexpected_lines,
unexpected_lines=[],
halt_on_unexpected=False,
null_renderer=False,
cfg_args=[cfg_args],

@ -0,0 +1,43 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
import os
import pytest
import ly_test_tools.environment.file_system as file_system
from ly_test_tools.o3de.editor_test import EditorSharedTest, EditorTestSuite
from ly_test_tools.image.screenshot_compare_qssim import qssim as compare_screenshots
from .atom_utils.atom_component_helper import create_screenshots_archive, golden_images_directory
DEFAULT_SUBFOLDER_PATH = 'user/PythonTests/Automated/Screenshots'
@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.")
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
class TestAutomation(EditorTestSuite):
# Remove -autotest_mode from global_extra_cmdline_args since we need rendering for these tests.
global_extra_cmdline_args = ["-BatchMode"] # Default is ["-BatchMode", "-autotest_mode"]
class AtomGPU_BasicLevelSetup_SetsUpLevel(EditorSharedTest):
use_null_renderer = False # Default is True
screenshot_name = "AtomBasicLevelSetup.ppm"
test_screenshots = [] # Gets set by setup()
screenshot_directory = "" # Gets set by setup()
# Clear existing test screenshots before starting test.
def setup(self, workspace):
screenshot_directory = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH)
test_screenshots = [os.path.join(screenshot_directory, self.screenshot_name)]
file_system.delete(test_screenshots, True, True)
from Atom.tests import hydra_AtomGPU_BasicLevelSetup as test_module
golden_images = [os.path.join(golden_images_directory(), screenshot_name)]
for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images):
compare_screenshots(test_screenshot, golden_screenshot)
create_screenshots_archive(screenshot_directory)

@ -14,33 +14,54 @@ from ly_test_tools.o3de.editor_test import EditorSharedTest, EditorTestSuite
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
class TestAutomation(EditorTestSuite):
@pytest.mark.test_case_id("C32078118")
class AtomEditorComponents_DecalAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_DecalAdded as test_module
@pytest.mark.test_case_id("C32078119")
class AtomEditorComponents_DepthOfFieldAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_DepthOfFieldAdded as test_module
@pytest.mark.test_case_id("C32078120")
class AtomEditorComponents_DirectionalLightAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_DirectionalLightAdded as test_module
@pytest.mark.test_case_id("C32078121")
class AtomEditorComponents_ExposureControlAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_ExposureControlAdded as test_module
@pytest.mark.test_case_id("C32078115")
class AtomEditorComponents_GlobalSkylightIBLAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_GlobalSkylightIBLAdded as test_module
@pytest.mark.test_case_id("C32078125")
class AtomEditorComponents_PhysicalSkyAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_PhysicalSkyAdded as test_module
@pytest.mark.test_case_id("C32078131")
class AtomEditorComponents_PostFXRadiusWeightModifierAdded(EditorSharedTest):
from Atom.tests import (
hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded as test_module)
@pytest.mark.test_case_id("C32078117")
class AtomEditorComponents_LightAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_LightAdded as test_module
@pytest.mark.test_case_id("C36525660")
class AtomEditorComponents_DisplayMapperAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_DisplayMapperAdded as test_module
@pytest.mark.test_case_id("C32078128")
class AtomEditorComponents_ReflectionProbeAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_ReflectionProbeAdded as test_module
@pytest.mark.test_case_id("C32078124")
class AtomEditorComponents_MeshAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_MeshAdded as test_module
@pytest.mark.test_case_id("C32078123")
class AtomEditorComponents_MaterialAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_MaterialAdded as test_module
class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest):
from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module

@ -3,12 +3,17 @@ Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
Sandbox suite tests for the Atom renderer.
"""
import logging
import os
import pytest
import editor_python_test_tools.hydra_test_utils as hydra
logger = logging.getLogger(__name__)
TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "tests")
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@ -18,3 +23,49 @@ class TestAtomEditorComponentsSandbox(object):
# It requires at least one test
def test_Dummy(self, request, editor, level, workspace, project, launcher_platform):
pass
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("level", ["auto_test"])
class TestAtomEditorComponentsMain(object):
"""Holds tests for Atom components."""
def test_AtomEditorComponents_ReflectionProbeAddedToEntity(
self, request, editor, level, workspace, project, launcher_platform):
"""
Please review the hydra script run by this test for more specific test info.
Tests the following Atom components and verifies all "expected_lines" appear in Editor.log:
1. Reflection Probe
"""
cfg_args = [level]
expected_lines = [
# Reflection Probe Component
"Reflection Probe Entity successfully created",
"Reflection Probe_test: Component added to the entity: True",
"Reflection Probe_test: Component removed after UNDO: True",
"Reflection Probe_test: Component added after REDO: True",
"Reflection Probe_test: Entered game mode: True",
"Reflection Probe_test: Exit game mode: True",
"Reflection Probe_test: Entity disabled initially: True",
"Reflection Probe_test: Entity enabled after adding required components: True",
"Reflection Probe_test: Cubemap is generated: True",
"Reflection Probe_test: Entity is hidden: True",
"Reflection Probe_test: Entity is shown: True",
"Reflection Probe_test: Entity deleted: True",
"Reflection Probe_test: UNDO entity deletion works: True",
"Reflection Probe_test: REDO entity deletion works: True",
]
hydra.launch_and_validate_results(
request,
TEST_DIRECTORY,
editor,
"hydra_AtomEditorComponents_AddedToEntity.py",
timeout=120,
expected_lines=expected_lines,
unexpected_lines=[],
halt_on_unexpected=True,
null_renderer=True,
cfg_args=cfg_args,
)

@ -3,13 +3,54 @@ Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright
SPDX-License-Identifier: Apache-2.0 OR MIT
File to assist with common hydra component functions used across various Atom tests.
"""
import datetime
import os
import zipfile
from editor_python_test_tools.editor_test_helper import EditorTestHelper
helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper")
def create_screenshots_archive(screenshot_path):
"""
Creates a new zip file archive at archive_path containing all files listed within archive_path.
:param screenshot_path: location containing the files to archive, the zip archive file will also be saved here.
:return: None, but creates a new zip file archive inside path containing all of the files inside archive_path.
"""
files_to_archive = []
# Search for .png and .ppm files to add to the zip archive file.
for (folder_name, sub_folders, file_names) in os.walk(screenshot_path):
for file_name in file_names:
if file_name.endswith(".png") or file_name.endswith(".ppm"):
file_path = os.path.join(folder_name, file_name)
files_to_archive.append(file_path)
# Setup variables for naming the zip archive file.
timestamp = datetime.datetime.now().timestamp()
formatted_timestamp = datetime.datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d_%H-%M-%S")
screenshots_file = os.path.join(screenshot_path, f'screenshots_{formatted_timestamp}.zip')
# Write all of the valid .png and .ppm files to the archive file.
with zipfile.ZipFile(screenshots_file, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zip_archive:
for file_path in files_to_archive:
file_name = os.path.basename(file_path)
zip_archive.write(file_path, file_name)
def golden_images_directory():
"""
Uses this file location to return the valid location for golden image files.
:return: The path to the golden_images directory, but raises an IOError if the golden_images directory is missing.
"""
current_file_directory = os.path.join(os.path.dirname(__file__))
golden_images_dir = os.path.join(current_file_directory, '..', 'golden_images')
if not os.path.exists(golden_images_dir):
raise IOError(
f'golden_images" directory was not found at path "{golden_images_dir}"'
f'Please add a "golden_images" directory inside: "{current_file_directory}"'
)
return golden_images_dir
def create_basic_atom_level(level_name):
@ -31,6 +72,9 @@ def create_basic_atom_level(level_name):
import azlmbr.object
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.editor_test_helper import EditorTestHelper
helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper")
# Create a new level.
new_level_name = level_name

@ -211,7 +211,7 @@ class Timeout:
return time.time() > self.die_after
screenshotsFolder = os.path.join(azlmbr.paths.devroot, "AtomTest", "Cache" "pc", "Screenshots")
screenshotsFolder = os.path.join(azlmbr.paths.products, "Screenshots")
class ScreenshotHelper:

@ -17,7 +17,7 @@ import azlmbr.legacy.general as general
import azlmbr.editor as editor
import azlmbr.render as render
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import TestHelper

@ -14,7 +14,7 @@ import azlmbr.math as math
import azlmbr.paths
import azlmbr.legacy.general as general
sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests"))
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
import editor_python_test_tools.hydra_editor_utils as hydra
from Atom.atom_utils.atom_constants import LIGHT_TYPES

@ -0,0 +1,205 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
class Tests:
creation_undo = (
"UNDO Entity creation success",
"UNDO Entity creation failed")
creation_redo = (
"REDO Entity creation success",
"REDO Entity creation failed")
material_creation = (
"Material Entity successfully created",
"Material Entity failed to be created")
material_component = (
"Entity has a Material component",
"Entity failed to find Material component")
material_disabled = (
"Material component disabled",
"Material component was not disabled.")
actor_component = (
"Entity has an Actor component",
"Entity did not have an Actor component")
actor_undo = (
"Entity Actor component gone",
"Entity Actor component add failed to undo")
mesh_component = (
"Entity has a Mesh component",
"Entity did not have a Mesh component")
material_enabled = (
"Material component enabled",
"Material component was not enabled.")
enter_game_mode = (
"Entered game mode",
"Failed to enter game mode")
exit_game_mode = (
"Exited game mode",
"Couldn't exit game mode")
is_visible = (
"Entity is visible",
"Entity was not visible")
is_hidden = (
"Entity is hidden",
"Entity was not hidden")
entity_deleted = (
"Entity deleted",
"Entity was not deleted")
deletion_undo = (
"UNDO deletion success",
"UNDO deletion failed")
deletion_redo = (
"REDO deletion success",
"REDO deletion failed")
def AtomEditorComponents_Material_AddedToEntity():
"""
Summary:
Tests the Material component can be added to an entity and has the expected functionality.
Test setup:
- Wait for Editor idle loop.
- Open the "Base" level.
Expected Behavior:
The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
Creation and deletion undo/redo should also work.
Test Steps:
1) Create a Material entity with no components.
2) Add a Material component to Material entity.
3) UNDO the entity creation and component addition.
4) REDO the entity creation and component addition.
5) Verify Material component not enabled.
6) Add Actor component since it is required by the Material component.
7) Verify Material component is enabled.
8) UNDO add Actor component
9) Verify Material component not enabled.
10) Add Mesh component since it is required by the Material component.
11) Verify Material component is enabled.
12) Enter/Exit game mode.
13) Test IsHidden.
14) Test IsVisible.
15) Delete Material entity.
16) UNDO deletion.
17) REDO deletion.
18) Look for errors.
:return: None
"""
import azlmbr.legacy.general as general
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.utils import Report, Tracer, TestHelper
with Tracer() as error_tracer:
# Test setup begins.
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
TestHelper.init_idle()
TestHelper.open_level("", "Base")
# Test steps begin.
# 1. Create a Material entity with no components.
material_name = "Material"
material_entity = EditorEntity.create_editor_entity(material_name)
Report.critical_result(Tests.material_creation, material_entity.exists())
# 2. Add a Material component to Material entity.
material_component = material_entity.add_component(material_name)
Report.critical_result(
Tests.material_component,
material_entity.has_component(material_name))
# 3. UNDO the entity creation and component addition.
# -> UNDO component addition.
general.undo()
# -> UNDO naming entity.
general.undo()
# -> UNDO selecting entity.
general.undo()
# -> UNDO entity creation.
general.undo()
general.idle_wait_frames(1)
Report.result(Tests.creation_undo, not material_entity.exists())
# 4. REDO the entity creation and component addition.
# -> REDO entity creation.
general.redo()
# -> REDO selecting entity.
general.redo()
# -> REDO naming entity.
general.redo()
# -> REDO component addition.
general.redo()
general.idle_wait_frames(1)
Report.result(Tests.creation_redo, material_entity.exists())
# 5. Verify Material component not enabled.
Report.result(Tests.material_disabled, not material_component.is_enabled())
# 6. Add Actor component since it is required by the Material component.
actor_name = "Actor"
material_entity.add_component(actor_name)
Report.result(Tests.actor_component, material_entity.has_component(actor_name))
# 7. Verify Material component is enabled.
Report.result(Tests.material_enabled, material_component.is_enabled())
# 8. UNDO component addition.
general.undo()
general.idle_wait_frames(1)
Report.result(Tests.actor_undo, not material_entity.has_component(actor_name))
# 9. Verify Material component not enabled.
Report.result(Tests.material_disabled, not material_component.is_enabled())
# 10. Add Mesh component since it is required by the Material component.
mesh_name = "Mesh"
material_entity.add_component(mesh_name)
Report.result(Tests.mesh_component, material_entity.has_component(mesh_name))
# 11. Verify Material component is enabled.
Report.result(Tests.material_enabled, material_component.is_enabled())
# 12. Enter/Exit game mode.
TestHelper.enter_game_mode(Tests.enter_game_mode)
general.idle_wait_frames(1)
TestHelper.exit_game_mode(Tests.exit_game_mode)
# 13. Test IsHidden.
material_entity.set_visibility_state(False)
Report.result(Tests.is_hidden, material_entity.is_hidden() is True)
# 14. Test IsVisible.
material_entity.set_visibility_state(True)
general.idle_wait_frames(1)
Report.result(Tests.is_visible, material_entity.is_visible() is True)
# 15. Delete Material entity.
material_entity.delete()
Report.result(Tests.entity_deleted, not material_entity.exists())
# 16. UNDO deletion.
general.undo()
Report.result(Tests.deletion_undo, material_entity.exists())
# 17. REDO deletion.
general.redo()
Report.result(Tests.deletion_redo, not material_entity.exists())
# 18. Look for errors or asserts.
TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
for error_info in error_tracer.errors:
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
for assert_info in error_tracer.asserts:
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(AtomEditorComponents_Material_AddedToEntity)

@ -0,0 +1,171 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
class Tests:
creation_undo = (
"UNDO Entity creation success",
"UNDO Entity creation failed")
creation_redo = (
"REDO Entity creation success",
"REDO Entity creation failed")
mesh_entity_creation = (
"Mesh Entity successfully created",
"Mesh Entity failed to be created")
mesh_component_added = (
"Entity has a Mesh component",
"Entity failed to find Mesh component")
mesh_asset_specified = (
"Mesh asset set",
"Mesh asset not set")
enter_game_mode = (
"Entered game mode",
"Failed to enter game mode")
exit_game_mode = (
"Exited game mode",
"Couldn't exit game mode")
is_visible = (
"Entity is visible",
"Entity was not visible")
is_hidden = (
"Entity is hidden",
"Entity was not hidden")
entity_deleted = (
"Entity deleted",
"Entity was not deleted")
deletion_undo = (
"UNDO deletion success",
"UNDO deletion failed")
deletion_redo = (
"REDO deletion success",
"REDO deletion failed")
def AtomEditorComponents_Mesh_AddedToEntity():
"""
Summary:
Tests the Mesh component can be added to an entity and has the expected functionality.
Test setup:
- Wait for Editor idle loop.
- Open the "Base" level.
Expected Behavior:
The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
Creation and deletion undo/redo should also work.
Test Steps:
1) Create a Mesh entity with no components.
2) Add a Mesh component to Mesh entity.
3) UNDO the entity creation and component addition.
4) REDO the entity creation and component addition.
5) Specify the Mesh component asset
6) Enter/Exit game mode.
7) Test IsHidden.
8) Test IsVisible.
9) Delete Mesh entity.
10) UNDO deletion.
11) REDO deletion.
12) Look for errors.
:return: None
"""
import os
import azlmbr.legacy.general as general
from editor_python_test_tools.asset_utils import Asset
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper
with Tracer() as error_tracer:
# Test setup begins.
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
helper.init_idle()
helper.open_level("", "Base")
# Test steps begin.
# 1. Create a Mesh entity with no components.
mesh_name = "Mesh"
mesh_entity = EditorEntity.create_editor_entity(mesh_name)
Report.critical_result(Tests.mesh_entity_creation, mesh_entity.exists())
# 2. Add a Mesh component to Mesh entity.
mesh_component = mesh_entity.add_component(mesh_name)
Report.critical_result(
Tests.mesh_component_added,
mesh_entity.has_component(mesh_name))
# 3. UNDO the entity creation and component addition.
# -> UNDO component addition.
general.undo()
# -> UNDO naming entity.
general.undo()
# -> UNDO selecting entity.
general.undo()
# -> UNDO entity creation.
general.undo()
general.idle_wait_frames(1)
Report.result(Tests.creation_undo, not mesh_entity.exists())
# 4. REDO the entity creation and component addition.
# -> REDO entity creation.
general.redo()
# -> REDO selecting entity.
general.redo()
# -> REDO naming entity.
general.redo()
# -> REDO component addition.
general.redo()
general.idle_wait_frames(1)
Report.result(Tests.creation_redo, mesh_entity.exists())
# 5. Set Mesh component asset property
mesh_property_asset = 'Controller|Configuration|Mesh Asset'
model_path = os.path.join('Objects', 'shaderball', 'shaderball_default_1m.azmodel')
model = Asset.find_asset_by_path(model_path)
mesh_component.set_component_property_value(mesh_property_asset, model.id)
Report.result(Tests.mesh_asset_specified,
mesh_component.get_component_property_value(mesh_property_asset) == model.id)
# 6. Enter/Exit game mode.
helper.enter_game_mode(Tests.enter_game_mode)
general.idle_wait_frames(1)
helper.exit_game_mode(Tests.exit_game_mode)
# 7. Test IsHidden.
mesh_entity.set_visibility_state(False)
Report.result(Tests.is_hidden, mesh_entity.is_hidden() is True)
# 8. Test IsVisible.
mesh_entity.set_visibility_state(True)
general.idle_wait_frames(1)
Report.result(Tests.is_visible, mesh_entity.is_visible() is True)
# 9. Delete Mesh entity.
mesh_entity.delete()
Report.result(Tests.entity_deleted, not mesh_entity.exists())
# 10. UNDO deletion.
general.undo()
Report.result(Tests.deletion_undo, mesh_entity.exists())
# 11. REDO deletion.
general.redo()
Report.result(Tests.deletion_redo, not mesh_entity.exists())
# 12. Look for errors or asserts.
helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
for error_info in error_tracer.errors:
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
for assert_info in error_tracer.asserts:
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(AtomEditorComponents_Mesh_AddedToEntity)

@ -0,0 +1,194 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
class Tests:
creation_undo = (
"UNDO Entity creation success",
"UNDO Entity creation failed")
creation_redo = (
"REDO Entity creation success",
"REDO Entity creation failed")
reflection_probe_creation = (
"Reflection Probe Entity successfully created",
"Reflection Probe Entity failed to be created")
reflection_probe_component = (
"Entity has a Reflection Probe component",
"Entity failed to find Reflection Probe component")
reflection_probe_disabled = (
"Reflection Probe component disabled",
"Reflection Probe component was not disabled.")
reflection_map_generated = (
"Reflection Probe cubemap generated",
"Reflection Probe cubemap not generated")
box_shape_component = (
"Entity has a Box Shape component",
"Entity did not have a Box Shape component")
reflection_probe_enabled = (
"Reflection Probe component enabled",
"Reflection Probe component was not enabled.")
enter_game_mode = (
"Entered game mode",
"Failed to enter game mode")
exit_game_mode = (
"Exited game mode",
"Couldn't exit game mode")
is_visible = (
"Entity is visible",
"Entity was not visible")
is_hidden = (
"Entity is hidden",
"Entity was not hidden")
entity_deleted = (
"Entity deleted",
"Entity was not deleted")
deletion_undo = (
"UNDO deletion success",
"UNDO deletion failed")
deletion_redo = (
"REDO deletion success",
"REDO deletion failed")
def AtomEditorComponents_ReflectionProbe_AddedToEntity():
"""
Summary:
Tests the Reflection Probe component can be added to an entity and has the expected functionality.
Test setup:
- Wait for Editor idle loop.
- Open the "Base" level.
Expected Behavior:
The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
Creation and deletion undo/redo should also work.
Test Steps:
1) Create a Reflection Probe entity with no components.
2) Add a Reflection Probe component to Reflection Probe entity.
3) UNDO the entity creation and component addition.
4) REDO the entity creation and component addition.
5) Verify Reflection Probe component not enabled.
6) Add Shape component since it is required by the Reflection Probe component.
7) Verify Reflection Probe component is enabled.
8) Enter/Exit game mode.
9) Test IsHidden.
10) Test IsVisible.
11) Verify cubemap generation
12) Delete Reflection Probe entity.
13) UNDO deletion.
14) REDO deletion.
15) Look for errors.
:return: None
"""
import azlmbr.legacy.general as general
import azlmbr.math as math
import azlmbr.render as render
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper
with Tracer() as error_tracer:
# Test setup begins.
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
helper.init_idle()
helper.open_level("", "Base")
# Test steps begin.
# 1. Create a Reflection Probe entity with no components.
reflection_probe_name = "Reflection Probe"
reflection_probe_entity = EditorEntity.create_editor_entity_at(
math.Vector3(512.0, 512.0, 34.0), reflection_probe_name)
Report.critical_result(Tests.reflection_probe_creation, reflection_probe_entity.exists())
# 2. Add a Reflection Probe component to Reflection Probe entity.
reflection_probe_component = reflection_probe_entity.add_component(reflection_probe_name)
Report.critical_result(
Tests.reflection_probe_component,
reflection_probe_entity.has_component(reflection_probe_name))
# 3. UNDO the entity creation and component addition.
# -> UNDO component addition.
general.undo()
# -> UNDO naming entity.
general.undo()
# -> UNDO selecting entity.
general.undo()
# -> UNDO entity creation.
general.undo()
general.idle_wait_frames(1)
Report.result(Tests.creation_undo, not reflection_probe_entity.exists())
# 4. REDO the entity creation and component addition.
# -> REDO entity creation.
general.redo()
# -> REDO selecting entity.
general.redo()
# -> REDO naming entity.
general.redo()
# -> REDO component addition.
general.redo()
general.idle_wait_frames(1)
Report.result(Tests.creation_redo, reflection_probe_entity.exists())
# 5. Verify Reflection Probe component not enabled.
Report.result(Tests.reflection_probe_disabled, not reflection_probe_component.is_enabled())
# 6. Add Box Shape component since it is required by the Reflection Probe component.
box_shape = "Box Shape"
reflection_probe_entity.add_component(box_shape)
Report.result(Tests.box_shape_component, reflection_probe_entity.has_component(box_shape))
# 7. Verify Reflection Probe component is enabled.
Report.result(Tests.reflection_probe_enabled, reflection_probe_component.is_enabled())
# 8. Enter/Exit game mode.
helper.enter_game_mode(Tests.enter_game_mode)
general.idle_wait_frames(1)
helper.exit_game_mode(Tests.exit_game_mode)
# 9. Test IsHidden.
reflection_probe_entity.set_visibility_state(False)
Report.result(Tests.is_hidden, reflection_probe_entity.is_hidden() is True)
# 10. Test IsVisible.
reflection_probe_entity.set_visibility_state(True)
general.idle_wait_frames(1)
Report.result(Tests.is_visible, reflection_probe_entity.is_visible() is True)
# 11. Verify cubemap generation
render.EditorReflectionProbeBus(azlmbr.bus.Event, "BakeReflectionProbe", reflection_probe_entity.id)
Report.result(
Tests.reflection_map_generated,
helper.wait_for_condition(
lambda: reflection_probe_component.get_component_property_value("Cubemap|Baked Cubemap Path") != "",
20.0))
# 12. Delete Reflection Probe entity.
reflection_probe_entity.delete()
Report.result(Tests.entity_deleted, not reflection_probe_entity.exists())
# 13. UNDO deletion.
general.undo()
Report.result(Tests.deletion_undo, reflection_probe_entity.exists())
# 14. REDO deletion.
general.redo()
Report.result(Tests.deletion_redo, not reflection_probe_entity.exists())
# 15. Look for errors or asserts.
helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
for error_info in error_tracer.errors:
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
for assert_info in error_tracer.asserts:
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(AtomEditorComponents_ReflectionProbe_AddedToEntity)

@ -0,0 +1,292 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# fmt: off
class Tests :
camera_component_added = ("Camera component was added", "Camera component wasn't added")
camera_fov_set = ("Camera component FOV property set", "Camera component FOV property wasn't set")
directional_light_component_added = ("Directional Light component added", "Directional Light component wasn't added")
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
global_skylight_component_added = ("Global Skylight (IBL) component added", "Global Skylight (IBL) component wasn't added")
global_skylight_diffuse_image_set = ("Global Skylight Diffuse Image property set", "Global Skylight Diffuse Image property wasn't set")
global_skylight_specular_image_set = ("Global Skylight Specular Image property set", "Global Skylight Specular Image property wasn't set")
ground_plane_material_asset_set = ("Ground Plane Material Asset was set", "Ground Plane Material Asset wasn't set")
ground_plane_material_component_added = ("Ground Plane Material component added", "Ground Plane Material component wasn't added")
ground_plane_mesh_asset_set = ("Ground Plane Mesh Asset property was set", "Ground Plane Mesh Asset property wasn't set")
hdri_skybox_component_added = ("HDRi Skybox component added", "HDRi Skybox component wasn't added")
hdri_skybox_cubemap_texture_set = ("HDRi Skybox Cubemap Texture property set", "HDRi Skybox Cubemap Texture property wasn't set")
mesh_component_added = ("Mesh component added", "Mesh component wasn't added")
no_assert_occurred = ("No asserts detected", "Asserts were detected")
no_error_occurred = ("No errors detected", "Errors were detected")
secondary_grid_spacing = ("Secondary Grid Spacing set", "Secondary Grid Spacing not set")
sphere_material_component_added = ("Sphere Material component added", "Sphere Material component wasn't added")
sphere_material_set = ("Sphere Material Asset was set", "Sphere Material Asset wasn't set")
sphere_mesh_asset_set = ("Sphere Mesh Asset was set", "Sphere Mesh Asset wasn't set")
viewport_set = ("Viewport set to correct size", "Viewport not set to correct size")
# fmt: on
def AtomGPU_BasicLevelSetup_SetsUpLevel():
"""
Summary:
Sets up a level to match the AtomBasicLevelSetup.ppm golden image then takes a screenshot to verify the setup.
Test setup:
- Wait for Editor idle loop.
- Open the "Base" level.
Expected Behavior:
The scene can be setup for a basic level.
The test screenshot matches the appearance of the AtomBasicLevelSetup.ppm golden image.
Test Steps:
1. Close error windows and display helpers then update the viewport size.
2. Create Default Level Entity.
3. Create Grid Entity as a child entity of the Default Level Entity.
4. Add Grid component to Grid Entity and set Secondary Grid Spacing.
5. Create Global Skylight (IBL) Entity as a child entity of the Default Level Entity.
6. Add HDRi Skybox component to the Global Skylight (IBL) Entity.
7. Add Global Skylight (IBL) component to the Global Skylight (IBL) Entity.
8. Set the Cubemap Texture property of the HDRi Skybox component.
9. Set the Diffuse Image property of the Global Skylight (IBL) component.
10. Set the Specular Image property of the Global Skylight (IBL) component.
11. Create a Ground Plane Entity with a Material component that is a child entity of the Default Level Entity.
12. Set the Material Asset property of the Material component for the Ground Plane Entity.
13. Add the Mesh component to the Ground Plane Entity and set the Mesh component Mesh Asset property.
14. Create a Directional Light Entity as a child entity of the Default Level Entity.
15. Add Directional Light component to Directional Light Entity and set entity rotation.
16. Create a Sphere Entity as a child entity of the Default Level Entity then add a Material component.
17. Set the Material Asset property of the Material component for the Sphere Entity.
18. Add Mesh component to Sphere Entity and set the Mesh Asset property for the Mesh component.
19. Create a Camera Entity as a child entity of the Default Level Entity then add a Camera component.
20. Set the Camera Entity rotation value and set the Camera component Field of View value.
21. Enter game mode.
22. Take screenshot.
23. Exit game mode.
24. Look for errors.
:return: None
"""
import os
from math import isclose
import azlmbr.asset as asset
import azlmbr.bus as bus
import azlmbr.legacy.general as general
import azlmbr.math as math
import azlmbr.paths
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper
from Atom.atom_utils.screenshot_utils import ScreenshotHelper
MATERIAL_COMPONENT_NAME = "Material"
MESH_COMPONENT_NAME = "Mesh"
SCREENSHOT_NAME = "AtomBasicLevelSetup"
SCREEN_WIDTH = 1280
SCREEN_HEIGHT = 720
DEGREE_RADIAN_FACTOR = 0.0174533
def initial_viewport_setup(screen_width, screen_height):
general.set_viewport_size(screen_width, screen_height)
general.update_viewport()
result = isclose(
a=general.get_viewport_size().x, b=SCREEN_WIDTH, rel_tol=0.1) and isclose(
a=general.get_viewport_size().y, b=SCREEN_HEIGHT, rel_tol=0.1)
return result
with Tracer() as error_tracer:
# Test setup begins.
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
helper.init_idle()
helper.open_level("", "Base")
# Test steps begin.
# 1. Close error windows and display helpers then update the viewport size.
helper.close_error_windows()
helper.close_display_helpers()
general.update_viewport()
Report.critical_result(Tests.viewport_set, initial_viewport_setup(SCREEN_WIDTH, SCREEN_HEIGHT))
# 2. Create Default Level Entity.
default_level_entity_name = "Default Level"
default_level_entity = EditorEntity.create_editor_entity_at(
math.Vector3(0.0, 0.0, 0.0), default_level_entity_name)
# 3. Create Grid Entity as a child entity of the Default Level Entity.
grid_name = "Grid"
grid_entity = EditorEntity.create_editor_entity(grid_name, default_level_entity.id)
# 4. Add Grid component to Grid Entity and set Secondary Grid Spacing.
grid_component = grid_entity.add_component(grid_name)
secondary_grid_spacing_property = "Controller|Configuration|Secondary Grid Spacing"
secondary_grid_spacing_value = 1.0
grid_component.set_component_property_value(secondary_grid_spacing_property, secondary_grid_spacing_value)
secondary_grid_spacing_set = grid_component.get_component_property_value(
secondary_grid_spacing_property) == secondary_grid_spacing_value
Report.result(Tests.secondary_grid_spacing, secondary_grid_spacing_set)
# 5. Create Global Skylight (IBL) Entity as a child entity of the Default Level Entity.
global_skylight_name = "Global Skylight (IBL)"
global_skylight_entity = EditorEntity.create_editor_entity(global_skylight_name, default_level_entity.id)
# 6. Add HDRi Skybox component to the Global Skylight (IBL) Entity.
hdri_skybox_name = "HDRi Skybox"
hdri_skybox_component = global_skylight_entity.add_component(hdri_skybox_name)
Report.result(Tests.hdri_skybox_component_added, global_skylight_entity.has_component(hdri_skybox_name))
# 7. Add Global Skylight (IBL) component to the Global Skylight (IBL) Entity.
global_skylight_component = global_skylight_entity.add_component(global_skylight_name)
Report.result(Tests.global_skylight_component_added, global_skylight_entity.has_component(global_skylight_name))
# 8. Set the Cubemap Texture property of the HDRi Skybox component.
global_skylight_image_asset_path = os.path.join(
"LightingPresets", "greenwich_park_02_4k_iblskyboxcm_iblspecular.exr.streamingimage")
global_skylight_image_asset = asset.AssetCatalogRequestBus(
bus.Broadcast, "GetAssetIdByPath", global_skylight_image_asset_path, math.Uuid(), False)
hdri_skybox_cubemap_texture_property = "Controller|Configuration|Cubemap Texture"
hdri_skybox_component.set_component_property_value(
hdri_skybox_cubemap_texture_property, global_skylight_image_asset)
Report.result(
Tests.hdri_skybox_cubemap_texture_set,
hdri_skybox_component.get_component_property_value(
hdri_skybox_cubemap_texture_property) == global_skylight_image_asset)
# 9. Set the Diffuse Image property of the Global Skylight (IBL) component.
# Re-use the same image that was used in the previous test step.
global_skylight_diffuse_image_property = "Controller|Configuration|Diffuse Image"
global_skylight_component.set_component_property_value(
global_skylight_diffuse_image_property, global_skylight_image_asset)
Report.result(
Tests.global_skylight_diffuse_image_set,
global_skylight_component.get_component_property_value(
global_skylight_diffuse_image_property) == global_skylight_image_asset)
# 10. Set the Specular Image property of the Global Skylight (IBL) component.
# Re-use the same image that was used in the previous test step.
global_skylight_specular_image_property = "Controller|Configuration|Specular Image"
global_skylight_component.set_component_property_value(
global_skylight_specular_image_property, global_skylight_image_asset)
global_skylight_specular_image_set = global_skylight_component.get_component_property_value(
global_skylight_specular_image_property)
Report.result(
Tests.global_skylight_specular_image_set, global_skylight_specular_image_set == global_skylight_image_asset)
# 11. Create a Ground Plane Entity with a Material component that is a child entity of the Default Level Entity.
ground_plane_name = "Ground Plane"
ground_plane_entity = EditorEntity.create_editor_entity(ground_plane_name, default_level_entity.id)
ground_plane_material_component = ground_plane_entity.add_component(MATERIAL_COMPONENT_NAME)
Report.result(
Tests.ground_plane_material_component_added, ground_plane_entity.has_component(MATERIAL_COMPONENT_NAME))
# 12. Set the Material Asset property of the Material component for the Ground Plane Entity.
ground_plane_entity.set_local_uniform_scale(32.0)
ground_plane_material_asset_path = os.path.join("Materials", "Presets", "PBR", "metal_chrome.azmaterial")
ground_plane_material_asset = asset.AssetCatalogRequestBus(
bus.Broadcast, "GetAssetIdByPath", ground_plane_material_asset_path, math.Uuid(), False)
ground_plane_material_asset_property = "Default Material|Material Asset"
ground_plane_material_component.set_component_property_value(
ground_plane_material_asset_property, ground_plane_material_asset)
Report.result(
Tests.ground_plane_material_asset_set,
ground_plane_material_component.get_component_property_value(
ground_plane_material_asset_property) == ground_plane_material_asset)
# 13. Add the Mesh component to the Ground Plane Entity and set the Mesh component Mesh Asset property.
ground_plane_mesh_component = ground_plane_entity.add_component(MESH_COMPONENT_NAME)
Report.result(Tests.mesh_component_added, ground_plane_entity.has_component(MESH_COMPONENT_NAME))
ground_plane_mesh_asset_path = os.path.join("Objects", "plane.azmodel")
ground_plane_mesh_asset = asset.AssetCatalogRequestBus(
bus.Broadcast, "GetAssetIdByPath", ground_plane_mesh_asset_path, math.Uuid(), False)
ground_plane_mesh_asset_property = "Controller|Configuration|Mesh Asset"
ground_plane_mesh_component.set_component_property_value(
ground_plane_mesh_asset_property, ground_plane_mesh_asset)
Report.result(
Tests.ground_plane_mesh_asset_set,
ground_plane_mesh_component.get_component_property_value(
ground_plane_mesh_asset_property) == ground_plane_mesh_asset)
# 14. Create a Directional Light Entity as a child entity of the Default Level Entity.
directional_light_name = "Directional Light"
directional_light_entity = EditorEntity.create_editor_entity_at(
math.Vector3(0.0, 0.0, 10.0), directional_light_name, default_level_entity.id)
# 15. Add Directional Light component to Directional Light Entity and set entity rotation.
directional_light_entity.add_component(directional_light_name)
directional_light_entity_rotation = math.Vector3(DEGREE_RADIAN_FACTOR * -90.0, 0.0, 0.0)
directional_light_entity.set_local_rotation(directional_light_entity_rotation)
Report.result(
Tests.directional_light_component_added, directional_light_entity.has_component(directional_light_name))
# 16. Create a Sphere Entity as a child entity of the Default Level Entity then add a Material component.
sphere_entity = EditorEntity.create_editor_entity_at(
math.Vector3(0.0, 0.0, 1.0), "Sphere", default_level_entity.id)
sphere_material_component = sphere_entity.add_component(MATERIAL_COMPONENT_NAME)
Report.result(Tests.sphere_material_component_added, sphere_entity.has_component(MATERIAL_COMPONENT_NAME))
# 17. Set the Material Asset property of the Material component for the Sphere Entity.
sphere_material_asset_path = os.path.join("Materials", "Presets", "PBR", "metal_brass_polished.azmaterial")
sphere_material_asset = asset.AssetCatalogRequestBus(
bus.Broadcast, "GetAssetIdByPath", sphere_material_asset_path, math.Uuid(), False)
sphere_material_asset_property = "Default Material|Material Asset"
sphere_material_component.set_component_property_value(sphere_material_asset_property, sphere_material_asset)
Report.result(Tests.sphere_material_set, sphere_material_component.get_component_property_value(
sphere_material_asset_property) == sphere_material_asset)
# 18. Add Mesh component to Sphere Entity and set the Mesh Asset property for the Mesh component.
sphere_mesh_component = sphere_entity.add_component(MESH_COMPONENT_NAME)
sphere_mesh_asset_path = os.path.join("Models", "sphere.azmodel")
sphere_mesh_asset = asset.AssetCatalogRequestBus(
bus.Broadcast, "GetAssetIdByPath", sphere_mesh_asset_path, math.Uuid(), False)
sphere_mesh_asset_property = "Controller|Configuration|Mesh Asset"
sphere_mesh_component.set_component_property_value(sphere_mesh_asset_property, sphere_mesh_asset)
Report.result(Tests.sphere_mesh_asset_set, sphere_mesh_component.get_component_property_value(
sphere_mesh_asset_property) == sphere_mesh_asset)
# 19. Create a Camera Entity as a child entity of the Default Level Entity then add a Camera component.
camera_name = "Camera"
camera_entity = EditorEntity.create_editor_entity_at(
math.Vector3(5.5, -12.0, 9.0), camera_name, default_level_entity.id)
camera_component = camera_entity.add_component(camera_name)
Report.result(Tests.camera_component_added, camera_entity.has_component(camera_name))
# 20. Set the Camera Entity rotation value and set the Camera component Field of View value.
camera_entity_rotation = math.Vector3(
DEGREE_RADIAN_FACTOR * -27.0, DEGREE_RADIAN_FACTOR * -12.0, DEGREE_RADIAN_FACTOR * 25.0)
camera_entity.set_local_rotation(camera_entity_rotation)
camera_fov_property = "Controller|Configuration|Field of view"
camera_fov_value = 60.0
camera_component.set_component_property_value(camera_fov_property, camera_fov_value)
azlmbr.camera.EditorCameraViewRequestBus(azlmbr.bus.Event, "ToggleCameraAsActiveView", camera_entity.id)
Report.result(Tests.camera_fov_set, camera_component.get_component_property_value(
camera_fov_property) == camera_fov_value)
# 21. Enter game mode.
helper.enter_game_mode(Tests.enter_game_mode)
helper.wait_for_condition(function=lambda: general.is_in_game_mode(), timeout_in_seconds=4.0)
# 22. Take screenshot.
ScreenshotHelper(general.idle_wait_frames).capture_screenshot_blocking(f"{SCREENSHOT_NAME}.ppm")
# 23. Exit game mode.
helper.exit_game_mode(Tests.exit_game_mode)
helper.wait_for_condition(function=lambda: not general.is_in_game_mode(), timeout_in_seconds=4.0)
# 24. Look for errors.
helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
Report.result(Tests.no_assert_occurred, not error_tracer.has_asserts)
Report.result(Tests.no_error_occurred, not error_tracer.has_errors)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(AtomGPU_BasicLevelSetup_SetsUpLevel)

@ -16,7 +16,7 @@ import time
import azlmbr.math as math
import azlmbr.paths
sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests"))
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
import Atom.atom_utils.material_editor_utils as material_editor
@ -27,10 +27,10 @@ TEST_MATERIAL_1 = "001_DefaultWhite.material"
TEST_MATERIAL_2 = "002_BaseColorLerp.material"
TEST_MATERIAL_3 = "003_MetalMatte.material"
TEST_DATA_PATH = os.path.join(
azlmbr.paths.devroot, "Gems", "Atom", "TestData", "TestData", "Materials", "StandardPbrTestCases"
azlmbr.paths.engroot, "Gems", "Atom", "TestData", "TestData", "Materials", "StandardPbrTestCases"
)
MATERIAL_TYPE_PATH = os.path.join(
azlmbr.paths.devroot, "Gems", "Atom", "Feature", "Common", "Assets",
azlmbr.paths.engroot, "Gems", "Atom", "Feature", "Common", "Assets",
"Materials", "Types", "StandardPBR.materialtype",
)
CACHE_FILE_EXTENSION = ".azmaterial"
@ -61,7 +61,7 @@ def run():
print(f"Material opened: {material_editor.is_open(document_id)}")
# Verify if the test material exists initially
target_path = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL)
target_path = os.path.join(azlmbr.paths.projectroot, "Materials", NEW_MATERIAL)
print(f"Test asset doesn't exist initially: {not os.path.exists(target_path)}")
# 2) Test Case: Creating a New Material Using Existing One
@ -109,10 +109,10 @@ def run():
# Assign new color to the material file and save the document as copy
expected_color_1 = math.Color(0.5, 0.5, 0.5, 1.0)
material_editor.set_property(document_id, property_name, expected_color_1)
target_path_1 = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL_1)
target_path_1 = os.path.join(azlmbr.paths.projectroot, "Materials", NEW_MATERIAL_1)
cache_file_name_1 = os.path.splitext(NEW_MATERIAL_1) # Example output: ('test_material_1', '.material')
cache_file_1 = f"{cache_file_name_1[0]}{CACHE_FILE_EXTENSION}"
target_path_1_cache = os.path.join(azlmbr.paths.devassets, "Cache", "pc", "materials", cache_file_1)
target_path_1_cache = os.path.join(azlmbr.paths.products, "materials", cache_file_1)
material_editor.save_document_as_copy(document_id, target_path_1)
material_editor.wait_for_condition(lambda: os.path.exists(target_path_1_cache), 4.0)
@ -120,10 +120,10 @@ def run():
# Assign new color to the material file save the document as child
expected_color_2 = math.Color(0.75, 0.75, 0.75, 1.0)
material_editor.set_property(document_id, property_name, expected_color_2)
target_path_2 = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL_2)
target_path_2 = os.path.join(azlmbr.paths.projectroot, "Materials", NEW_MATERIAL_2)
cache_file_name_2 = os.path.splitext(NEW_MATERIAL_1) # Example output: ('test_material_2', '.material')
cache_file_2 = f"{cache_file_name_2[0]}{CACHE_FILE_EXTENSION}"
target_path_2_cache = os.path.join(azlmbr.paths.devassets, "Cache", "pc", "materials", cache_file_2)
target_path_2_cache = os.path.join(azlmbr.paths.products, "materials", cache_file_2)
material_editor.save_document_as_child(document_id, target_path_2)
material_editor.wait_for_condition(lambda: os.path.exists(target_path_2_cache), 4.0)

@ -10,7 +10,7 @@ import sys
import azlmbr.legacy.general as general
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.editor_test_helper import EditorTestHelper

@ -17,7 +17,7 @@ import azlmbr.math as math
import azlmbr.paths
import azlmbr.editor as editor
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.editor_test_helper import EditorTestHelper

@ -14,7 +14,7 @@ import azlmbr.math as math
import azlmbr.paths
import azlmbr.legacy.general as general
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
import editor_python_test_tools.hydra_editor_utils as hydra
from Atom.atom_utils import atom_component_helper, atom_constants, screenshot_utils

@ -42,7 +42,6 @@ class TestEditorAutomation(object):
"editor command line arg bar",
"editor command line arg baz",
"editor engroot set",
"editor devroot set",
"path resolved worked"
]

@ -20,12 +20,6 @@ if (engroot is not None and len(engroot) is not 0):
print ('engroot is {}'.format(engroot))
print ('editor engroot set')
# make sure the @devroot@ exists as a azlmbr.paths property
devroot = azlmbr.paths.devroot
if (devroot is not None and len(devroot) != 0):
print ('devroot is {}'.format(devroot))
print ('editor devroot set')
# resolving a basic path
path = azlmbr.paths.resolve_path('@engroot@/engineassets/texturemsg/defaultsolids.mtl')
if (len(path) != 0 and path.find('@engroot@') == -1):

@ -16,7 +16,7 @@ import azlmbr.entity as entity
import azlmbr.math as math
import azlmbr.paths
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
sys.path.append(os.path.join(azlmbr.paths.projectroot, 'Gem', 'PythonTests'))
from automatedtesting_shared.editor_test_helper import EditorTestHelper

@ -1,2 +1,2 @@
# this file is copied to $/dev/editor_autoexec.cfg so the the Editor automation runs for this Hydra test
pyRunFile @devroot@/Tests/hydra/LevelComponentCommands_test_case.py exit_when_done
pyRunFile @engroot@/Tests/hydra/LevelComponentCommands_test_case.py exit_when_done

@ -1,2 +1,2 @@
# this file is copied to $/dev/editor_autoexec.cfg so the the Editor automation runs for this Hydra test
pyRunFile @devroot@/Tests/hydra/ViewportTitleDlgCommands_test_case.py
pyRunFile @engroot@/Tests/hydra/ViewportTitleDlgCommands_test_case.py

@ -361,3 +361,19 @@ class EditorEntity:
:return: True if "isVisible" is enabled, False otherwise.
"""
return editor.EditorEntityInfoRequestBus(bus.Event, "IsVisible", self.id)
def set_local_uniform_scale(self, scale_float) -> None:
"""
Sets the "SetLocalUniformScale" value on the entity.
:param scale_float: value for "SetLocalUniformScale" to set to.
:return: None
"""
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalUniformScale", self.id, scale_float)
def set_local_rotation(self, vector3_rotation) -> None:
"""
Sets the "SetLocalRotation" value on the entity.
:param vector3_rotation: The math.Vector3 value to use for rotation on the entity (uses radians).
:return: None
"""
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", self.id, vector3_rotation)

@ -4,18 +4,18 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
import json
import math
import os
import time
import math
import traceback
from typing import Callable, Tuple
import azlmbr
import azlmbr.legacy.general as general
import azlmbr.debug
import json
import traceback
from typing import Callable, Tuple
class FailFast(Exception):
"""
@ -127,6 +127,31 @@ class TestHelper:
if ret:
return True
@staticmethod
def close_error_windows():
"""
Closes Error Report and Error Log windows that block focus if they are visible.
:return: None
"""
if general.is_pane_visible("Error Report"):
general.close_pane("Error Report")
if general.is_pane_visible("Error Log"):
general.close_pane("Error Log")
@staticmethod
def close_display_helpers():
"""
Closes helper gizmos, anti-aliasing, and FPS meters.
:return: None
"""
if general.is_helpers_shown():
general.toggle_helpers()
general.idle_wait(1.0)
general.idle_wait(1.0)
general.run_console("r_displayInfo=0")
general.run_console("r_antialiasingmode=0")
general.idle_wait(1.0)
class Timeout:
# type: (float) -> None
@ -149,6 +174,7 @@ class Timeout:
def timed_out(self):
return time.time() > self.die_after
class Report:
_results = []
_exception = None
@ -290,8 +316,8 @@ class Report:
Report.info(" x: {:.2f}, y: {:.2f}, z: {:.2f}".format(vector3.x, vector3.y, vector3.z))
if magnitude is not None:
Report.info(" magnitude: {:.2f}".format(magnitude))
'''
Utility for scope tracing errors and warnings.
Usage:
@ -303,7 +329,7 @@ Usage:
Report.result(Tests.warnings_not_found_in_section, not section_tracer.has_warnings)
'''
'''
class Tracer:
def __init__(self):
self.warnings = []
@ -349,10 +375,10 @@ class Tracer:
self.line = args[1]
self.function = args[2]
self.message = args[3]
def __str__(self):
return f"Assert: [{self.filename}:{self.function}:{self.line}]: {self.message}"
def __repr__(self):
return f"[Assert: {self.message}]"
@ -360,21 +386,21 @@ class Tracer:
def __init__(self, args):
self.window = args[0]
self.message = args[1]
def _on_warning(self, args):
warningInfo = Tracer.WarningInfo(args)
self.warnings.append(warningInfo)
Report.info("Tracer caught Warning: %s" % warningInfo.message)
self.has_warnings = True
return False
def _on_error(self, args):
errorInfo = Tracer.ErrorInfo(args)
self.errors.append(errorInfo)
Report.info("Tracer caught Error: %s" % errorInfo.message)
self.has_errors = True
return False
def _on_assert(self, args):
assertInfo = Tracer.AssertInfo(args)
self.asserts.append(assertInfo)
@ -436,6 +462,7 @@ class AngleHelper:
def vector3_str(vector3):
return "(x: {:.2f}, y: {:.2f}, z: {:.2f})".format(vector3.x, vector3.y, vector3.z)
def aabb_str(aabb):
return "[Min: %s, Max: %s]" % (vector3_str(aabb.min), vector3_str(aabb.max))

@ -525,10 +525,6 @@ class TestAutomation(TestAutomationBase):
from .tests.joints import Joints_BallNoLimitsConstrained as test_module
self._run_test(request, workspace, editor, test_module)
def test_Joints_FixedLeadFollowerCollide(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_FixedLeadFollowerCollide as test_module
self._run_test(request, workspace, editor, test_module)
def test_Joints_GlobalFrameConstrained(self, request, workspace, editor, launcher_platform):
from .tests.joints import Joints_GlobalFrameConstrained as test_module
self._run_test(request, workspace, editor, test_module)

@ -82,7 +82,7 @@ def ForceRegion_SplineRegionWithModifiedTransform():
import azlmbr.bus as bus
# region Constants
TIMEOUT = 5.0
TIMEOUT = 10.0
MIN_TRIGGER_DISTANCE = 2.0
# endregion

@ -77,7 +77,7 @@ def ForceRegion_ZeroPointForceDoesNothing():
helper.init_idle()
TIMEOUT_SECONDS = 3.0
TIMEOUT_SECONDS = 5.0
X_Y_Z_TOLERANCE = 1.5
REGION_HEIGHT = 3.0
TERRAIN_HEIGHT = 32.0

@ -45,8 +45,13 @@ class JointEntity:
# Entity class that sets a flag when an instance receives collision events.
class JointEntityCollisionAware(JointEntity):
def on_collision_begin(self, args):
if not self.collided:
self.collided = True
self.collided = True
def on_collision_persist(self, args):
self.collided = True
def on_collision_end(self, args):
self.collided = True
def __init__(self, name):
self.id = general.find_game_entity(name)
@ -58,3 +63,5 @@ class JointEntityCollisionAware(JointEntity):
self.handler = azlmbr.physics.CollisionNotificationBusHandler()
self.handler.connect(self.id)
self.handler.add_callback("OnCollisionBegin", self.on_collision_begin)
self.handler.add_callback("OnCollisionPresist", self.on_collision_persist)
self.handler.add_callback("OnCollisionEnd", self.on_collision_end)

@ -1,92 +0,0 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test case ID : C18243582
# Test Case Title : Check that fixed joint allows lead-follower collision
# fmt: off
class Tests:
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
lead_found = ("Found lead", "Did not find lead")
follower_found = ("Found follower", "Did not find follower")
check_collision_happened = ("Lead and follower collided", "Lead and follower did not collide")
# fmt: on
def Joints_FixedLeadFollowerCollide():
"""
Summary: Check that fixed joint allows lead-follower collision
Level Description:
lead - Starts above follower entity
follower - Starts below lead entity. Constrained to lead entity with fixed joint. Starts with initial velocity of (5, 0, 0) in positive X direction.
Expected Behavior:
The follower entity moves in the positive X direction and the lead entity is dragged along towards the positive X direction.
The x position of the lead entity is incremented from its original.
The lead and follower entities are kept apart at a distance of approximately 1.0 due to collision.
Test Steps:
1) Open Level
2) Enter Game Mode
3) Create and Validate Entities
4) Wait for several seconds
5) Check to see if lead and follower behaved as expected.
6) Exit Game Mode
7) Close Editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import sys
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
import azlmbr.legacy.general as general
import azlmbr.bus
from JointsHelper import JointEntityCollisionAware
# Helper Entity class - self.collided flag is set when instance receives collision event.
class Entity(JointEntityCollisionAware):
def criticalEntityFound(self): # Override function to use local Test dictionary
Report.critical_result(Tests.__dict__[self.name + "_found"], self.id.isValid())
# Main Script
helper.init_idle()
# 1) Open Level
helper.open_level("Physics", "Joints_FixedLeadFollowerCollide")
# 2) Enter Game Mode
helper.enter_game_mode(Tests.enter_game_mode)
# 3) Create and Validate Entities
lead = Entity("lead")
follower = Entity("follower")
# 4) Wait for several seconds
general.idle_wait(2.0) # wait for lead and follower to move
# 5) Check to see if lead entity and follower collided
Report.critical_result(Tests.check_collision_happened, lead.collided and follower.collided)
# 6) Exit Game Mode
helper.exit_game_mode(Tests.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(Joints_FixedLeadFollowerCollide)

@ -80,6 +80,20 @@ def RigidBody_KinematicModeWorks():
ramp_id = general.find_game_entity("Ramp")
Report.result(Tests.find_ramp, ramp_id.IsValid())
# 2.1) setup collision handler
class RampTouched:
value = False
def on_collision_begin(args):
other_id = args[0]
if other_id.Equal(ramp_id):
Report.info("Box touched ramp")
RampTouched.value = True
handler = azlmbr.physics.CollisionNotificationBusHandler()
handler.connect(box_id)
handler.add_callback("OnCollisionBegin", on_collision_begin)
# 3) Check for kinematic ramp and not kinematic box
box_kinematic = azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "IsKinematic", box_id)
Report.result(Tests.box_is_not_kinematic, not box_kinematic)
@ -98,21 +112,7 @@ def RigidBody_KinematicModeWorks():
ramp_pos_start = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", ramp_id)
Report.info("Ramp's initial position: {}".format(ramp_pos_start))
# 6) Check to see that the box hits the ramp
class RampTouched:
value = False
def on_collision_begin(args):
other_id = args[0]
if other_id.Equal(ramp_id):
Report.info("Box touched ramp")
RampTouched.value = True
handler = azlmbr.physics.CollisionNotificationBusHandler()
handler.connect(box_id)
handler.add_callback("OnCollisionBegin", on_collision_begin)
# 6.5) Wait for the box to touch the ramp or timeout
# 6) Wait for the box to touch the ramp or timeout
helper.wait_for_condition(lambda: RampTouched.value, TIME_OUT)
Report.result(Tests.box_touched_ramp, RampTouched.value)

@ -70,19 +70,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
## GradientSignal ##
ly_add_pytest(
NAME AutomatedTesting::GradientSignalTests_Periodic
TEST_SERIAL
TEST_SUITE periodic
PATH ${CMAKE_CURRENT_LIST_DIR}/gradient_signal/TestSuite_Periodic.py
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
Legacy::Editor
AutomatedTesting.Assets
COMPONENT
LargeWorlds
)
ly_add_pytest(
NAME AutomatedTesting::GradientSignalTests_Periodic_Optimized
TEST_SERIAL

@ -109,7 +109,7 @@ def DynamicSliceInstanceSpawner_Embedded_E2E():
# 6) Save and export to engine
general.save_level()
general.export_to_engine()
pak_path = os.path.join(paths.devroot, "AutomatedTesting", "cache", "pc", "levels", lvl_name, "level.pak")
pak_path = os.path.join(paths.products, "levels", lvl_name, "level.pak")
Report.result(Tests.saved_and_exported, os.path.exists(pak_path))

@ -131,7 +131,7 @@ def DynamicSliceInstanceSpawner_External_E2E():
# 6) Save and export to engine
general.save_level()
general.export_to_engine()
pak_path = os.path.join(paths.devroot, "AutomatedTesting", "cache", "pc", "levels", lvl_name, "level.pak")
pak_path = os.path.join(paths.products, "levels", lvl_name, "level.pak")
Report.result(Tests.saved_and_exported, os.path.exists(pak_path))

@ -155,7 +155,7 @@ def LayerBlender_E2E_Editor():
# 6) Save and export to engine
general.save_level()
general.export_to_engine()
pak_path = os.path.join(paths.devroot, "AutomatedTesting", "cache", "pc", "levels", lvl_name, "level.pak")
pak_path = os.path.join(paths.products, "levels", lvl_name, "level.pak")
Report.result(Tests.saved_and_exported, os.path.exists(pak_path))

@ -10,7 +10,6 @@ import pytest
from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorParallelTest, EditorTestSuite
@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.")
@pytest.mark.SUITE_periodic
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("project", ["AutomatedTesting"])

@ -17,7 +17,7 @@ import azlmbr.vegetation as vegetation
import azlmbr.areasystem as areasystem
import azlmbr.paths
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
sys.path.append(os.path.join(azlmbr.paths.projectroot, 'Gem', 'PythonTests'))
import editor_python_test_tools.hydra_editor_utils as hydra
@ -25,7 +25,7 @@ def create_surface_entity(name, center_point, box_size_x, box_size_y, box_size_z
# Create a "flat surface" entity to use as a plantable vegetation surface
surface_entity = hydra.Entity(name)
surface_entity.create_entity(
center_point,
center_point,
["Box Shape", "Shape Surface Tag Emitter"]
)
if surface_entity.id.IsValid():
@ -56,7 +56,7 @@ def create_vegetation_area(name, center_point, box_size_x, box_size_y, box_size_
# Create a vegetation area entity to use as our test vegetation spawner
spawner_entity = hydra.Entity(name)
spawner_entity.create_entity(
center_point,
center_point,
["Vegetation Layer Spawner", "Box Shape", "Vegetation Asset List"]
)
if spawner_entity.id.IsValid():

@ -122,6 +122,7 @@ class TestAutomation(TestAutomationBase):
from . import Debugger_HappyPath_TargetMultipleEntities as test_module
self._run_test(request, workspace, editor, test_module)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
def test_EditMenu_Default_UndoRedo(self, request, workspace, editor, launcher_platform, project):
from . import EditMenu_Default_UndoRedo as test_module
self._run_test(request, workspace, editor, test_module)
@ -181,6 +182,7 @@ class TestAutomation(TestAutomationBase):
from . import NodePalette_SearchText_Deletion as test_module
self._run_test(request, workspace, editor, test_module)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
def test_VariableManager_UnpinVariableType_Works(self, request, workspace, editor, launcher_platform):
from . import VariableManager_UnpinVariableType_Works as test_module
self._run_test(request, workspace, editor, test_module)

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3093fee5317ba6fb353a435c09f43f13c5e722421aae62a297f699c202d6129e
size 6699

@ -1,6 +0,0 @@
<download name="Joints_Fixed2BodiesConstrained" type="Map">
<index src="filelist.xml" dest="filelist.xml"/>
<files>
<file src="level.pak" dest="level.pak" size="7959" md5="f315f559517fa8d28c600ea74c3ea555"/>
</files>
</download>

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b1daa050e732ff0594601bbfca8ac9ed05972c2f9fa3e43dbc8645e802ed2730
size 7959

@ -1,14 +0,0 @@
<Environment>
<Fog ViewDistance="8000" ViewDistanceLowSpec="1000"/>
<Terrain DetailLayersViewDistRatio="1.0" HeightMapAO="0"/>
<EnvState WindVector="1,0,0" BreezeGeneration="0" BreezeStrength="1.f" BreezeMovementSpeed="8.f" BreezeVariation="1.f" BreezeLifeTime="15.f" BreezeCount="4" BreezeSpawnRadius="25.f" BreezeSpread="0.f" BreezeRadius="5.f" ConsoleMergedMeshesPool="2750" ShowTerrainSurface="1" SunShadowsMinSpec="1" SunShadowsAdditionalCascadeMinSpec="0" SunShadowsClipPlaneRange="256.0f" SunShadowsClipPlaneRangeShift="0.0f" UseLayersActivation="0" SunLinkedToTOD="1"/>
<VolFogShadows Enable="0" EnableForClouds="0"/>
<CloudShadows CloudShadowTexture="" CloudShadowSpeed="0,0,0" CloudShadowTiling="1.0" CloudShadowBrightness="1.0" CloudShadowInvert="0"/>
<ParticleLighting AmbientMul="1.0" LightsMul="1.0"/>
<SkyBox Material="EngineAssets/Materials/Sky/Sky" MaterialLowSpec="EngineAssets/Materials/Sky/Sky" Angle="0" Stretching="0.5"/>
<Ocean Material="EngineAssets/Materials/Water/Ocean_default" CausticsDistanceAtten="100.0" CausticDepth="8.0" CausticIntensity="1.0" CausticsTilling="1.0"/>
<OceanAnimation WindDirection="1.0" WindSpeed="4.0" WavesAmount="1.5" WavesSize="0.4" WavesSpeed="1.0"/>
<Moon Latitude="240.0" Longitude="45.0" Size="0.5" Texture="Textures/Skys/Night/half_moon.dds"/>
<DynTexSource Width="256" Height="256"/>
<Total_Illumination_v2 Active="0" IntegrationMode="0" NumberOfBounces="1" DiffuseConeWidth="24" ConeMaxLength="12.0" UseLightProbes="0" InjectionMultiplier="1.0" AmbientOffsetRed="1.0" AmbientOffsetGreen="1.0" AmbientOffsetBlue="1.0" AmbientOffsetBias="0.1" Saturation="0.8" SSAOAmount="0.7"/>
</Environment>

@ -1,7 +0,0 @@
<TerrainTexture TileCountX="1" TileCountY="1" TileResolution="512">
<RGBLayer>
<Tiles>
<tile X="0" Y="0" Size="512"/>
</Tiles>
</RGBLayer>
</TerrainTexture>

@ -1,356 +0,0 @@
<TimeOfDay Time="13.5" TimeStart="13.5" TimeEnd="13.5" TimeAnimSpeed="0">
<Variable Name="Sun color" Color="0.99989021,0.99946922,0.9991194">
<Spline Keys="-0.000628322:(0.783538:0.89627:0.930341):36,0:(0.783538:0.887923:0.921582):36,0.229167:(0.783538:0.879623:0.921582):36,0.25:(0.947307:0.745404:0.577581):36,0.458333:(1:1:1):36,0.5625:(1:1:1):36,0.75:(0.947307:0.745404:0.577581):36,0.770833:(0.783538:0.879623:0.921582):36,1:(0.783538:0.89627:0.930556):36,"/>
</Variable>
<Variable Name="Sun intensity" Value="92366.68">
<Spline Keys="0:1000:36,0.229167:1000:36,0.5:120000:36,0.770833:1000:65572,0.999306:1000:36,"/>
</Variable>
<Variable Name="Sun specular multiplier" Value="1">
<Spline Keys="0:1:36,0.25:1:36,0.5:1:36,0.75:1:36,1:1:36,"/>
</Variable>
<Variable Name="Fog color" Color="0.27049801,0.47353199,0.83076996">
<Spline Keys="0:(0.00651209:0.00972122:0.0137021):36,0.229167:(0.00604883:0.00972122:0.0137021):36,0.25:(0.270498:0.473532:0.83077):36,0.5:(0.270498:0.473532:0.83077):458788,0.75:(0.270498:0.473532:0.83077):36,0.770833:(0.00604883:0.00972122:0.0137021):36,1:(0.00651209:0.00972122:0.0137021):36,"/>
</Variable>
<Variable Name="Fog color multiplier" Value="1">
<Spline Keys="0:0.5:36,0.229167:0.5:36,0.25:1:36,0.5:1:36,0.75:1:36,0.770833:0.5:36,1:0.5:65572,"/>
</Variable>
<Variable Name="Fog height (bottom)" Value="0">
<Spline Keys="0:0:36,0.25:0:36,0.5:0:36,0.75:0:36,1:0:36,"/>
</Variable>
<Variable Name="Fog layer density (bottom)" Value="1">
<Spline Keys="0:1:36,0.25:1:36,0.5:1:36,0.75:1:36,1:1:36,"/>
</Variable>
<Variable Name="Fog color (top)" Color="0.597202,0.72305501,0.91309899">
<Spline Keys="0:(0.00699541:0.00972122:0.0122865):36,0.229167:(0.00699541:0.00972122:0.0122865):36,0.25:(0.597202:0.723055:0.913099):36,0.5:(0.597202:0.723055:0.913099):458788,0.75:(0.597202:0.723055:0.913099):36,0.770833:(0.00699541:0.00972122:0.0122865):36,1:(0.00699541:0.00972122:0.0122865):36,"/>
</Variable>
<Variable Name="Fog color (top) multiplier" Value="0.88389361">
<Spline Keys="-4.40702e-06:0.5:36,0.0297507:0.499195:36,0.229167:0.5:36,0.5:1:36,0.770833:0.5:36,1:0.5:36,"/>
</Variable>
<Variable Name="Fog height (top)" Value="100.00001">
<Spline Keys="0:100:36,0.25:100:36,0.5:100:36,0.75:100:65572,1:100:36,"/>
</Variable>
<Variable Name="Fog layer density (top)" Value="9.9999997e-05">
<Spline Keys="0:0.0001:36,0.25:0.0001:36,0.5:0.0001:65572,0.75:0.0001:36,1:0.0001:36,"/>
</Variable>
<Variable Name="Fog color height offset" Value="0">
<Spline Keys="0:0:36,0.25:0:36,0.5:0:36,0.75:0:36,1:0:65572,"/>
</Variable>
<Variable Name="Fog color (radial)" Color="0.78592348,0.52744436,0.17234583">
<Spline Keys="0:(0:0:0):36,0.229167:(0.00439144:0.00367651:0.00334654):36,0.25:(0.838799:0.564712:0.184475):36,0.5:(0.768151:0.514918:0.168269):458788,0.75:(0.838799:0.564712:0.184475):36,0.770833:(0.00402472:0.00334654:0.00303527):36,1:(0:0:0):36,"/>
</Variable>
<Variable Name="Fog color (radial) multiplier" Value="6">
<Spline Keys="0:0:36,0.25:6:36,0.5:6:36,0.75:6:36,1:0:36,"/>
</Variable>
<Variable Name="Fog radial size" Value="0.85000002">
<Spline Keys="0:0:36,0.25:0.85:65572,0.5:0.85:36,0.75:0.85:36,1:0:36,"/>
</Variable>
<Variable Name="Fog radial lobe" Value="0.75">
<Spline Keys="0:0:36,0.25:0.75:36,0.5:0.75:36,0.75:0.75:65572,1:0:36,"/>
</Variable>
<Variable Name="Volumetric fog: Final density clamp" Value="1">
<Spline Keys="0:1:36,0.25:1:36,0.5:1:65572,0.75:1:36,1:1:36,"/>
</Variable>
<Variable Name="Volumetric fog: Global density" Value="1.5">
<Spline Keys="0:1.5:36,0.25:1.5:36,0.5:1.5:65572,0.75:1.5:36,1:1.5:36,"/>
</Variable>
<Variable Name="Volumetric fog: Ramp start" Value="25.000002">
<Spline Keys="0:25:36,0.25:25:36,0.5:25:65572,0.75:25:36,1:25:36,"/>
</Variable>
<Variable Name="Volumetric fog: Ramp end" Value="1000.0001">
<Spline Keys="0:1000:36,0.25:1000:36,0.5:1000:65572,0.75:1000:36,1:1000:36,"/>
</Variable>
<Variable Name="Volumetric fog: Ramp influence" Value="0.69999993">
<Spline Keys="0:0.7:36,0.25:0.7:36,0.5:0.7:65572,0.75:0.7:36,1:0.7:36,"/>
</Variable>
<Variable Name="Volumetric fog: Shadow darkening" Value="0.20000002">
<Spline Keys="0:0.2:36,0.25:0.2:36,0.5:0.2:65572,0.75:0.2:36,1:0.2:36,"/>
</Variable>
<Variable Name="Volumetric fog: Shadow darkening sun" Value="0.5">
<Spline Keys="0:0.5:36,0.25:0.5:36,0.5:0.5:65572,0.75:0.5:36,1:0.5:36,"/>
</Variable>
<Variable Name="Volumetric fog: Shadow darkening ambient" Value="1">
<Spline Keys="0:1:36,0.25:1:36,0.5:1:65572,0.75:1:36,1:1:36,"/>
</Variable>
<Variable Name="Volumetric fog: Shadow range" Value="0.10000001">
<Spline Keys="0:0.1:36,0.25:0.1:36,0.5:0.1:65572,0.75:0.1:36,1:0.1:36,"/>
</Variable>
<Variable Name="Volumetric fog 2: Fog height (bottom)" Value="0">
<Spline Keys="0:0:0,1:0:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Fog layer density (bottom)" Value="1">
<Spline Keys="0:1:0,1:1:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Fog height (top)" Value="4000">
<Spline Keys="0:4000:0,1:4000:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Fog layer density (top)" Value="9.9999997e-05">
<Spline Keys="0:0.0001:0,1:0.0001:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Global fog density" Value="0.1">
<Spline Keys="0:0.1:0,1:0.1:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Ramp start" Value="0">
<Spline Keys="0:0:0,1:0:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Ramp end" Value="0">
<Spline Keys="0:0:0,1:0:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Fog albedo color (atmosphere)" Color="1,1,1">
<Spline Keys="0:(1:1:1):0,1:(1:1:1):0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Anisotropy factor (atmosphere)" Value="0.60000002">
<Spline Keys="0:0.6:0,1:0.6:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Fog albedo color (sun radial)" Color="1,1,1">
<Spline Keys="0:(1:1:1):0,1:(1:1:1):0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Anisotropy factor (sun radial)" Value="0.94999999">
<Spline Keys="0:0.95:0,1:0.95:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Blend factor for sun scattering" Value="1">
<Spline Keys="0:1:0,1:1:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Blend mode for sun scattering" Value="0">
<Spline Keys="0:0:0,1:0:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Fog albedo color (entities)" Color="1,1,1">
<Spline Keys="0:(1:1:1):0,1:(1:1:1):0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Anisotropy factor (entities)" Value="0.60000002">
<Spline Keys="0:0.6:0,1:0.6:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Maximum range of ray-marching" Value="64">
<Spline Keys="0:64:0,1:64:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: In-scattering factor" Value="1">
<Spline Keys="0:1:0,1:1:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Extinction factor" Value="0.30000001">
<Spline Keys="0:0.3:0,1:0.3:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Analytical volumetric fog visibility" Value="0.5">
<Spline Keys="0:0.5:0,1:0.5:0,"/>
</Variable>
<Variable Name="Volumetric fog 2: Final density clamp" Value="1">
<Spline Keys="0:1:0,0.5:1:36,1:1:0,"/>
</Variable>
<Variable Name="Sky light: Sun intensity" Color="1,1,1">
<Spline Keys="0:(1:1:1):36,0.25:(1:1:1):36,0.494381:(1:1:1):65572,0.5:(1:1:1):36,0.75:(1:1:1):36,1:(1:1:1):36,"/>
</Variable>
<Variable Name="Sky light: Sun intensity multiplier" Value="200.00002">
<Spline Keys="0:200:36,0.25:200:36,0.5:200:36,0.75:200:36,1:200:36,"/>
</Variable>
<Variable Name="Sky light: Mie scattering" Value="6.779707">
<Spline Keys="0:40:36,0.5:2:36,1:40:36,"/>
</Variable>
<Variable Name="Sky light: Rayleigh scattering" Value="0.20000002">
<Spline Keys="0:0.2:36,0.229167:0.2:36,0.25:1:36,0.291667:0.2:36,0.5:0.2:36,0.729167:0.2:36,0.75:1:36,0.770833:0.2:36,1:0.2:36,"/>
</Variable>
<Variable Name="Sky light: Sun anisotropy factor" Value="-0.99989998">
<Spline Keys="0:-0.9999:36,0.25:-0.9999:36,0.5:-0.9999:65572,0.75:-0.9999:36,1:-0.9999:36,"/>
</Variable>
<Variable Name="Sky light: Wavelength (R)" Value="694">
<Spline Keys="0:694:36,0.25:694:36,0.5:694:65572,0.75:694:36,1:694:36,"/>
</Variable>
<Variable Name="Sky light: Wavelength (G)" Value="596.99994">
<Spline Keys="0:597:36,0.25:597:36,0.5:597:36,0.75:597:36,1:597:36,"/>
</Variable>
<Variable Name="Sky light: Wavelength (B)" Value="488">
<Spline Keys="0:488:36,0.25:488:36,0.5:488:65572,0.75:488:36,1:488:36,"/>
</Variable>
<Variable Name="Night sky: Horizon color" Color="0.27049801,0.39157301,0.52711499">
<Spline Keys="0:(0.270498:0.391573:0.520996):36,0.25:(0.270498:0.391573:0.527115):36,0.5:(0.270498:0.391573:0.527115):262180,0.75:(0.270498:0.391573:0.527115):36,1:(0.270498:0.391573:0.520996):36,"/>
</Variable>
<Variable Name="Night sky: Horizon color multiplier" Value="0">
<Spline Keys="0:0.1:36,0.25:0:36,0.5:0:65572,0.75:0:36,1:0.1:36,"/>
</Variable>
<Variable Name="Night sky: Zenith color" Color="0.36130697,0.434154,0.46778399">
<Spline Keys="0:(0.361307:0.434154:0.467784):36,0.25:(0.361307:0.434154:0.467784):36,0.5:(0.361307:0.434154:0.467784):262180,0.75:(0.361307:0.434154:0.467784):36,1:(0.361307:0.434154:0.467784):36,"/>
</Variable>
<Variable Name="Night sky: Zenith color multiplier" Value="0">
<Spline Keys="0:0.02:36,0.25:0:36,0.5:0:65572,0.75:0:36,1:0.02:36,"/>
</Variable>
<Variable Name="Night sky: Zenith shift" Value="0.5">
<Spline Keys="0:0.5:36,0.25:0.5:36,0.5:0.5:65572,0.75:0.5:36,1:0.5:36,"/>
</Variable>
<Variable Name="Night sky: Star intensity" Value="0">
<Spline Keys="0:3:36,0.25:0:36,0.5:0:65572,0.75:0:36,0.836647:1.03977:36,1:3:36,"/>
</Variable>
<Variable Name="Night sky: Moon color" Color="1,1,1">
<Spline Keys="0:(1:1:1):36,0.25:(1:1:1):36,0.5:(1:1:1):458788,0.75:(1:1:1):36,1:(1:1:1):36,"/>
</Variable>
<Variable Name="Night sky: Moon color multiplier" Value="0">
<Spline Keys="0:0.4:36,0.25:0:36,0.5:0:36,0.75:0:65572,1:0.4:36,"/>
</Variable>
<Variable Name="Night sky: Moon inner corona color" Color="0.904661,1,1">
<Spline Keys="0:(0.89627:1:1):36,0.25:(0.904661:1:1):36,0.5:(0.904661:1:1):393252,0.75:(0.904661:1:1):36,0.836647:(0.89627:1:1):36,1:(0.89627:1:1):36,"/>
</Variable>
<Variable Name="Night sky: Moon inner corona color multiplier" Value="0">
<Spline Keys="0:0.1:36,0.25:0:36,0.5:0:65572,0.75:0:36,1:0.1:36,"/>
</Variable>
<Variable Name="Night sky: Moon inner corona scale" Value="0">
<Spline Keys="0:2:36,0.25:0:36,0.5:0:65572,0.75:0:36,0.836647:0.693178:36,1:2:36,"/>
</Variable>
<Variable Name="Night sky: Moon outer corona color" Color="0.201556,0.22696599,0.25415203">
<Spline Keys="0:(0.198069:0.226966:0.250158):36,0.25:(0.201556:0.226966:0.254152):36,0.5:(0.201556:0.226966:0.254152):36,0.75:(0.201556:0.226966:0.254152):36,1:(0.198069:0.226966:0.250158):36,"/>
</Variable>
<Variable Name="Night sky: Moon outer corona color multiplier" Value="0">
<Spline Keys="0:0.1:36,0.25:0:36,0.5:0:65572,0.75:0:36,1:0.1:36,"/>
</Variable>
<Variable Name="Night sky: Moon outer corona scale" Value="0">
<Spline Keys="0:0.01:36,0.25:0:36,0.5:0:65572,0.75:0:36,1:0.01:36,"/>
</Variable>
<Variable Name="Cloud shading: Sun light multiplier" Value="1">
<Spline Keys="0:1:36,0.25:1:36,0.5:1:65572,0.75:1:36,1:1:36,"/>
</Variable>
<Variable Name="Cloud shading: Sun custom color" Color="0.83076996,0.76815104,0.65837508">
<Spline Keys="0:(0.737911:0.737911:0.737911):36,0.25:(0.83077:0.768151:0.658375):36,0.5:(0.83077:0.768151:0.658375):458788,0.75:(0.83077:0.768151:0.658375):36,1:(0.737911:0.737911:0.737911):36,"/>
</Variable>
<Variable Name="Cloud shading: Sun custom color multiplier" Value="1">
<Spline Keys="0:0.1:36,0.25:1:36,0.5:1:65572,0.75:1:36,1:0.1:36,"/>
</Variable>
<Variable Name="Cloud shading: Sun custom color influence" Value="0">
<Spline Keys="0:0.5:36,0.25:0:36,0.5:0:65572,0.75:0:36,1:0.5:36,"/>
</Variable>
<Variable Name="Sun shafts visibility" Value="0">
<Spline Keys="0:0:36,0.25:0:36,0.5:0:65572,0.75:0:36,1:0:36,"/>
</Variable>
<Variable Name="Sun rays visibility" Value="1.5">
<Spline Keys="0:1:36,0.25:1.5:36,0.5:1.5:65572,0.75:1.5:36,1:1:36,"/>
</Variable>
<Variable Name="Sun rays attenuation" Value="1.5">
<Spline Keys="0:0.1:36,0.25:1.5:36,0.5:1.5:65572,0.75:1.5:36,1:0.1:36,"/>
</Variable>
<Variable Name="Sun rays suncolor influence" Value="0.5">
<Spline Keys="0:0.5:36,0.25:0.5:36,0.5:0.5:65572,0.75:0.5:36,1:0.5:36,"/>
</Variable>
<Variable Name="Sun rays custom color" Color="0.66538697,0.83879906,0.94730699">
<Spline Keys="0:(0.665387:0.838799:0.947307):36,0.25:(0.665387:0.838799:0.947307):36,0.5:(0.665387:0.838799:0.947307):458788,0.75:(0.665387:0.838799:0.947307):36,1:(0.665387:0.838799:0.947307):36,"/>
</Variable>
<Variable Name="Ocean fog color" Color="0.0012141101,0.0091340598,0.017642001">
<Spline Keys="0:(0.00121411:0.00913406:0.017642):36,0.25:(0.00121411:0.00913406:0.017642):36,0.5:(0.00121411:0.00913406:0.017642):458788,0.75:(0.00121411:0.00913406:0.017642):36,1:(0.00121411:0.00913406:0.017642):36,"/>
</Variable>
<Variable Name="Ocean fog color multiplier" Value="0.5">
<Spline Keys="0:0.5:36,0.25:0.5:36,0.5:0.5:65572,0.75:0.5:36,1:0.5:36,"/>
</Variable>
<Variable Name="Ocean fog density" Value="0.5">
<Spline Keys="0:0.5:36,0.25:0.5:36,0.5:0.5:65572,0.75:0.5:36,1:0.5:36,"/>
</Variable>
<Variable Name="Static skybox multiplier" Value="1">
<Spline Keys="0:1:0,1:1:0,"/>
</Variable>
<Variable Name="Film curve shoulder scale" Value="2.232213">
<Spline Keys="0:3:36,0.229167:3:36,0.5:2:36,0.770833:3:36,1:3:36,"/>
</Variable>
<Variable Name="Film curve midtones scale" Value="0.88389361">
<Spline Keys="0:0.5:36,0.229167:0.5:36,0.5:1:36,0.770833:0.5:36,1:0.5:36,"/>
</Variable>
<Variable Name="Film curve toe scale" Value="1">
<Spline Keys="0:1:36,0.25:1:36,0.5:1:65572,0.75:1:36,1:1:36,"/>
</Variable>
<Variable Name="Film curve whitepoint" Value="4">
<Spline Keys="0:4:36,0.25:4:36,0.5:4:65572,0.75:4:36,1:4:36,"/>
</Variable>
<Variable Name="Saturation" Value="1">
<Spline Keys="0:0.8:36,0.229167:0.8:36,0.5:1:36,0.751391:1:65572,0.770833:0.8:36,1:0.8:36,"/>
</Variable>
<Variable Name="Color balance" Color="1,1,1">
<Spline Keys="0:(1:1:1):36,0.25:(1:1:1):36,0.5:(1:1:1):36,0.75:(1:1:1):36,1:(1:1:1):36,"/>
</Variable>
<Variable Name="Scene key" Value="0.18000002">
<Spline Keys="0:0.18:36,0.25:0.18:36,0.5:0.18:65572,0.75:0.18:36,1:0.18:36,"/>
</Variable>
<Variable Name="Min exposure" Value="1">
<Spline Keys="0:1:36,0.25:1:36,0.5:1:65572,0.75:1:36,1:1:36,"/>
</Variable>
<Variable Name="Max exposure" Value="2.6142297">
<Spline Keys="0:2:36,0.229167:2:36,0.5:2.8:36,0.770833:2:36,1:2:36,"/>
</Variable>
<Variable Name="EV Min" Value="4.5">
<Spline Keys="0:4.5:0,1:4.5:0,"/>
</Variable>
<Variable Name="EV Max" Value="17">
<Spline Keys="0:17:0,1:17:0,"/>
</Variable>
<Variable Name="EV Auto compensation" Value="1.5">
<Spline Keys="0:1.5:0,1:1.5:0,"/>
</Variable>
<Variable Name="Bloom amount" Value="0.30899152">
<Spline Keys="0:1:36,0.229167:1:36,0.5:0.1:36,0.770833:1:36,1:1:36,"/>
</Variable>
<Variable Name="Filters: grain" Value="0">
<Spline Keys="0:0.3:65572,0.229167:0.3:36,0.25:0:36,0.5:0:36,0.75:0:36,1:0.3:36,"/>
</Variable>
<Variable Name="Filters: photofilter color" Color="0,0,0">
<Spline Keys="0:(0:0:0):36,0.25:(0:0:0):36,0.5:(0:0:0):458788,0.75:(0:0:0):36,1:(0:0:0):36,"/>
</Variable>
<Variable Name="Filters: photofilter density" Value="0">
<Spline Keys="0:0:36,0.25:0:36,0.5:0:36,0.75:0:36,1:0:36,"/>
</Variable>
<Variable Name="Dof: focus range" Value="500.00003">
<Spline Keys="0:500:36,0.25:500:36,0.5:500:65572,0.75:500:36,1:500:36,"/>
</Variable>
<Variable Name="Dof: blur amount" Value="0.10000001">
<Spline Keys="0:0.1:36,0.25:0.1:36,0.5:0.1:65572,0.75:0.1:36,1:0.1:36,"/>
</Variable>
<Variable Name="Cascade 0: Bias" Value="0.10000001">
<Spline Keys="0:0.1:36,0.25:0.1:36,0.5:0.1:65572,0.75:0.1:36,1:0.1:36,"/>
</Variable>
<Variable Name="Cascade 0: Slope Bias" Value="64">
<Spline Keys="0:64:36,0.25:64:36,0.5:64:65572,0.75:64:36,1:64:36,"/>
</Variable>
<Variable Name="Cascade 1: Bias" Value="0.10000001">
<Spline Keys="0:0.1:36,0.25:0.1:36,0.5:0.1:65572,0.75:0.1:36,1:0.1:36,"/>
</Variable>
<Variable Name="Cascade 1: Slope Bias" Value="23">
<Spline Keys="0:23:36,0.25:23:36,0.5:23:65572,0.75:23:36,1:23:36,"/>
</Variable>
<Variable Name="Cascade 2: Bias" Value="0.10000001">
<Spline Keys="0:0.1:36,0.25:0.1:36,0.5:0.1:65572,0.75:0.1:36,1:0.1:36,"/>
</Variable>
<Variable Name="Cascade 2: Slope Bias" Value="4">
<Spline Keys="0:4:36,0.25:4:36,0.5:4:65572,0.75:4:36,1:4:36,"/>
</Variable>
<Variable Name="Cascade 3: Bias" Value="0.10000001">
<Spline Keys="0:0.1:36,0.25:0.1:36,0.5:0.1:36,0.75:0.1:36,1:0.1:36,"/>
</Variable>
<Variable Name="Cascade 3: Slope Bias" Value="1">
<Spline Keys="0:1:36,0.25:1:36,0.5:1:65572,0.75:1:36,1:1:36,"/>
</Variable>
<Variable Name="Cascade 4: Bias" Value="0.10000001">
<Spline Keys="0:0.1:0,0.25:0.1:36,0.5:0.1:65572,0.75:0.1:36,1:0.1:36,"/>
</Variable>
<Variable Name="Cascade 4: Slope Bias" Value="1">
<Spline Keys="0:1:0,0.25:1:36,0.5:1:65572,0.75:1:36,1:1:36,"/>
</Variable>
<Variable Name="Cascade 5: Bias" Value="0.0099999998">
<Spline Keys="0:0.01:0,0.25:0.01:36,0.5:0.01:65572,0.75:0.01:36,1:0.01:36,"/>
</Variable>
<Variable Name="Cascade 5: Slope Bias" Value="1">
<Spline Keys="0:1:0,0.25:1:36,0.5:1:65572,0.75:1:36,1:1:36,"/>
</Variable>
<Variable Name="Cascade 6: Bias" Value="0.10000001">
<Spline Keys="0:0.1:0,0.25:0.1:36,0.5:0.1:36,0.75:0.1:36,1:0.1:36,"/>
</Variable>
<Variable Name="Cascade 6: Slope Bias" Value="1">
<Spline Keys="0:1:0,0.25:1:36,0.5:1:65572,0.75:1:36,1:1:36,"/>
</Variable>
<Variable Name="Cascade 7: Bias" Value="0.10000001">
<Spline Keys="0:0.1:0,0.25:0.1:36,0.5:0.1:36,0.75:0.1:36,1:0.1:36,"/>
</Variable>
<Variable Name="Cascade 7: Slope Bias" Value="1">
<Spline Keys="0:1:0,0.25:1:36,0.5:1:65572,0.75:1:36,1:1:36,"/>
</Variable>
<Variable Name="Shadow jittering" Value="2.4999998">
<Spline Keys="0:5:36,0.25:2.5:36,0.5:2.5:65572,0.75:2.5:36,1:5:0,"/>
</Variable>
<Variable Name="HDR dynamic power factor" Value="0">
<Spline Keys="0:0:36,0.25:0:36,0.5:0:65572,0.75:0:36,1:0:36,"/>
</Variable>
<Variable Name="Sky brightening (terrain occlusion)" Value="0">
<Spline Keys="0:0:36,0.25:0:36,0.5:0:36,0.75:0:36,1:0:36,"/>
</Variable>
<Variable Name="Sun color multiplier" Value="9.999999">
<Spline Keys="0:0.1:36,0.25:10:36,0.5:10:36,0.75:10:36,1:0.1:36,"/>
</Variable>
</TimeOfDay>

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0e6a5435c928079b27796f6b202bbc2623e7e454244ddc099a3cadf33b7cb9e9
size 63

@ -1,12 +0,0 @@
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0
0,0,0,0,0,0

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8739c76e681f900923b900c9df0ef75cf421d39cabb54650c4b9ad19b6a76d85
size 22

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:012caffa9354f6253d2e626ba183b44eb02a74eba286fde0430227ef024411e2
size 8961
oid sha256:817bd8dd22e185136418b60fba5b3552993687515d3d5ae96791f2c3be907b92
size 7233

@ -1,3 +1,3 @@
[General]
version=1
startScript="ImportActor -filename \"@assets@/characters/cowboy/actor/cowboy_01.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 0.000000 -yPos 0.000000 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.00000000,1.00000000\n"
startScript="ImportActor -filename \"@products@/characters/cowboy/actor/cowboy_01.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 0.000000 -yPos 0.000000 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.00000000,1.00000000\n"

@ -1,3 +1,3 @@
[General]
version=1
startScript="ImportActor -filename \"@assets@/levels/physics/c15096734_physxmaterials_defaultmateriallibrary/rin_skeleton_newgeo.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 0.000000 -yPos 0.000000 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.00000000,1.00000000\nLoadMotionSet -filename \"@assets@/Levels/Physics/C15096734_PhysxMaterials_DefaultMaterialLibrary/custom_motionset.motionset\"\nLoadAnimGraph -filename \"@assets@/Levels/Physics/C15096734_PhysxMaterials_DefaultMaterialLibrary/rin_physics.animgraph\"\n"
startScript="ImportActor -filename \"@products@/levels/physics/c15096734_physxmaterials_defaultmateriallibrary/rin_skeleton_newgeo.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 0.000000 -yPos 0.000000 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.00000000,1.00000000\nLoadMotionSet -filename \"@products@/levels/physics/c15096734_physxmaterials_defaultmateriallibrary/custom_motionset.motionset\"\nLoadAnimGraph -filename \"@products@/levels/physics/c15096734_physxmaterials_defaultmateriallibrary/rin_physics.animgraph\"\n"

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:619bcf0c2a2b08f4ffe05e60858c479828fe39d5530f4e488b9c0ec8a585ccb7
size 7735
oid sha256:cb97ada674d123c67d7a32eb65e81fa66472cf51f748054c4a4297649f2a0f40
size 5568

@ -1 +0,0 @@
/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:0,pc:0,provo:0"

@ -51,6 +51,14 @@
[
"Gems/UiBasics"
]
},
"Hair":
{
"SourcePaths":
[
"Gems/AtomTressFX/Assets",
"Gems/AtomTressFX/Assets/Passes"
]
}
}
}

@ -109,7 +109,7 @@
},
"MaterialLibrary": {
"assetId": {
"guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
"guid": "{7CDF49C3-91A2-5C4E-B642-6D1AEC80E70E}"
},
"loadBehavior": "QueueLoad",
"assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"

@ -121,7 +121,7 @@
},
"MaterialLibrary": {
"assetId": {
"guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
"guid": "{7CDF49C3-91A2-5C4E-B642-6D1AEC80E70E}"
},
"loadBehavior": "QueueLoad",
"assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"

@ -121,7 +121,7 @@
},
"MaterialLibrary": {
"assetId": {
"guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
"guid": "{7CDF49C3-91A2-5C4E-B642-6D1AEC80E70E}"
},
"loadBehavior": "QueueLoad",
"assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"

@ -121,7 +121,7 @@
},
"MaterialLibrary": {
"assetId": {
"guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
"guid": "{7CDF49C3-91A2-5C4E-B642-6D1AEC80E70E}"
},
"loadBehavior": "QueueLoad",
"assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"

@ -121,7 +121,7 @@
},
"MaterialLibrary": {
"assetId": {
"guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
"guid": "{7CDF49C3-91A2-5C4E-B642-6D1AEC80E70E}"
},
"loadBehavior": "QueueLoad",
"assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"

@ -103,7 +103,7 @@
},
"MaterialLibrary": {
"assetId": {
"guid": "{62446378-67F8-5E49-AC31-761DD5942695}"
"guid": "{7CDF49C3-91A2-5C4E-B642-6D1AEC80E70E}"
},
"loadBehavior": "QueueLoad",
"assetHint": "assets/physics/surfacetypemateriallibrary.physmaterial"

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:827a63985273229050bf4f63030bcc666f045091fe81cf8157a9ca23b40074b6
size 3214

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d8d24963e6e8765205bc79cbe2304fc39f1245ee75249e2834a71c96c3cab824
size 22700

@ -0,0 +1,8 @@
{
"values": [
{
"$type": "ScriptProcessorRule",
"scriptFilename": "Editor/Scripts/scene_mesh_to_prefab.py"
}
]
}

@ -1 +0,0 @@
/autooptimizefile=0 /preset=LensOptics /reduce=-1

@ -1 +0,0 @@
/autooptimizefile=0 /preset=Albedo /reduce=0

@ -1 +0,0 @@
/autooptimizefile=0 /preset=Terrain_Albedo_HighPassed /reduce=0

@ -1 +0,0 @@
/autooptimizefile=0 /preset=Terrain_Albedo_HighPassed /reduce=0

@ -33,7 +33,6 @@ ly_add_target(
BUILD_DEPENDENCIES
PRIVATE
Legacy::CryCommon
3rdParty::zlib
PUBLIC
3rdParty::Qt::Core
3rdParty::Qt::Gui
@ -105,7 +104,6 @@ ly_add_target(
3rdParty::Qt::Concurrent
3rdParty::tiff
3rdParty::squish-ccr
3rdParty::zlib
3rdParty::AWSNativeSDK::STS
Legacy::CryCommon
Legacy::EditorCommon

@ -278,17 +278,16 @@ void CFolderTreeCtrl::LoadTreeRec(const QString& currentFolder)
void CFolderTreeCtrl::AddItem(const QString& path)
{
QString folder;
QString fileNameWithoutExtension;
QString ext;
Path::Split(path, folder, fileNameWithoutExtension, ext);
AZ::IO::FixedMaxPath folder{ AZ::IO::PathView(path.toUtf8().constData()) };
AZ::IO::FixedMaxPath fileNameWithoutExtension = folder.Extension();
folder = folder.ParentPath();
auto regex = QRegExp(m_fileNameSpec, Qt::CaseInsensitive, QRegExp::Wildcard);
if (regex.exactMatch(path))
{
CTreeItem* folderTreeItem = CreateFolderItems(folder);
folderTreeItem->AddChild(fileNameWithoutExtension, path, eTreeImage_File);
CTreeItem* folderTreeItem = CreateFolderItems(QString::fromUtf8(folder.c_str(), static_cast<int>(folder.Native().size())));
folderTreeItem->AddChild(QString::fromUtf8(fileNameWithoutExtension.c_str(),
static_cast<int>(fileNameWithoutExtension.Native().size())), path, eTreeImage_File);
}
}

@ -32,6 +32,7 @@
#include <AzFramework/API/ApplicationAPI.h>
// AzToolsFramework
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h>
// AzQtComponents
@ -166,15 +167,14 @@ LevelEditorMenuHandler::LevelEditorMenuHandler(MainWindow* mainWindow, QtViewPan
m_mainWindow->menuBar()->setNativeMenuBar(true);
#endif
ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
AzToolsFramework::GetEntityContextId());
ViewportEditorModeNotificationsBus::Handler::BusConnect(GetEntityContextId());
EditorMenuRequestBus::Handler::BusConnect();
}
LevelEditorMenuHandler::~LevelEditorMenuHandler()
{
EditorMenuRequestBus::Handler::BusDisconnect();
ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
}
void LevelEditorMenuHandler::Initialize()
@ -487,8 +487,6 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
editMenu.AddAction(AzToolsFramework::EditPivot);
editMenu.AddAction(AzToolsFramework::EditReset);
editMenu.AddAction(AzToolsFramework::EditResetManipulator);
editMenu.AddAction(AzToolsFramework::EditResetLocal);
editMenu.AddAction(AzToolsFramework::EditResetWorld);
// Hide Selection
editMenu.AddAction(AzToolsFramework::HideSelection);
@ -1186,36 +1184,44 @@ void LevelEditorMenuHandler::AddDisableActionInSimModeListener(QAction* action)
}));
}
void LevelEditorMenuHandler::EnteredComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
void LevelEditorMenuHandler::OnEditorModeActivated(
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
{
auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
if (!menuWrapper.isNull())
if (mode == ViewportEditorMode::Component)
{
// copy of menu actions
auto actions = menuWrapper.Get()->actions();
// remove all non-reserved edit menu options
actions.erase(
std::remove_if(actions.begin(), actions.end(), [](QAction* action)
{
return !action->property("Reserved").toBool();
}),
actions.end());
if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
!menuWrapper.isNull())
{
// copy of menu actions
auto actions = menuWrapper.Get()->actions();
// remove all non-reserved edit menu options
actions.erase(
std::remove_if(actions.begin(), actions.end(), [](QAction* action)
{
return !action->property("Reserved").toBool();
}),
actions.end());
// clear and update the menu with new actions
menuWrapper.Get()->clear();
menuWrapper.Get()->addActions(actions);
// clear and update the menu with new actions
menuWrapper.Get()->clear();
menuWrapper.Get()->addActions(actions);
}
}
}
void LevelEditorMenuHandler::LeftComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
void LevelEditorMenuHandler::OnEditorModeDeactivated(
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
{
RestoreEditMenuToDefault();
if (mode == ViewportEditorMode::Component)
{
RestoreEditMenuToDefault();
}
}
void LevelEditorMenuHandler::AddEditMenuAction(QAction* action)
{
auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
if (!menuWrapper.isNull())
if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
!menuWrapper.isNull())
{
menuWrapper.Get()->addAction(action);
}
@ -1239,8 +1245,8 @@ void LevelEditorMenuHandler::AddMenuAction(AZStd::string_view categoryId, QActio
void LevelEditorMenuHandler::RestoreEditMenuToDefault()
{
auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
if (!menuWrapper.isNull())
if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
!menuWrapper.isNull())
{
menuWrapper.Get()->clear();
PopulateEditMenu(menuWrapper);

@ -18,7 +18,7 @@
#include <QPointer>
#include "ActionManager.h"
#include "QtViewPaneManager.h"
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
#include <AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h>
#endif
class MainWindow;
@ -28,7 +28,7 @@ struct QtViewPane;
class LevelEditorMenuHandler
: public QObject
, private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
, private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler
, private AzToolsFramework::EditorMenuRequestBus::Handler
{
Q_OBJECT
@ -88,9 +88,11 @@ private:
void AddDisableActionInSimModeListener(QAction* action);
// EditorComponentModeNotificationBus
void EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
void LeftComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
// ViewportEditorModeNotificationsBus overrides ...
void OnEditorModeActivated(
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
void OnEditorModeDeactivated(
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
// EditorMenuRequestBus
void AddEditMenuAction(QAction* action) override;

@ -33,6 +33,7 @@ public:
protected:
void SetupEnvironment() override
{
AttachEditorCoreAZEnvironment(AZ::Environment::GetInstance());
m_allocatorScope.ActivateAllocators();
m_cryPak = new NiceMock<CryPakMock>();
@ -49,6 +50,7 @@ protected:
{
delete m_cryPak;
m_allocatorScope.DeactivateAllocators();
DetachEditorCoreAZEnvironment();
}
private:

@ -5,22 +5,29 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "EditorDefs.h"
#include <AzTest/AzTest.h>
#include "Util/PathUtil.h"
#include <CrySystemBus.h>
TEST(PathUtil, GamePathToFullPath_DoesNotBufferOverflow)
#include <AzCore/UnitTest/TestTypes.h>
#include <Util/PathUtil.h>
namespace UnitTest
{
// There are no test assertions in this test because the purpose is just to verify that the test runs without crashing
QString pngExtension(".png");
class PathUtil
: public ScopedAllocatorSetupFixture
{
};
TEST_F(PathUtil, GamePathToFullPath_DoesNotBufferOverflow)
{
// There are no test assertions in this test because the purpose is just to verify that the test runs without crashing
QString pngExtension(".png");
// Create a string of lenth AZ_MAX_PATH_LEN that ends in .png
QString longStringMaxPath(AZ_MAX_PATH_LEN, 'x');
longStringMaxPath.replace(longStringMaxPath.length() - pngExtension.length(), longStringMaxPath.length(), pngExtension);
Path::GamePathToFullPath(longStringMaxPath);
// Create a string of length AZ_MAX_PATH_LEN that ends in .png
QString longStringMaxPath(AZ_MAX_PATH_LEN, 'x');
longStringMaxPath.replace(longStringMaxPath.length() - pngExtension.length(), longStringMaxPath.length(), pngExtension);
AZ_TEST_START_TRACE_SUPPRESSION;
Path::GamePathToFullPath(longStringMaxPath);
AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
QString longStringMaxPathPlusOne(AZ_MAX_PATH_LEN + 1, 'x');
longStringMaxPathPlusOne.replace(longStringMaxPathPlusOne.length() - pngExtension.length(), longStringMaxPathPlusOne.length(), pngExtension);
Path::GamePathToFullPath(longStringMaxPathPlusOne);
QString longStringMaxPathPlusOne(AZ_MAX_PATH_LEN + 1, 'x');
longStringMaxPathPlusOne.replace(longStringMaxPathPlusOne.length() - pngExtension.length(), longStringMaxPathPlusOne.length(), pngExtension);
Path::GamePathToFullPath(longStringMaxPathPlusOne);
}
}

@ -2124,6 +2124,8 @@ bool CCryEditApp::FixDanglingSharedMemory(const QString& sharedMemName) const
int CCryEditApp::ExitInstance(int exitCode)
{
AZ_TracePrintf("Exit", "Called ExitInstance() with exit code: 0x%x", exitCode);
if (m_pEditor)
{
m_pEditor->OnBeginShutdownSequence();
@ -2642,7 +2644,7 @@ void CCryEditApp::OnFileResaveSlices()
sliceAssetInfos.reserve(5000);
AZ::Data::AssetCatalogRequests::AssetEnumerationCB sliceCountCb = [&sliceAssetInfos]([[maybe_unused]] const AZ::Data::AssetId id, const AZ::Data::AssetInfo& info)
{
// Only add slices and nothing that has been temporarily added to the catalog with a macro in it (ie @devroot@)
// Only add slices and nothing that has been temporarily added to the catalog with a macro in it (ie @engroot@)
if (info.m_assetType == azrtti_typeid<AZ::SliceAsset>() && info.m_relativePath[0] != '@')
{
sliceAssetInfos.push_back(info);

@ -1108,7 +1108,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename)
if (QFileInfo(filename).isRelative())
{
// Resolving the path through resolvepath would normalize and lowcase it, and in this case, we don't want that.
fullPathName = Path::ToUnixPath(QDir(QString::fromUtf8(gEnv->pFileIO->GetAlias("@devassets@"))).absoluteFilePath(fullPathName));
fullPathName = Path::ToUnixPath(QDir(QString::fromUtf8(gEnv->pFileIO->GetAlias("@projectroot@"))).absoluteFilePath(fullPathName));
}
if (!CFileUtil::OverwriteFile(fullPathName))
@ -2159,7 +2159,7 @@ bool CCryEditDoc::LoadXmlArchiveArray(TDocMultiArchive& arrXmlAr, const QString&
xmlAr.bLoading = true;
// bound to the level folder, as if it were the assets folder.
// this mounts (whateverlevelname.ly) as @assets@/Levels/whateverlevelname/ and thus it works...
// this mounts (whateverlevelname.ly) as @products@/Levels/whateverlevelname/ and thus it works...
bool openLevelPakFileSuccess = pIPak->OpenPack(levelPath.toUtf8().data(), absoluteLevelPath.toUtf8().data());
if (!openLevelPakFileSuccess)
{

@ -91,7 +91,7 @@ CPythonScriptsDialog::CPythonScriptsDialog(QWidget* parent)
{
AZ::IO::Path newSourcePath = jsonSourcePathPointer;
// Resolve any file aliases first - Do not use ResolvePath() as that assumes
// any relative path is underneath the @assets@ alias
// any relative path is underneath the @products@ alias
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
{
AZ::IO::FixedMaxPath replacedAliasPath;

@ -14,6 +14,8 @@
// Editor
#include "CryEdit.h"
#include <AzCore/Utils/Utils.h>
//////////////////////////////////////////////////////////////////////////
CEditorFileMonitor::CEditorFileMonitor()
{
@ -177,26 +179,14 @@ void CEditorFileMonitor::OnFileMonitorChange(const SFileChangeInfo& rChange)
// Make file relative to PrimaryCD folder.
QString filename = rChange.filename;
// Remove game directory if present in path.
const QString rootPath =
QDir::fromNativeSeparators(QString::fromLatin1(Path::GetEditingRootFolder().c_str()));
if (filename.startsWith(rootPath, Qt::CaseInsensitive))
{
filename = filename.right(filename.length() - rootPath.length());
}
// Make sure there is no leading slash
if (!filename.isEmpty() && (filename[0] == '\\' || filename[0] == '/'))
{
filename = filename.mid(1);
}
// Make path relative to the the project directory
AZ::IO::Path projectPath{ AZ::Utils::GetProjectPath() };
AZ::IO::FixedMaxPath projectRelativeFilePath = AZ::IO::PathView(filename.toUtf8().constData()).LexicallyProximate(
projectPath);
if (!filename.isEmpty())
if (!projectRelativeFilePath.empty())
{
//remove game name. Make it relative to the game folder
const QString filenameRelGame = RemoveGameName(filename);
const int extIndex = filename.lastIndexOf('.');
const QString ext = filename.right(filename.length() - 1 - extIndex);
AZ::IO::PathView ext = projectRelativeFilePath.Extension();
// Check for File Monitor callback
std::vector<SFileChangeCallback>::iterator iter;
@ -207,15 +197,11 @@ void CEditorFileMonitor::OnFileMonitorChange(const SFileChangeInfo& rChange)
// We compare against length of callback string, so we get directory matches as well as full filenames
if (sCallback.pListener)
{
if (sCallback.extension == "*" || ext.compare(sCallback.extension, Qt::CaseInsensitive) == 0)
if (sCallback.extension == "*" || AZ::IO::PathView(sCallback.extension.toUtf8().constData()) == ext)
{
if (filenameRelGame.compare(sCallback.item, Qt::CaseInsensitive) == 0)
{
sCallback.pListener->OnFileChange(qPrintable(filenameRelGame), IFileChangeListener::EChangeType(rChange.changeType));
}
else if (filename.compare(sCallback.item, Qt::CaseInsensitive) == 0)
if (AZ::IO::PathView(sCallback.item.toUtf8().constData()) == projectRelativeFilePath)
{
sCallback.pListener->OnFileChange(qPrintable(filename), IFileChangeListener::EChangeType(rChange.changeType));
sCallback.pListener->OnFileChange(qPrintable(projectRelativeFilePath.c_str()), IFileChangeListener::EChangeType(rChange.changeType));
}
}
}

@ -95,7 +95,8 @@ namespace SandboxEditor
cameras.AddCamera(m_firstPersonPanCamera);
cameras.AddCamera(m_firstPersonTranslateCamera);
cameras.AddCamera(m_firstPersonScrollCamera);
cameras.AddCamera(m_pivotCamera);
cameras.AddCamera(m_firstPersonFocusCamera);
cameras.AddCamera(m_orbitCamera);
});
return controller;
@ -111,6 +112,7 @@ namespace SandboxEditor
viewportId, &AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::BeginCursorCapture);
}
};
const auto showCursor = [viewportId = m_viewportId]
{
if (SandboxEditor::CameraCaptureCursorForLook())
@ -133,7 +135,7 @@ namespace SandboxEditor
m_firstPersonRotateCamera->SetActivationEndedFn(showCursor);
m_firstPersonPanCamera = AZStd::make_shared<AzFramework::PanCameraInput>(
SandboxEditor::CameraFreePanChannelId(), AzFramework::LookPan, AzFramework::TranslatePivot);
SandboxEditor::CameraFreePanChannelId(), AzFramework::LookPan, AzFramework::TranslatePivotLook);
m_firstPersonPanCamera->m_panSpeedFn = []
{
@ -153,7 +155,7 @@ namespace SandboxEditor
const auto translateCameraInputChannelIds = BuildTranslateCameraInputChannelIds();
m_firstPersonTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(
translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivot);
translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivotLook);
m_firstPersonTranslateCamera->m_translateSpeedFn = []
{
@ -165,90 +167,111 @@ namespace SandboxEditor
return SandboxEditor::CameraBoostMultiplier();
};
m_firstPersonScrollCamera = AZStd::make_shared<AzFramework::ScrollTranslationCameraInput>();
m_firstPersonScrollCamera = AZStd::make_shared<AzFramework::LookScrollTranslationCameraInput>();
m_firstPersonScrollCamera->m_scrollSpeedFn = []
{
return SandboxEditor::CameraScrollSpeed();
};
m_pivotCamera = AZStd::make_shared<AzFramework::PivotCameraInput>(SandboxEditor::CameraPivotChannelId());
const auto pivotFn = []
{
// use the manipulator transform as the pivot point
AZStd::optional<AZ::Transform> entityPivot;
AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
entityPivot, AzToolsFramework::GetEntityContextId(),
&AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
m_pivotCamera->SetPivotFn(
[]([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction)
if (entityPivot.has_value())
{
// use the manipulator transform as the pivot point
AZStd::optional<AZ::Transform> entityPivot;
AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
entityPivot, AzToolsFramework::GetEntityContextId(),
&AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
// otherwise just use the identity
return entityPivot.value_or(AZ::Transform::CreateIdentity()).GetTranslation();
return entityPivot->GetTranslation();
}
// otherwise just use the identity
return AZ::Vector3::CreateZero();
};
m_firstPersonFocusCamera =
AZStd::make_shared<AzFramework::FocusCameraInput>(SandboxEditor::CameraFocusChannelId(), AzFramework::FocusLook);
m_firstPersonFocusCamera->SetPivotFn(pivotFn);
m_orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>(SandboxEditor::CameraOrbitChannelId());
m_orbitCamera->SetPivotFn(
[pivotFn]([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction)
{
return pivotFn();
});
m_pivotRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(SandboxEditor::CameraPivotLookChannelId());
m_orbitRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(SandboxEditor::CameraOrbitLookChannelId());
m_pivotRotateCamera->m_rotateSpeedFn = []
m_orbitRotateCamera->m_rotateSpeedFn = []
{
return SandboxEditor::CameraRotateSpeed();
};
m_pivotRotateCamera->m_invertYawFn = []
m_orbitRotateCamera->m_invertYawFn = []
{
return SandboxEditor::CameraPivotYawRotationInverted();
return SandboxEditor::CameraOrbitYawRotationInverted();
};
m_pivotTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(
translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslateOffset);
m_orbitTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(
translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslateOffsetOrbit);
m_pivotTranslateCamera->m_translateSpeedFn = []
m_orbitTranslateCamera->m_translateSpeedFn = []
{
return SandboxEditor::CameraTranslateSpeed();
};
m_pivotTranslateCamera->m_boostMultiplierFn = []
m_orbitTranslateCamera->m_boostMultiplierFn = []
{
return SandboxEditor::CameraBoostMultiplier();
};
m_pivotDollyScrollCamera = AZStd::make_shared<AzFramework::PivotDollyScrollCameraInput>();
m_orbitDollyScrollCamera = AZStd::make_shared<AzFramework::OrbitDollyScrollCameraInput>();
m_pivotDollyScrollCamera->m_scrollSpeedFn = []
m_orbitDollyScrollCamera->m_scrollSpeedFn = []
{
return SandboxEditor::CameraScrollSpeed();
};
m_pivotDollyMoveCamera = AZStd::make_shared<AzFramework::PivotDollyMotionCameraInput>(SandboxEditor::CameraPivotDollyChannelId());
m_orbitDollyMoveCamera = AZStd::make_shared<AzFramework::OrbitDollyMotionCameraInput>(SandboxEditor::CameraOrbitDollyChannelId());
m_pivotDollyMoveCamera->m_motionSpeedFn = []
m_orbitDollyMoveCamera->m_motionSpeedFn = []
{
return SandboxEditor::CameraDollyMotionSpeed();
};
m_pivotPanCamera = AZStd::make_shared<AzFramework::PanCameraInput>(
SandboxEditor::CameraPivotPanChannelId(), AzFramework::LookPan, AzFramework::TranslateOffset);
m_orbitPanCamera = AZStd::make_shared<AzFramework::PanCameraInput>(
SandboxEditor::CameraOrbitPanChannelId(), AzFramework::LookPan, AzFramework::TranslateOffsetOrbit);
m_pivotPanCamera->m_panSpeedFn = []
m_orbitPanCamera->m_panSpeedFn = []
{
return SandboxEditor::CameraPanSpeed();
};
m_pivotPanCamera->m_invertPanXFn = []
m_orbitPanCamera->m_invertPanXFn = []
{
return SandboxEditor::CameraPanInvertedX();
};
m_pivotPanCamera->m_invertPanYFn = []
m_orbitPanCamera->m_invertPanYFn = []
{
return SandboxEditor::CameraPanInvertedY();
};
m_pivotCamera->m_pivotCameras.AddCamera(m_pivotRotateCamera);
m_pivotCamera->m_pivotCameras.AddCamera(m_pivotTranslateCamera);
m_pivotCamera->m_pivotCameras.AddCamera(m_pivotDollyScrollCamera);
m_pivotCamera->m_pivotCameras.AddCamera(m_pivotDollyMoveCamera);
m_pivotCamera->m_pivotCameras.AddCamera(m_pivotPanCamera);
m_orbitFocusCamera =
AZStd::make_shared<AzFramework::FocusCameraInput>(SandboxEditor::CameraFocusChannelId(), AzFramework::FocusOrbit);
m_orbitFocusCamera->SetPivotFn(pivotFn);
m_orbitCamera->m_orbitCameras.AddCamera(m_orbitRotateCamera);
m_orbitCamera->m_orbitCameras.AddCamera(m_orbitTranslateCamera);
m_orbitCamera->m_orbitCameras.AddCamera(m_orbitDollyScrollCamera);
m_orbitCamera->m_orbitCameras.AddCamera(m_orbitDollyMoveCamera);
m_orbitCamera->m_orbitCameras.AddCamera(m_orbitPanCamera);
m_orbitCamera->m_orbitCameras.AddCamera(m_orbitFocusCamera);
}
void EditorModularViewportCameraComposer::OnEditorModularViewportCameraComposerSettingsChanged()
@ -257,12 +280,14 @@ namespace SandboxEditor
m_firstPersonTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds);
m_firstPersonPanCamera->SetPanInputChannelId(SandboxEditor::CameraFreePanChannelId());
m_firstPersonRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraFreeLookChannelId());
m_pivotCamera->SetPivotInputChannelId(SandboxEditor::CameraPivotChannelId());
m_pivotTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds);
m_pivotPanCamera->SetPanInputChannelId(SandboxEditor::CameraPivotPanChannelId());
m_pivotRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraPivotLookChannelId());
m_pivotDollyMoveCamera->SetDollyInputChannelId(SandboxEditor::CameraPivotDollyChannelId());
m_firstPersonFocusCamera->SetFocusInputChannelId(SandboxEditor::CameraFocusChannelId());
m_orbitCamera->SetOrbitInputChannelId(SandboxEditor::CameraOrbitChannelId());
m_orbitTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds);
m_orbitPanCamera->SetPanInputChannelId(SandboxEditor::CameraOrbitPanChannelId());
m_orbitRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraOrbitLookChannelId());
m_orbitDollyMoveCamera->SetDollyInputChannelId(SandboxEditor::CameraOrbitDollyChannelId());
m_orbitFocusCamera->SetFocusInputChannelId(SandboxEditor::CameraFocusChannelId());
}
void EditorModularViewportCameraComposer::OnViewportViewEntityChanged(const AZ::EntityId& viewEntityId)

@ -41,13 +41,15 @@ namespace SandboxEditor
AZStd::shared_ptr<AzFramework::RotateCameraInput> m_firstPersonRotateCamera;
AZStd::shared_ptr<AzFramework::PanCameraInput> m_firstPersonPanCamera;
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_firstPersonTranslateCamera;
AZStd::shared_ptr<AzFramework::ScrollTranslationCameraInput> m_firstPersonScrollCamera;
AZStd::shared_ptr<AzFramework::PivotCameraInput> m_pivotCamera;
AZStd::shared_ptr<AzFramework::RotateCameraInput> m_pivotRotateCamera;
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_pivotTranslateCamera;
AZStd::shared_ptr<AzFramework::PivotDollyScrollCameraInput> m_pivotDollyScrollCamera;
AZStd::shared_ptr<AzFramework::PivotDollyMotionCameraInput> m_pivotDollyMoveCamera;
AZStd::shared_ptr<AzFramework::PanCameraInput> m_pivotPanCamera;
AZStd::shared_ptr<AzFramework::LookScrollTranslationCameraInput> m_firstPersonScrollCamera;
AZStd::shared_ptr<AzFramework::FocusCameraInput> m_firstPersonFocusCamera;
AZStd::shared_ptr<AzFramework::OrbitCameraInput> m_orbitCamera;
AZStd::shared_ptr<AzFramework::RotateCameraInput> m_orbitRotateCamera;
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_orbitTranslateCamera;
AZStd::shared_ptr<AzFramework::OrbitDollyScrollCameraInput> m_orbitDollyScrollCamera;
AZStd::shared_ptr<AzFramework::OrbitDollyMotionCameraInput> m_orbitDollyMoveCamera;
AZStd::shared_ptr<AzFramework::PanCameraInput> m_orbitPanCamera;
AZStd::shared_ptr<AzFramework::FocusCameraInput> m_orbitFocusCamera;
AzFramework::ViewportId m_viewportId;
};

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

Loading…
Cancel
Save