Merge remote-tracking branch 'upstream/development' into Atom/santorac/RemixableMaterialTypes4_FlatMaterialFiles

Signed-off-by: santorac <55155825+santorac@users.noreply.github.com>
monroegm-disable-blank-issue-2
santorac 4 years ago
commit 1894cd60c7

@ -17,34 +17,34 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesti
from base import TestAutomationBase
@pytest.mark.SUITE_periodic
@pytest.mark.SUITE_main
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(TestAutomationBase):
def test_ActorSplitsAfterCollision(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterCollision as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_ActorSplitsAfterRadialDamage(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterRadialDamage as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_ActorSplitsAfterCapsuleDamage(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterCapsuleDamage as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_ActorSplitsAfterImpactSpreadDamage(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterImpactSpreadDamage as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_ActorSplitsAfterShearDamage(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterShearDamage as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_ActorSplitsAfterTriangleDamage(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterTriangleDamage as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_ActorSplitsAfterStressDamage(self, request, workspace, editor, launcher_platform):
from .tests import Blast_ActorSplitsAfterStressDamage as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)

@ -14,7 +14,7 @@ import azlmbr.math as math
import azlmbr.asset as asset
# Open a level (any level should work)
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'WaterSample')
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'Base')
def GetSetCompareTest(component, path, assetId):
# Test Get/Set (get old value, set new value, check that new value was set correctly)

@ -24,6 +24,7 @@ from hydra_utils import launch_test_case
@pytest.mark.parametrize('level', ['Simple'])
class TestComponentCommands(object):
# It needs a new test level in prefab format to make it testable again.
def test_MeshComponentBasics(self, request, editor, level, launcher_platform):
unexpected_lines=[]

@ -5,6 +5,8 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# It needs a new test level in prefab format to make it testable again.
# Tests a portion of the Component CRUD Python API while the Editor is running
import azlmbr.bus as bus
@ -18,7 +20,7 @@ def CompareComponentEntityIdPairs(component1, component2):
return component1.Equal(component2)
# Open a level (any level should work)
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'WaterSample')
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'Base')
# Get Component Types for Mesh and Comment
typeIdsList = editor.EditorComponentAPIBus(bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Mesh", "Comment", "Mesh Collider"], entity.EntityType().Game)

@ -13,7 +13,7 @@ import azlmbr.entity as entity
import azlmbr.math as math
# Open a level (any level should work)
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'WaterSample')
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'Base')
def GetSetCompareTest(component, path, value):
oldObj = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentProperty', component, path)

@ -12,7 +12,7 @@ import azlmbr.editor as editor
from azlmbr.entity import EntityId
# Open a level (any level should work)
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'WaterSample')
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'Base')
parentEntityId = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', EntityId())
childEntityId = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', EntityId())

@ -32,7 +32,7 @@ def onEditorEntityDeleted(parameters):
# Open a level (any level should work)
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'WaterSample')
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'Base')
# Listen for notifications when entities are created/deleted
handler = bus.NotificationHandler('EditorEntityContextNotificationBus')

@ -16,13 +16,13 @@ import os
sys.path.append(os.path.dirname(__file__))
from hydra_utils import launch_test_case
@pytest.mark.SUITE_sandbox
@pytest.mark.parametrize('launcher_platform', ['windows_editor'])
@pytest.mark.parametrize('project', ['AutomatedTesting'])
@pytest.mark.parametrize('level', ['Simple'])
class TestObjectManagerAutomation(object):
# It needs a new test level in prefab format to make it testable again.
def test_ViewPane(self, request, editor, level, launcher_platform):
unexpected_lines=[]

@ -20,12 +20,10 @@ def fetch_vector3_parts(vec3):
general.idle_enable(True)
# Try to open the WaterSample level. If not, fail the test.
# We need to rely on an existing level since the API does not provide
# a way to create entities, but only lets us manipulate them.
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'WaterSample')
# It needs a new test level in prefab format to make it testable again.
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'Base')
if (editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'GetCurrentLevelName') == 'WaterSample'):
if (editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'GetCurrentLevelName') == 'Base'):
objs_list = general.get_all_objects()

@ -21,8 +21,7 @@ import azlmbr.bus as bus
import azlmbr.entity as entity
import azlmbr.editor as editor
import azlmbr.legacy.general as general
import editor_python_test_tools.pyside_component_utils as pysde_component_utils
import editor_python_test_tools.pyside_component_utils as pyside_component_utils
def PySide_Example_test_case():
# Open level, any level should work

@ -13,7 +13,7 @@ import azlmbr.math
import azlmbr.legacy.general as general
# Open a level (any level should work)
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'WaterSample')
editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'OpenLevelNoPrompt', 'Base')
general.idle_wait(0.5)

@ -11,7 +11,7 @@ import azlmbr.math
import azlmbr.legacy.general as general
# Open a level (any level should work)
general.open_level_no_prompt('WaterSample')
general.open_level_no_prompt('Base')
general.idle_wait(0.5)
test_success = True

@ -20,7 +20,7 @@ from editor_python_test_tools.utils import TestHelper as helper
def open_base_level():
helper.init_idle()
helper.open_level("Prefab", "Base")
helper.open_level("", "Base")
def find_entity_by_name(entity_name):

@ -61,7 +61,7 @@ def launch_and_validate_results(request, test_directory, editor, editor_script,
from os import path
editor.args.extend([
"--regset=/Amazon/Preferences/EnablePrefabSystem=true",
f"--regset-file={os.path.join(workspace.paths.engine_root(), 'Registry', 'prefab.test.setreg')}"])
f"--regset-file={os.path.join(editor.workspace.paths.engine_root(), 'Registry', 'prefab.test.setreg')}"])
else:
editor.args.extend(["--regset=/Amazon/Preferences/EnablePrefabSystem=false"])

@ -7,8 +7,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
import PySide2
import editor_python_test_tools.pyside_utils
import editor_python_test_tools.pyside_utils as pyside_utils
def get_component_combobox_values(component_name, property_name, log_fn=None):
"""

@ -67,7 +67,7 @@ class TestHelper:
return result == 0
@staticmethod
def open_level(directory : str, level : str):
def open_level(directory : str, level : str, no_prompt: bool = True):
# type: (str, str) -> None
"""
:param level: the name of the level folder in AutomatedTesting\\Physics\\
@ -75,7 +75,11 @@ class TestHelper:
:return: None
"""
Report.info("Open level {}/{}".format(directory, level))
success = general.open_level_no_prompt(os.path.join(directory, level))
if no_prompt:
success = general.open_level_no_prompt(os.path.join(directory, level))
else:
success = general.open_level(os.path.join(directory, level))
if not success:
open_level_name = general.get_current_level_name()
if open_level_name == level:

@ -52,11 +52,11 @@ class TestAutomation(TestAutomationBase):
@revert_physics_config
def test_CharacterController_SwitchLevels(self, request, workspace, editor, launcher_platform):
from .tests.character_controller import CharacterController_SwitchLevels as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_Ragdoll_AddPhysxRagdollComponentWorks(self, request, workspace, editor, launcher_platform):
from .tests.ragdoll import Ragdoll_AddPhysxRagdollComponentWorks as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
def test_ScriptCanvas_MultipleRaycastNode(self, request, workspace, editor, launcher_platform):
@ -81,7 +81,7 @@ class TestAutomation(TestAutomationBase):
@revert_physics_config
def test_Collider_PxMeshConvexMeshCollides(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_PxMeshConvexMeshCollides as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
def test_ShapeCollider_CylinderShapeCollides(self, request, workspace, editor, launcher_platform):

@ -53,7 +53,8 @@ class EditorSingleTest_WithFileOverrides(EditorSingleTest):
for f in original_file_list:
fm._restore_file(f, file_list[f])
@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.")
# @pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.")
@pytest.mark.SUITE_main
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@ -72,6 +73,48 @@ class TestAutomationWithPrefabSystemEnabled(EditorTestSuite):
class C4982802_PhysXColliderShape_CanBeSelected(EditorSharedTest):
from .tests.collider import Collider_CapsuleShapeEditing as test_module
class C14654881_CharacterController_SwitchLevels(EditorSharedTest):
from .tests.character_controller import CharacterController_SwitchLevels as test_module
class C14861500_DefaultSetting_ColliderShape(EditorSharedTest):
from .tests.collider import Collider_CheckDefaultShapeSettingIsPxMesh as test_module
class C4044695_PhysXCollider_AddMultipleSurfaceFbx(EditorSharedTest):
from .tests.collider import Collider_MultipleSurfaceSlots as test_module
class C14861501_PhysXCollider_RenderMeshAutoAssigned(EditorSharedTest):
from .tests.collider import Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent as test_module
@pytest.mark.xfail(reason="This will fail due to this issue ATOM-15487.")
class C14861502_PhysXCollider_AssetAutoAssigned(EditorSharedTest):
from .tests.collider import Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent as test_module
class C4982803_Enable_PxMesh_Option(EditorSharedTest):
from .tests.collider import Collider_PxMeshConvexMeshCollides as test_module
class C15096740_Material_LibraryUpdatedCorrectly(EditorSharedTest):
from .tests.material import Material_LibraryClearingAssignsDefault as test_module
class C17411467_AddPhysxRagdollComponent(EditorSharedTest):
from .tests.ragdoll import Ragdoll_AddPhysxRagdollComponentWorks as test_module
class C19578021_ShapeCollider_CanBeAdded(EditorSharedTest):
from .tests.shape_collider import ShapeCollider_CanBeAddedWitNoWarnings as test_module
class C19578018_ShapeColliderWithNoShapeComponent(EditorSharedTest):
from .tests.shape_collider import ShapeCollider_InactiveWhenNoShapeComponent as test_module
class C19723164_ShapeCollider_WontCrashEditor(EditorSharedTest):
from .tests.shape_collider import ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor as test_module
class C12905528_ForceRegion_WithNonTriggerCollider(EditorSharedTest):
from .tests.force_region import ForceRegion_WithNonTriggerColliderWarning as test_module
# Fixme: expected_lines = ["[Warning] (PhysX Force Region) - Please ensure collider component marked as trigger exists in entity"]
class C14861504_RenderMeshAsset_WithNoPxAsset(EditorSharedTest):
from .tests.collider import Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx as test_module
@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.")
@pytest.mark.SUITE_main
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@ -116,18 +159,12 @@ class TestAutomation(EditorTestSuite):
class C14654881_CharacterController_SwitchLevels(EditorSharedTest):
from .tests.character_controller import CharacterController_SwitchLevels as test_module
class C17411467_AddPhysxRagdollComponent(EditorSharedTest):
from .tests.ragdoll import Ragdoll_AddPhysxRagdollComponentWorks as test_module
class C12712453_ScriptCanvas_MultipleRaycastNode(EditorSharedTest):
from .tests.script_canvas import ScriptCanvas_MultipleRaycastNode as test_module
class C18243586_Joints_HingeLeadFollowerCollide(EditorSharedTest):
from .tests.joints import Joints_HingeLeadFollowerCollide as test_module
class C4982803_Enable_PxMesh_Option(EditorSharedTest):
from .tests.collider import Collider_PxMeshConvexMeshCollides as test_module
class C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain(EditorSharedTest):
from .tests.shape_collider import ShapeCollider_CylinderShapeCollides as test_module
@ -297,19 +334,6 @@ class TestAutomation(EditorTestSuite):
class C18243591_Joints_BallLeadFollowerCollide(EditorSharedTest):
from .tests.joints import Joints_BallLeadFollowerCollide as test_module
class C19578018_ShapeColliderWithNoShapeComponent(EditorSharedTest):
from .tests.shape_collider import ShapeCollider_InactiveWhenNoShapeComponent as test_module
class C14861500_DefaultSetting_ColliderShape(EditorSharedTest):
from .tests.collider import Collider_CheckDefaultShapeSettingIsPxMesh as test_module
class C19723164_ShapeCollider_WontCrashEditor(EditorSharedTest):
from .tests.shape_collider import ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor as test_module
class C12905528_ForceRegion_WithNonTriggerCollider(EditorSharedTest):
from .tests.force_region import ForceRegion_WithNonTriggerColliderWarning as test_module
# Fixme: expected_lines = ["[Warning] (PhysX Force Region) - Please ensure collider component marked as trigger exists in entity"]
class C5932040_ForceRegion_CubeExertsWorldForce(EditorSharedTest):
from .tests.force_region import ForceRegion_WorldSpaceForceOnRigidBodies as test_module
@ -322,25 +346,9 @@ class TestAutomation(EditorTestSuite):
class C5959809_ForceRegion_RotationalOffset(EditorSharedTest):
from .tests.force_region import ForceRegion_RotationalOffset as test_module
class C15096740_Material_LibraryUpdatedCorrectly(EditorSharedTest):
from .tests.material import Material_LibraryClearingAssignsDefault as test_module
class C4976236_AddPhysxColliderComponent(EditorSharedTest):
from .tests.collider import Collider_AddColliderComponent as test_module
@pytest.mark.xfail(reason="This will fail due to this issue ATOM-15487.")
class C14861502_PhysXCollider_AssetAutoAssigned(EditorSharedTest):
from .tests.collider import Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent as test_module
class C14861501_PhysXCollider_RenderMeshAutoAssigned(EditorSharedTest):
from .tests.collider import Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent as test_module
class C4044695_PhysXCollider_AddMultipleSurfaceFbx(EditorSharedTest):
from .tests.collider import Collider_MultipleSurfaceSlots as test_module
class C14861504_RenderMeshAsset_WithNoPxAsset(EditorSharedTest):
from .tests.collider import Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx as test_module
class C100000_RigidBody_EnablingGravityWorksPoC(EditorSharedTest):
from .tests.rigid_body import RigidBody_EnablingGravityWorksPoC as test_module
@ -350,8 +358,5 @@ class TestAutomation(EditorTestSuite):
class C6090547_ForceRegion_ParentChildForceRegions(EditorSharedTest):
from .tests.force_region import ForceRegion_ParentChildForcesCombineForces as test_module
class C19578021_ShapeCollider_CanBeAdded(EditorSharedTest):
from .tests.shape_collider import ShapeCollider_CanBeAddedWitNoWarnings as test_module
class C15425929_Undo_Redo(EditorSharedTest):
from .tests import Physics_UndoRedoWorksOnEntityWithPhysComponents as test_module

@ -388,17 +388,17 @@ class TestAutomation(TestAutomationBase):
@revert_physics_config
def test_ShapeCollider_InactiveWhenNoShapeComponent(self, request, workspace, editor, launcher_platform):
from .tests.shape_collider import ShapeCollider_InactiveWhenNoShapeComponent as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
def test_Collider_CheckDefaultShapeSettingIsPxMesh(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_CheckDefaultShapeSettingIsPxMesh as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
def test_ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor(self, request, workspace, editor, launcher_platform):
from .tests.shape_collider import ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
def test_Collider_SphereShapeEditing(self, request, workspace, editor, launcher_platform):
@ -418,7 +418,7 @@ class TestAutomation(TestAutomationBase):
def test_ForceRegion_WithNonTriggerColliderWarning(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_WithNonTriggerColliderWarning as test_module
# Fixme: expected_lines = ["[Warning] (PhysX Force Region) - Please ensure collider component marked as trigger exists in entity"]
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_ForceRegion_WorldSpaceForceOnRigidBodies(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_WorldSpaceForceOnRigidBodies as test_module
@ -438,8 +438,12 @@ class TestAutomation(TestAutomationBase):
def test_Material_LibraryClearingAssignsDefault(self, request, workspace, editor, launcher_platform):
from .tests.material import Material_LibraryClearingAssignsDefault as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@pytest.mark.xfail(reason=
"Test failed due to an error message shown while in game mode: "
"'(Prefab) - Invalid asset found referenced in scene while entering game mode. "
"The asset was stored in an instance of Asset.'")
def test_Collider_AddColliderComponent(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_AddColliderComponent as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
@ -448,19 +452,19 @@ class TestAutomation(TestAutomationBase):
reason="This will fail due to this issue ATOM-15487.")
def test_Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_Collider_MultipleSurfaceSlots(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_MultipleSurfaceSlots as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_RigidBody_EnablingGravityWorksPoC(self, request, workspace, editor, launcher_platform):
from .tests.rigid_body import RigidBody_EnablingGravityWorksPoC as test_module
@ -486,7 +490,7 @@ class TestAutomation(TestAutomationBase):
@revert_physics_config
def test_ShapeCollider_CanBeAddedWitNoWarnings(self, request, workspace, editor, launcher_platform):
from .tests.shape_collider import ShapeCollider_CanBeAddedWitNoWarnings as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
def test_Physics_UndoRedoWorksOnEntityWithPhysComponents(self, request, workspace, editor, launcher_platform):

@ -53,10 +53,12 @@ def CharacterController_SwitchLevels():
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
import editor_python_test_tools.hydra_editor_utils as hydra
# Constants
WAIT_FOR_ERRORS = 3.0
@ -77,7 +79,7 @@ def CharacterController_SwitchLevels():
helper.exit_game_mode(Tests.level1_exit_game_mode)
# 2.1) Load level 2 (empty level)
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2.2) Enter game mode
helper.enter_game_mode(Tests.level2_enter_game_mode)

@ -45,14 +45,15 @@ def Collider_CheckDefaultShapeSettingIsPxMesh():
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
import editor_python_test_tools.hydra_editor_utils as hydra
# Open 3D Engine Imports
import azlmbr.legacy.general as general
PHYSICS_ASSET_INDEX = 7 # Hardcoded enum index value for Shape property
helper.init_idle()
# 1) Load empty level
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2) Create an entity to hold the PhysX Shape Collider component
collider_entity = Entity.create_editor_entity("Collider")

@ -54,6 +54,8 @@ def Collider_MultipleSurfaceSlots():
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.asset_utils import Asset
import editor_python_test_tools.hydra_editor_utils as hydra
# Constants
PHYSICS_ASSET_INDEX = 7 # Hardcoded enum index value for Shape property
SURFACE_TAG_COUNT = 4 # Number of surface tags included in used asset
@ -62,9 +64,8 @@ def Collider_MultipleSurfaceSlots():
STATIC_MESH = os.path.join("assets", "Physics", "Collider_MultipleSurfaceSlots", "test.azmodel")
PHYSX_MESH = os.path.join("assets", "Physics","Collider_MultipleSurfaceSlots", "test.pxmesh")
helper.init_idle()
# 1) Load the empty level
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2) Create an entity
test_entity = Entity.create_editor_entity("test_entity")

@ -54,15 +54,16 @@ def Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent():
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.asset_utils import Asset
import editor_python_test_tools.hydra_editor_utils as hydra
# Asset paths
STATIC_MESH = os.path.join("assets", "Physics", "Collider_PxMeshAutoAssigned", "spherebot", "r0-b_body.azmodel")
PHYSX_MESH = os.path.join(
"assets", "Physics", "Collider_PxMeshAutoAssigned", "spherebot", "r0-b_body.pxmesh"
)
helper.init_idle()
# 1) Load the empty level
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2) Create an entity
test_entity = Entity.create_editor_entity("test_entity")

@ -53,6 +53,8 @@ def Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent():
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.asset_utils import Asset
import editor_python_test_tools.hydra_editor_utils as hydra
# Open 3D Engine Imports
import azlmbr.legacy.general as general
@ -60,9 +62,8 @@ def Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent():
MESH_PROPERTY_PATH = "Controller|Configuration|Mesh Asset"
TESTED_PROPERTY_PATH = "Shape Configuration|Asset|PhysX Mesh"
helper.init_idle()
# 1) Load the empty level
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2) Create an entity
test_entity = Entity.create_editor_entity("test_entity")

@ -62,7 +62,9 @@ def Collider_PxMeshConvexMeshCollides():
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.asset_utils import Asset
import azlmbr.math as math
import editor_python_test_tools.hydra_editor_utils as hydra
# Open 3D Engine Imports
import azlmbr
@ -73,9 +75,8 @@ def Collider_PxMeshConvexMeshCollides():
MESH_ASSET_PATH = os.path.join("assets", "Physics", "Collider_PxMeshConvexMeshCollides", "spherebot", "r0-b_body.pxmesh")
TIMEOUT = 2.0
helper.init_idle()
# 1) Load the level
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2) Create test entity
collider = EditorEntity.create_editor_entity_at([512.0, 512.0, 33.0], "Collider")

@ -59,15 +59,16 @@ def Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx():
from editor_python_test_tools.utils import Tracer
from editor_python_test_tools.asset_utils import Asset
import editor_python_test_tools.hydra_editor_utils as hydra
# Open 3D Engine Imports
import azlmbr.asset as azasset
# Asset paths
STATIC_MESH = os.path.join("assets", "Physics", "Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx", "test_asset.azmodel")
helper.init_idle()
# 1) Load the empty level
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2) Create an entity
test_entity = Entity.create_editor_entity("test_entity")

@ -44,15 +44,15 @@ def ForceRegion_WithNonTriggerColliderWarning():
:return: None
"""
import azlmbr.legacy.general as general
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.utils import Tracer
helper.init_idle()
# 1) Load the empty level
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2) Create test entity
test_entity = EditorEntity.create_editor_entity("TestEntity")

@ -57,6 +57,8 @@ def Material_LibraryClearingAssignsDefault():
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.asset_utils import Asset
import editor_python_test_tools.hydra_editor_utils as hydra
# Open 3D Engine Imports
import azlmbr.asset as azasset
@ -66,9 +68,8 @@ def Material_LibraryClearingAssignsDefault():
default_material_path = os.path.join("assets", "physics", "surfacetypemateriallibrary.physmaterial")
new_material_path = os.path.join("physicssurfaces", "default_phys_materials.physmaterial")
helper.init_idle()
# 1) Load the level
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2) Create new Entity with PhysX Character Controller
test_entity = EditorEntity.create_editor_entity("TestEntity")

@ -49,9 +49,10 @@ def Ragdoll_AddPhysxRagdollComponentWorks():
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.utils import Tracer
helper.init_idle()
import editor_python_test_tools.hydra_editor_utils as hydra
# 1) Load the level
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2) Create test entity
test_entity = EditorEntity.create_editor_entity("TestEntity")

@ -50,12 +50,13 @@ def ShapeCollider_CanBeAddedWitNoWarnings():
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.utils import Tracer
import editor_python_test_tools.hydra_editor_utils as hydra
# Open 3D Engine Imports
import azlmbr.legacy.general as general
helper.init_idle()
# 1) Load the empty level
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2) Create an entity
collider_entity = Entity.create_editor_entity("Collider")

@ -54,6 +54,8 @@ def ShapeCollider_InactiveWhenNoShapeComponent():
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.utils import TestHelper as helper
import editor_python_test_tools.hydra_editor_utils as hydra
# Open 3D Engine Imports
import azlmbr.bus as bus
import azlmbr.editor as editor
@ -65,9 +67,8 @@ def ShapeCollider_InactiveWhenNoShapeComponent():
"""
return editor.EditorComponentAPIBus(bus.Broadcast, "IsComponentEnabled", component_id)
helper.init_idle()
# 1) Load the level
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2) Add an entity with a PhysX Shape Collider component.
collider = EditorEntity.create_editor_entity("Collider")

@ -45,6 +45,8 @@ def ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor():
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity
import editor_python_test_tools.hydra_editor_utils as hydra
# Open 3D Engine Imports
import azlmbr.legacy.general as general
@ -61,9 +63,8 @@ def ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor():
# Wait 60 frames more
general.idle_wait_frames(60)
helper.init_idle()
# 1) Load the empty level
helper.open_level("Physics", "Base")
hydra.open_base_level()
# 2) Create 512 entities with PhysX Shape Collider and Sphere Shape components
entity_failure = False

@ -24,12 +24,12 @@ from base import TestAutomationBase
class TestAutomation(TestAutomationBase):
def test_WhiteBox_AddComponentToEntity(self, request, workspace, editor, launcher_platform):
from .tests import WhiteBox_AddComponentToEntity as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_WhiteBox_SetDefaultShape(self, request, workspace, editor, launcher_platform):
from .tests import WhiteBox_SetDefaultShape as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_WhiteBox_SetInvisible(self, request, workspace, editor, launcher_platform):
from .tests import WhiteBox_SetInvisible as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)

@ -32,7 +32,7 @@ def C28798177_WhiteBox_AddComponentToEntity():
# open level
helper.init_idle()
general.open_level("EmptyLevel")
helper.open_level("WhiteBox", "EmptyLevel", no_prompt=False)
# create white box entity and attach component
white_box_entity = init.create_white_box_entity()

@ -54,7 +54,7 @@ def C29279329_WhiteBox_SetDefaultShape():
# open level
helper.init_idle()
general.open_level("EmptyLevel")
helper.open_level("WhiteBox", "EmptyLevel", no_prompt=False)
# create white box entity and attach component
white_box_entity = init.create_white_box_entity()

@ -39,7 +39,7 @@ def C28798205_WhiteBox_SetInvisible():
# open level
helper.init_idle()
general.open_level("EmptyLevel")
helper.open_level("WhiteBox", "EmptyLevel", no_prompt=False)
white_box_entity_name = 'WhiteBox-Visibility'
white_box_visibility_path = 'White Box Material|Visible'

@ -79,7 +79,7 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
workspace.asset_processor_platform)
)
# Useful sizes
self.max_bundle_size_in_mib = 5
self.max_bundle_size_in_mib = 35
self.number_of_bytes_in_mib = 1024 * 1024
self.workspace = workspace
self.platforms = platforms
@ -271,11 +271,13 @@ def bundler_batch_setup_fixture(request, workspace, asset_processor, timeout) ->
for rel_path in self.get_asset_relative_paths(self.asset_info_file_result):
assets_from_file.append(os.path.normpath(rel_path))
expected_size = self.max_bundle_size_in_mib * self.number_of_bytes_in_mib
# extract all files from the bundles
for bundle in dependent_bundle_name:
file_info = os.stat(bundle)
# Verify that the size of all bundles is less than the max size specified
assert file_info.st_size <= (self.max_bundle_size_in_mib * self.number_of_bytes_in_mib)
assert file_info.st_size <= expected_size, \
f"file_info.st_size {file_info.st_size} for bundle {bundle} was expected to be smaller than {expected_size}"
with zipfile.ZipFile(bundle) as bundle_zip:
bundle_zip.extractall(extract_dir)

@ -27,15 +27,15 @@ TEST_DIRECTORY = os.path.dirname(__file__)
class TestAutomation(TestAutomationBase):
def test_Pane_HappyPath_OpenCloseSuccessfully(self, request, workspace, editor, launcher_platform):
from . import Pane_HappyPath_OpenCloseSuccessfully as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_Pane_HappyPath_DocksProperly(self, request, workspace, editor, launcher_platform):
from . import Pane_HappyPath_DocksProperly as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_Pane_HappyPath_ResizesProperly(self, request, workspace, editor, launcher_platform):
from . import Pane_HappyPath_ResizesProperly as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@ -45,7 +45,7 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptCanvas_TwoComponents_InteractSuccessfully as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@ -55,15 +55,15 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptCanvas_ChangingAssets_ComponentStable as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_Graph_HappyPath_ZoomInZoomOut(self, request, workspace, editor, launcher_platform):
from . import Graph_HappyPath_ZoomInZoomOut as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_NodePalette_HappyPath_CanSelectNode(self, request, workspace, editor, launcher_platform):
from . import NodePalette_HappyPath_CanSelectNode as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@ -73,11 +73,11 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_NodePalette_HappyPath_ClearSelection(self, request, workspace, editor, launcher_platform, project):
from . import NodePalette_HappyPath_ClearSelection as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@ -87,7 +87,7 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptCanvas_TwoEntities_UseSimultaneously as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_ScriptEvent_HappyPath_CreatedWithoutError(self, request, workspace, editor, launcher_platform, project):
def teardown():
@ -99,19 +99,19 @@ class TestAutomation(TestAutomationBase):
[os.path.join(workspace.paths.project(), "ScriptCanvas", "test_file.scriptevent")], True, True
)
from . import ScriptEvent_HappyPath_CreatedWithoutError as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_ScriptCanvasTools_Toggle_OpenCloseSuccess(self, request, workspace, editor, launcher_platform):
from . import ScriptCanvasTools_Toggle_OpenCloseSuccess as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_NodeInspector_HappyPath_VariableRenames(self, request, workspace, editor, launcher_platform, project):
from . import NodeInspector_HappyPath_VariableRenames as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_Debugger_HappyPath_TargetMultipleGraphs(self, request, workspace, editor, launcher_platform, project):
from . import Debugger_HappyPath_TargetMultipleGraphs as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@pytest.mark.parametrize("level", ["tmp_level"])
def test_Debugger_HappyPath_TargetMultipleEntities(self, request, workspace, editor, launcher_platform, project, level):
@ -120,16 +120,16 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import Debugger_HappyPath_TargetMultipleEntities as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
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, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_Pane_Undocked_ClosesSuccessfully(self, request, workspace, editor, launcher_platform):
from . import Pane_Undocked_ClosesSuccessfully as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@pytest.mark.parametrize("level", ["tmp_level"])
def test_Entity_HappyPath_AddScriptCanvasComponent(self, request, workspace, editor, launcher_platform, project, level):
@ -138,11 +138,11 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import Entity_HappyPath_AddScriptCanvasComponent as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_Pane_Default_RetainOnSCRestart(self, request, workspace, editor, launcher_platform):
from . import Pane_Default_RetainOnSCRestart as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@ -152,7 +152,7 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptEvents_HappyPath_SendReceiveAcrossMultiple as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@ -162,7 +162,7 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptEvents_Default_SendReceiveSuccessfully as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@pytest.mark.parametrize("level", ["tmp_level"])
@ -172,24 +172,24 @@ class TestAutomation(TestAutomationBase):
request.addfinalizer(teardown)
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
from . import ScriptEvents_ReturnSetType_Successfully as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_NodeCategory_ExpandOnClick(self, request, workspace, editor, launcher_platform):
from . import NodeCategory_ExpandOnClick as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_NodePalette_SearchText_Deletion(self, request, workspace, editor, launcher_platform):
from . import NodePalette_SearchText_Deletion as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
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, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_Node_HappyPath_DuplicateNode(self, request, workspace, editor, launcher_platform):
from . import Node_HappyPath_DuplicateNode as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
def test_ScriptEvent_AddRemoveParameter_ActionsSuccessful(self, request, workspace, editor, launcher_platform):
def teardown():
@ -201,7 +201,7 @@ class TestAutomation(TestAutomationBase):
[os.path.join(workspace.paths.project(), "ScriptCanvas", "test_file.scriptevent")], True, True
)
from . import ScriptEvent_AddRemoveParameter_ActionsSuccessful as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)
# NOTE: We had to use hydra_test_utils.py, as TestAutomationBase run_test method
# fails because of pyside_utils import
@ -227,7 +227,6 @@ class TestScriptCanvasTests(object):
expected_lines,
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@ -246,7 +245,6 @@ class TestScriptCanvasTests(object):
expected_lines,
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
def test_GraphClose_Default_SavePrompt(self, request, editor, launcher_platform):
@ -263,7 +261,6 @@ class TestScriptCanvasTests(object):
expected_lines,
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
def test_VariableManager_Default_CreateDeleteVars(self, request, editor, launcher_platform):
@ -278,7 +275,6 @@ class TestScriptCanvasTests(object):
expected_lines,
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
@pytest.mark.parametrize(
@ -314,7 +310,6 @@ class TestScriptCanvasTests(object):
cfg_args=[config.get('cfg_args')],
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@ -343,7 +338,6 @@ class TestScriptCanvasTests(object):
expected_lines,
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)
@pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.")
@ -371,6 +365,5 @@ class TestScriptCanvasTests(object):
expected_lines,
auto_test_mode=False,
timeout=60,
enable_prefab_system=False,
)

@ -23,4 +23,4 @@ class TestAutomation(TestAutomationBase):
def test_Opening_Closing_Pane(self, request, workspace, editor, launcher_platform):
from . import Opening_Closing_Pane as test_module
self._run_test(request, workspace, editor, test_module, enable_prefab_system=False)
self._run_test(request, workspace, editor, test_module)

@ -45,4 +45,14 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
AutomatedTesting.Assets
)
ly_add_pytest(
NAME AutomatedTesting::SmokeTest_Sandbox
TEST_SUITE sandbox
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}
PYTEST_MARKS "SUITE_sandbox"
RUNTIME_DEPENDENCIES
AZ::AssetProcessor
)
endif()

@ -14,7 +14,7 @@ import pytest
import subprocess
@pytest.mark.SUITE_smoke
@pytest.mark.SUITE_sandbox
class TestCLIToolAssetBuilderWorks(object):
def test_CLITool_AssetBuilder_Works(self, build_directory):
file_path = os.path.join(build_directory, "AssetBuilder")

@ -0,0 +1,255 @@
{
"ContainerEntity": {
"Id": "ContainerEntity",
"Name": "Blast_ActorSplitsAfterCollision",
"Components": {
"Component_[10182366347512475253]": {
"$type": "EditorPrefabComponent",
"Id": 10182366347512475253
},
"Component_[12917798267488243668]": {
"$type": "EditorPendingCompositionComponent",
"Id": 12917798267488243668
},
"Component_[3261249813163778338]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3261249813163778338
},
"Component_[3837204912784440039]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 3837204912784440039
},
"Component_[4272963378099646759]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 4272963378099646759,
"Parent Entity": ""
},
"Component_[4848458548047175816]": {
"$type": "EditorVisibilityComponent",
"Id": 4848458548047175816
},
"Component_[5787060997243919943]": {
"$type": "EditorInspectorComponent",
"Id": 5787060997243919943
},
"Component_[7804170251266531779]": {
"$type": "EditorLockComponent",
"Id": 7804170251266531779
},
"Component_[7874177159288365422]": {
"$type": "EditorEntitySortComponent",
"Id": 7874177159288365422
},
"Component_[8018146290632383969]": {
"$type": "EditorEntityIconComponent",
"Id": 8018146290632383969
},
"Component_[8452360690590857075]": {
"$type": "SelectionComponent",
"Id": 8452360690590857075
}
}
},
"Entities": {
"Entity_[678057008134]": {
"Id": "Entity_[678057008134]",
"Name": "Sphere_Moving",
"Components": {
"Component_[158491845118288574]": {
"$type": "EditorColliderComponent",
"Id": 158491845118288574,
"ColliderConfiguration": {
"CollisionGroupId": {
"GroupId": "{45EBDE87-10BA-405B-9118-1FE9C750E5A3}"
},
"MaterialSelection": {
"MaterialIds": [
{}
]
}
},
"ShapeConfiguration": {
"ShapeType": 0
}
},
"Component_[15882836540317052831]": {
"$type": "EditorOnlyEntityComponent",
"Id": 15882836540317052831
},
"Component_[15988538924200810686]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 15988538924200810686
},
"Component_[17332118306686659923]": {
"$type": "SelectionComponent",
"Id": 17332118306686659923
},
"Component_[18013098363541384892]": {
"$type": "EditorPendingCompositionComponent",
"Id": 18013098363541384892
},
"Component_[3299242856338866058]": {
"$type": "EditorVisibilityComponent",
"Id": 3299242856338866058
},
"Component_[3368757662560547573]": {
"$type": "EditorInspectorComponent",
"Id": 3368757662560547573,
"ComponentOrderEntryArray": [
{
"ComponentId": 9646670826592538370
},
{
"ComponentId": 158491845118288574,
"SortIndex": 1
},
{
"ComponentId": 7177752238184232813,
"SortIndex": 2
},
{
"ComponentId": 3538399061071907667,
"SortIndex": 3
}
]
},
"Component_[3538399061071907667]": {
"$type": "EditorSphereShapeComponent",
"Id": 3538399061071907667,
"GameView": true
},
"Component_[3584595476595239676]": {
"$type": "EditorLockComponent",
"Id": 3584595476595239676
},
"Component_[4539775501292735153]": {
"$type": "EditorEntityIconComponent",
"Id": 4539775501292735153
},
"Component_[5885911623396957736]": {
"$type": "EditorEntitySortComponent",
"Id": 5885911623396957736
},
"Component_[7177752238184232813]": {
"$type": "EditorRigidBodyComponent",
"Id": 7177752238184232813,
"Configuration": {
"entityId": "",
"Compute Mass": false,
"Mass": 100.0,
"Inertia tensor": {
"roll": 0.0,
"pitch": 0.0,
"yaw": 0.0,
"scale": 0.10000000149011612
}
}
},
"Component_[9646670826592538370]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 9646670826592538370,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
511.9999694824219,
532.0,
43.0
]
}
}
}
},
"Entity_[682351975430]": {
"Id": "Entity_[682351975430]",
"Name": "Destructable_Box",
"Components": {
"Component_[14428979635353087750]": {
"$type": "EditorEntitySortComponent",
"Id": 14428979635353087750
},
"Component_[14459069801260260996]": {
"$type": "EditorPendingCompositionComponent",
"Id": 14459069801260260996
},
"Component_[16353277599917996564]": {
"$type": "SelectionComponent",
"Id": 16353277599917996564
},
"Component_[16528484535459302978]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 16528484535459302978
},
"Component_[17689177494335411023]": {
"$type": "EditorVisibilityComponent",
"Id": 17689177494335411023
},
"Component_[18116908665747450198]": {
"$type": "EditorOnlyEntityComponent",
"Id": 18116908665747450198
},
"Component_[3544855145233062627]": {
"$type": "EditorInspectorComponent",
"Id": 3544855145233062627,
"ComponentOrderEntryArray": [
{
"ComponentId": 3826825320808092990
},
{
"ComponentId": 5627868831214978789,
"SortIndex": 1
},
{
"ComponentId": 7875098433529363009,
"SortIndex": 2
}
]
},
"Component_[3569626399556956817]": {
"$type": "EditorLockComponent",
"Id": 3569626399556956817
},
"Component_[3826825320808092990]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 3826825320808092990,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
511.9991455078125,
532.031982421875,
39.52538299560547
],
"Scale": [
1.0000001192092896,
0.9999998807907104,
1.0
]
}
},
"Component_[5627868831214978789]": {
"$type": "EditorBlastFamilyComponent",
"Id": 5627868831214978789,
"BlastAsset": {
"assetId": {
"guid": "{BAB71D97-F136-5C11-8AB6-6E9F768CA83B}"
},
"assetHint": "assets/destruction/box_2_chunks.blast"
},
"BlastMaterial": {
"BlastMaterialId": "{2F200947-553F-487F-B4EA-57F0EF5AE024}"
},
"PhysicsMaterial": {
"MaterialId": "{34AD1046-240B-448C-A694-AE80F595C431}"
}
},
"Component_[7159608037522336146]": {
"$type": "EditorEntityIconComponent",
"Id": 7159608037522336146
},
"Component_[7875098433529363009]": {
"$type": "EditorBlastMeshDataComponent",
"Id": 7875098433529363009
}
}
}
}
}

@ -0,0 +1,148 @@
{
"ContainerEntity": {
"Id": "ContainerEntity",
"Name": "Blast_ActorSplitsAfterDamage",
"Components": {
"Component_[10182366347512475253]": {
"$type": "EditorPrefabComponent",
"Id": 10182366347512475253
},
"Component_[12917798267488243668]": {
"$type": "EditorPendingCompositionComponent",
"Id": 12917798267488243668
},
"Component_[3261249813163778338]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3261249813163778338
},
"Component_[3837204912784440039]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 3837204912784440039
},
"Component_[4272963378099646759]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 4272963378099646759,
"Parent Entity": ""
},
"Component_[4848458548047175816]": {
"$type": "EditorVisibilityComponent",
"Id": 4848458548047175816
},
"Component_[5787060997243919943]": {
"$type": "EditorInspectorComponent",
"Id": 5787060997243919943
},
"Component_[7804170251266531779]": {
"$type": "EditorLockComponent",
"Id": 7804170251266531779
},
"Component_[7874177159288365422]": {
"$type": "EditorEntitySortComponent",
"Id": 7874177159288365422
},
"Component_[8018146290632383969]": {
"$type": "EditorEntityIconComponent",
"Id": 8018146290632383969
},
"Component_[8452360690590857075]": {
"$type": "SelectionComponent",
"Id": 8452360690590857075
}
}
},
"Entities": {
"Entity_[682351975430]": {
"Id": "Entity_[682351975430]",
"Name": "Destructable_Box",
"Components": {
"Component_[14428979635353087750]": {
"$type": "EditorEntitySortComponent",
"Id": 14428979635353087750
},
"Component_[14459069801260260996]": {
"$type": "EditorPendingCompositionComponent",
"Id": 14459069801260260996
},
"Component_[16353277599917996564]": {
"$type": "SelectionComponent",
"Id": 16353277599917996564
},
"Component_[16528484535459302978]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 16528484535459302978
},
"Component_[17689177494335411023]": {
"$type": "EditorVisibilityComponent",
"Id": 17689177494335411023
},
"Component_[18116908665747450198]": {
"$type": "EditorOnlyEntityComponent",
"Id": 18116908665747450198
},
"Component_[3544855145233062627]": {
"$type": "EditorInspectorComponent",
"Id": 3544855145233062627,
"ComponentOrderEntryArray": [
{
"ComponentId": 3826825320808092990
},
{
"ComponentId": 5627868831214978789,
"SortIndex": 1
},
{
"ComponentId": 7875098433529363009,
"SortIndex": 2
}
]
},
"Component_[3569626399556956817]": {
"$type": "EditorLockComponent",
"Id": 3569626399556956817
},
"Component_[3826825320808092990]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 3826825320808092990,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
511.9991455078125,
532.031982421875,
39.52538299560547
],
"Scale": [
1.0000001192092896,
0.9999998807907104,
1.0
]
}
},
"Component_[5627868831214978789]": {
"$type": "EditorBlastFamilyComponent",
"Id": 5627868831214978789,
"BlastAsset": {
"assetId": {
"guid": "{BAB71D97-F136-5C11-8AB6-6E9F768CA83B}"
},
"assetHint": "assets/destruction/box_2_chunks.blast"
},
"BlastMaterial": {
"BlastMaterialId": "{2F200947-553F-487F-B4EA-57F0EF5AE024}"
},
"PhysicsMaterial": {
"MaterialId": "{34AD1046-240B-448C-A694-AE80F595C431}"
}
},
"Component_[7159608037522336146]": {
"$type": "EditorEntityIconComponent",
"Id": 7159608037522336146
},
"Component_[7875098433529363009]": {
"$type": "EditorBlastMeshDataComponent",
"Id": 7875098433529363009,
"Show Mesh Assets": true
}
}
}
}
}

@ -0,0 +1,217 @@
{
"ContainerEntity": {
"Id": "ContainerEntity",
"Name": "CharacterController_SwitchLevels",
"Components": {
"Component_[10182366347512475253]": {
"$type": "EditorPrefabComponent",
"Id": 10182366347512475253
},
"Component_[12917798267488243668]": {
"$type": "EditorPendingCompositionComponent",
"Id": 12917798267488243668
},
"Component_[3261249813163778338]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3261249813163778338
},
"Component_[3837204912784440039]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 3837204912784440039
},
"Component_[4272963378099646759]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 4272963378099646759,
"Parent Entity": ""
},
"Component_[4848458548047175816]": {
"$type": "EditorVisibilityComponent",
"Id": 4848458548047175816
},
"Component_[5787060997243919943]": {
"$type": "EditorInspectorComponent",
"Id": 5787060997243919943
},
"Component_[7804170251266531779]": {
"$type": "EditorLockComponent",
"Id": 7804170251266531779
},
"Component_[7874177159288365422]": {
"$type": "EditorEntitySortComponent",
"Id": 7874177159288365422
},
"Component_[8018146290632383969]": {
"$type": "EditorEntityIconComponent",
"Id": 8018146290632383969
},
"Component_[8452360690590857075]": {
"$type": "SelectionComponent",
"Id": 8452360690590857075
}
}
},
"Entities": {
"Entity_[271494215500]": {
"Id": "Entity_[271494215500]",
"Name": "DefaultLevelSetup",
"Components": {
"Component_[10017568850356726118]": {
"$type": "EditorEntitySortComponent",
"Id": 10017568850356726118
},
"Component_[13730791873699866292]": {
"$type": "EditorVisibilityComponent",
"Id": 13730791873699866292
},
"Component_[14036484285432839222]": {
"$type": "EditorInspectorComponent",
"Id": 14036484285432839222,
"ComponentOrderEntryArray": [
{
"ComponentId": 9432950532896492451
},
{
"ComponentId": 16094906495473882735,
"SortIndex": 1
}
]
},
"Component_[15490606709331567745]": {
"$type": "EditorOnlyEntityComponent",
"Id": 15490606709331567745
},
"Component_[17819059404707659501]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 17819059404707659501
},
"Component_[2317367007807622931]": {
"$type": "EditorLockComponent",
"Id": 2317367007807622931
},
"Component_[2676812743453687109]": {
"$type": "EditorPendingCompositionComponent",
"Id": 2676812743453687109
},
"Component_[3047355939801335922]": {
"$type": "EditorEntityIconComponent",
"Id": 3047355939801335922
},
"Component_[3687396159953003426]": {
"$type": "SelectionComponent",
"Id": 3687396159953003426
},
"Component_[9432950532896492451]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 9432950532896492451,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
512.0,
512.0,
100.0
]
}
}
}
},
"Entity_[348803626828]": {
"Id": "Entity_[348803626828]",
"Name": "CharacterController",
"Components": {
"Component_[10957270521451904134]": {
"$type": "EditorOnlyEntityComponent",
"Id": 10957270521451904134
},
"Component_[12992548330649678626]": {
"$type": "EditorLockComponent",
"Id": 12992548330649678626
},
"Component_[15540557783782258382]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 15540557783782258382
},
"Component_[16081734969125733179]": {
"$type": "EditorEntitySortComponent",
"Id": 16081734969125733179
},
"Component_[1999380243426028380]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 1999380243426028380,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
511.9999694824219,
512.0,
34.0
]
}
},
"Component_[2476703453858708137]": {
"$type": "EditorEntityIconComponent",
"Id": 2476703453858708137
},
"Component_[259360796349614835]": {
"$type": "EditorVisibilityComponent",
"Id": 259360796349614835
},
"Component_[5309782390278392323]": {
"$type": "EditorCapsuleShapeComponent",
"Id": 5309782390278392323,
"GameView": true,
"ShapeColor": [
0.6666666865348816,
0.0,
0.0
],
"CapsuleShape": {
"Configuration": {
"DrawColor": [
0.6666666865348816,
0.0,
0.0
],
"Height": 2.0
}
}
},
"Component_[5810440768491728833]": {
"$type": "EditorInspectorComponent",
"Id": 5810440768491728833,
"ComponentOrderEntryArray": [
{
"ComponentId": 1999380243426028380
},
{
"ComponentId": 6864662272767840579,
"SortIndex": 1
},
{
"ComponentId": 5309782390278392323,
"SortIndex": 2
}
]
},
"Component_[6654367643820201613]": {
"$type": "EditorPendingCompositionComponent",
"Id": 6654367643820201613
},
"Component_[6864662272767840579]": {
"$type": "EditorCharacterControllerComponent",
"Id": 6864662272767840579,
"Configuration": {
"entityId": "",
"Material": {
"MaterialIds": [
{}
]
}
}
},
"Component_[9211907343705413938]": {
"$type": "SelectionComponent",
"Id": 9211907343705413938
}
}
}
}
}

@ -0,0 +1,118 @@
{
"ContainerEntity": {
"Id": "ContainerEntity",
"Name": "EmptyLevel",
"Components": {
"Component_[10182366347512475253]": {
"$type": "EditorPrefabComponent",
"Id": 10182366347512475253
},
"Component_[12917798267488243668]": {
"$type": "EditorPendingCompositionComponent",
"Id": 12917798267488243668
},
"Component_[3261249813163778338]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3261249813163778338
},
"Component_[3837204912784440039]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 3837204912784440039
},
"Component_[4272963378099646759]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 4272963378099646759,
"Parent Entity": ""
},
"Component_[4848458548047175816]": {
"$type": "EditorVisibilityComponent",
"Id": 4848458548047175816
},
"Component_[5787060997243919943]": {
"$type": "EditorInspectorComponent",
"Id": 5787060997243919943
},
"Component_[7804170251266531779]": {
"$type": "EditorLockComponent",
"Id": 7804170251266531779
},
"Component_[7874177159288365422]": {
"$type": "EditorEntitySortComponent",
"Id": 7874177159288365422
},
"Component_[8018146290632383969]": {
"$type": "EditorEntityIconComponent",
"Id": 8018146290632383969
},
"Component_[8452360690590857075]": {
"$type": "SelectionComponent",
"Id": 8452360690590857075
}
}
},
"Entities": {
"Entity_[273050554979]": {
"Id": "Entity_[273050554979]",
"Name": "DefaultLevelSetup",
"Components": {
"Component_[10017568850356726118]": {
"$type": "EditorEntitySortComponent",
"Id": 10017568850356726118
},
"Component_[13730791873699866292]": {
"$type": "EditorVisibilityComponent",
"Id": 13730791873699866292
},
"Component_[14036484285432839222]": {
"$type": "EditorInspectorComponent",
"Id": 14036484285432839222,
"ComponentOrderEntryArray": [
{
"ComponentId": 9432950532896492451
},
{
"ComponentId": 16094906495473882735,
"SortIndex": 1
}
]
},
"Component_[16744953497953161231]": {
"$type": "EditorOnlyEntityComponent",
"Id": 16744953497953161231
},
"Component_[17819059404707659501]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 17819059404707659501
},
"Component_[2317367007807622931]": {
"$type": "EditorLockComponent",
"Id": 2317367007807622931
},
"Component_[2676812743453687109]": {
"$type": "EditorPendingCompositionComponent",
"Id": 2676812743453687109
},
"Component_[3047355939801335922]": {
"$type": "EditorEntityIconComponent",
"Id": 3047355939801335922
},
"Component_[3687396159953003426]": {
"$type": "SelectionComponent",
"Id": 3687396159953003426
},
"Component_[9432950532896492451]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 9432950532896492451,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
512.0,
512.0,
100.0
]
}
}
}
}
}
}

@ -0,0 +1,214 @@
{
"ContainerEntity": {
"Id": "ContainerEntity",
"Name": "auto_test",
"Components": {
"Component_[10182366347512475253]": {
"$type": "EditorPrefabComponent",
"Id": 10182366347512475253
},
"Component_[12917798267488243668]": {
"$type": "EditorPendingCompositionComponent",
"Id": 12917798267488243668
},
"Component_[3261249813163778338]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3261249813163778338
},
"Component_[3837204912784440039]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 3837204912784440039
},
"Component_[4272963378099646759]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 4272963378099646759,
"Parent Entity": ""
},
"Component_[4848458548047175816]": {
"$type": "EditorVisibilityComponent",
"Id": 4848458548047175816
},
"Component_[5787060997243919943]": {
"$type": "EditorInspectorComponent",
"Id": 5787060997243919943
},
"Component_[7804170251266531779]": {
"$type": "EditorLockComponent",
"Id": 7804170251266531779
},
"Component_[7874177159288365422]": {
"$type": "EditorEntitySortComponent",
"Id": 7874177159288365422
},
"Component_[8018146290632383969]": {
"$type": "EditorEntityIconComponent",
"Id": 8018146290632383969
},
"Component_[8452360690590857075]": {
"$type": "SelectionComponent",
"Id": 8452360690590857075
}
}
},
"Entities": {
"Entity_[212522713927]": {
"Id": "Entity_[212522713927]",
"Name": "Entity1",
"Components": {
"Component_[13533719491703491179]": {
"$type": "EditorLockComponent",
"Id": 13533719491703491179
},
"Component_[14279778360325346613]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 14279778360325346613,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
512.0,
512.0,
32.0
]
}
},
"Component_[16516432490694776069]": {
"$type": "EditorPendingCompositionComponent",
"Id": 16516432490694776069
},
"Component_[16894842505954369943]": {
"$type": "ScriptEditorComponent",
"Id": 16894842505954369943,
"ScriptComponent": {
"Script": {
"assetId": {
"guid": "{AEB649BE-6E63-5D08-B6A6-323EE80125D9}",
"subId": 1
},
"assetHint": "scripts/auto_director.luac"
}
},
"ScriptAsset": {
"assetId": {
"guid": "{AEB649BE-6E63-5D08-B6A6-323EE80125D9}",
"subId": 1
},
"assetHint": "scripts/auto_director.luac"
}
},
"Component_[17917865139404413371]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 17917865139404413371
},
"Component_[300870010798916271]": {
"$type": "EditorOnlyEntityComponent",
"Id": 300870010798916271
},
"Component_[3542492159899223622]": {
"$type": "EditorEntitySortComponent",
"Id": 3542492159899223622
},
"Component_[5861133001616453159]": {
"$type": "SelectionComponent",
"Id": 5861133001616453159
},
"Component_[5861394204754691870]": {
"$type": "EditorVisibilityComponent",
"Id": 5861394204754691870
},
"Component_[6534723243071167847]": {
"$type": "EditorEntityIconComponent",
"Id": 6534723243071167847
},
"Component_[8192412641288145942]": {
"$type": "EditorInspectorComponent",
"Id": 8192412641288145942,
"ComponentOrderEntryArray": [
{
"ComponentId": 14279778360325346613
},
{
"ComponentId": 16894842505954369943,
"SortIndex": 1
}
]
}
}
},
"Entity_[264062321479]": {
"Id": "Entity_[264062321479]",
"Name": "Camera1",
"Components": {
"Component_[0]": {
"$type": "{CA11DA46-29FF-4083-B5F6-E02C3A8C3A3D} EditorCameraComponent"
},
"Component_[10250997976046839424]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 10250997976046839424,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
512.0531005859375,
505.3736877441406,
36.008216857910156
],
"Rotate": [
343.8316345214844,
359.8723449707031,
0.44026151299476624
],
"Scale": [
1.0,
1.0,
0.9999998807907104
]
}
},
"Component_[14117951654550186353]": {
"$type": "EditorOnlyEntityComponent",
"Id": 14117951654550186353
},
"Component_[15441561693121796704]": {
"$type": "EditorEntitySortComponent",
"Id": 15441561693121796704
},
"Component_[16579888413894171159]": {
"$type": "EditorEntityIconComponent",
"Id": 16579888413894171159
},
"Component_[2015490294161116421]": {
"$type": "EditorVisibilityComponent",
"Id": 2015490294161116421
},
"Component_[2585309221365912267]": {
"$type": "EditorInspectorComponent",
"Id": 2585309221365912267,
"ComponentOrderEntryArray": [
{
"ComponentId": 10250997976046839424
},
{
"ComponentId": 17989353981643488311,
"SortIndex": 1
}
]
},
"Component_[4907915728143987395]": {
"$type": "SelectionComponent",
"Id": 4907915728143987395
},
"Component_[5911437040663285596]": {
"$type": "EditorPendingCompositionComponent",
"Id": 5911437040663285596
},
"Component_[8717969720874629567]": {
"$type": "EditorLockComponent",
"Id": 8717969720874629567
},
"Component_[992024776394048323]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 992024776394048323
}
}
}
}
}

@ -0,0 +1,348 @@
{
"ContainerEntity": {
"Id": "ContainerEntity",
"Name": "ocean_component",
"Components": {
"Component_[10182366347512475253]": {
"$type": "EditorPrefabComponent",
"Id": 10182366347512475253
},
"Component_[12917798267488243668]": {
"$type": "EditorPendingCompositionComponent",
"Id": 12917798267488243668
},
"Component_[3261249813163778338]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3261249813163778338
},
"Component_[3837204912784440039]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 3837204912784440039
},
"Component_[4272963378099646759]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 4272963378099646759,
"Parent Entity": ""
},
"Component_[4848458548047175816]": {
"$type": "EditorVisibilityComponent",
"Id": 4848458548047175816
},
"Component_[5787060997243919943]": {
"$type": "EditorInspectorComponent",
"Id": 5787060997243919943
},
"Component_[7804170251266531779]": {
"$type": "EditorLockComponent",
"Id": 7804170251266531779
},
"Component_[7874177159288365422]": {
"$type": "EditorEntitySortComponent",
"Id": 7874177159288365422
},
"Component_[8018146290632383969]": {
"$type": "EditorEntityIconComponent",
"Id": 8018146290632383969
},
"Component_[8452360690590857075]": {
"$type": "SelectionComponent",
"Id": 8452360690590857075
}
}
},
"Entities": {
"Entity_[113557230075]": {
"Id": "Entity_[113557230075]",
"Name": "the_ocean",
"Components": {
"Component_[10578707299131614649]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 10578707299131614649,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
55.0,
81.0,
20.0
]
}
},
"Component_[11046344975288527044]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 11046344975288527044
},
"Component_[13465592091248295601]": {
"$type": "EditorInspectorComponent",
"Id": 13465592091248295601,
"ComponentOrderEntryArray": [
{
"ComponentId": 10578707299131614649
},
{
"ComponentId": 2840515548992536974,
"SortIndex": 1
}
]
},
"Component_[13984822296855598165]": {
"$type": "EditorLockComponent",
"Id": 13984822296855598165
},
"Component_[14230937071328458692]": {
"$type": "EditorEntitySortComponent",
"Id": 14230937071328458692
},
"Component_[1515275142160994114]": {
"$type": "EditorPendingCompositionComponent",
"Id": 1515275142160994114
},
"Component_[16187876448121091850]": {
"$type": "EditorEntityIconComponent",
"Id": 16187876448121091850
},
"Component_[16861233641669829560]": {
"$type": "EditorOnlyEntityComponent",
"Id": 16861233641669829560
},
"Component_[9086259058015300489]": {
"$type": "SelectionComponent",
"Id": 9086259058015300489
},
"Component_[9741974704446379447]": {
"$type": "EditorVisibilityComponent",
"Id": 9741974704446379447
}
}
},
"Entity_[127885714554]": {
"Id": "Entity_[127885714554]",
"Name": "the_camera",
"Components": {
"Component_[0]": {
"$type": "{CA11DA46-29FF-4083-B5F6-E02C3A8C3A3D} EditorCameraComponent"
},
"Component_[12093754677865520350]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 12093754677865520350
},
"Component_[12730323471937880555]": {
"$type": "EditorEntityIconComponent",
"Id": 12730323471937880555
},
"Component_[13204709256342535717]": {
"$type": "EditorPendingCompositionComponent",
"Id": 13204709256342535717
},
"Component_[14559512685789945421]": {
"$type": "EditorLockComponent",
"Id": 14559512685789945421
},
"Component_[15770539414692920876]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 15770539414692920876,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
23.118545532226563,
128.9333038330078,
41.236572265625
],
"Rotate": [
0.12950840592384338,
35.17909240722656,
269.7752685546875
],
"Scale": [
1.0,
0.9999998807907104,
1.0
]
}
},
"Component_[17658049626755079421]": {
"$type": "EditorVisibilityComponent",
"Id": 17658049626755079421
},
"Component_[3194947345798045730]": {
"$type": "EditorInspectorComponent",
"Id": 3194947345798045730,
"ComponentOrderEntryArray": [
{
"ComponentId": 15770539414692920876
},
{
"ComponentId": 7411461277430009852,
"SortIndex": 1
}
]
},
"Component_[4514043637061174274]": {
"$type": "SelectionComponent",
"Id": 4514043637061174274
},
"Component_[6690157295583364107]": {
"$type": "EditorEntitySortComponent",
"Id": 6690157295583364107
},
"Component_[8418547677002847981]": {
"$type": "EditorOnlyEntityComponent",
"Id": 8418547677002847981
}
}
},
"Entity_[132180681850]": {
"Id": "Entity_[132180681850]",
"Name": "the_thing",
"Components": {
"Component_[10221686237776167339]": {
"$type": "EditorOnlyEntityComponent",
"Id": 10221686237776167339
},
"Component_[10230254870444799387]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 10230254870444799387
},
"Component_[10910683815551719249]": {
"$type": "EditorEntityIconComponent",
"Id": 10910683815551719249
},
"Component_[1551781018072505537]": {
"$type": "EditorInspectorComponent",
"Id": 1551781018072505537,
"ComponentOrderEntryArray": [
{
"ComponentId": 750431367071390348
},
{
"ComponentId": 10543707305560077725,
"SortIndex": 1
},
{
"ComponentId": 16828474708198673661,
"SortIndex": 2
},
{
"ComponentId": 6413469258372364445,
"SortIndex": 3
}
]
},
"Component_[1610584700060024614]": {
"$type": "EditorEntitySortComponent",
"Id": 1610584700060024614
},
"Component_[1702498396513087308]": {
"$type": "EditorLockComponent",
"Id": 1702498396513087308
},
"Component_[191898962635170167]": {
"$type": "SelectionComponent",
"Id": 191898962635170167
},
"Component_[5524024140510561095]": {
"$type": "EditorVisibilityComponent",
"Id": 5524024140510561095
},
"Component_[7126349013266909622]": {
"$type": "EditorPendingCompositionComponent",
"Id": 7126349013266909622
},
"Component_[750431367071390348]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 750431367071390348,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
56.0,
128.0,
37.0
],
"Scale": [
2.0,
2.0,
2.0
],
"UniformScale": 2.0
}
}
}
},
"Entity_[285018505936]": {
"Id": "Entity_[285018505936]",
"Name": "the_comments",
"Components": {
"Component_[12254043508887231201]": {
"$type": "EditorCommentComponent",
"Id": 12254043508887231201,
"Configuration": "This level is meant to show the most basic ocean scene.\n"
},
"Component_[13365140461414494550]": {
"$type": "EditorLockComponent",
"Id": 13365140461414494550
},
"Component_[15049990108511425568]": {
"$type": "EditorOnlyEntityComponent",
"Id": 15049990108511425568
},
"Component_[16058263010361769158]": {
"$type": "EditorCommentComponent",
"Id": 16058263010361769158,
"Configuration": "The physical object of \"the_thing\" requires the PhysicsEntities gem"
},
"Component_[3610853239595723287]": {
"$type": "EditorInspectorComponent",
"Id": 3610853239595723287,
"ComponentOrderEntryArray": [
{
"ComponentId": 6600498728445617807
},
{
"ComponentId": 12254043508887231201,
"SortIndex": 1
},
{
"ComponentId": 16058263010361769158,
"SortIndex": 2
}
]
},
"Component_[4646570851596337987]": {
"$type": "EditorEntitySortComponent",
"Id": 4646570851596337987
},
"Component_[6425461812824751097]": {
"$type": "EditorEntityIconComponent",
"Id": 6425461812824751097
},
"Component_[6600498728445617807]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 6600498728445617807,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
19.0,
114.0,
32.0
]
}
},
"Component_[748169014486201159]": {
"$type": "EditorVisibilityComponent",
"Id": 748169014486201159
},
"Component_[7489457744445094173]": {
"$type": "SelectionComponent",
"Id": 7489457744445094173
},
"Component_[8625778444077768294]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 8625778444077768294
},
"Component_[8776561997810927609]": {
"$type": "EditorPendingCompositionComponent",
"Id": 8776561997810927609
}
}
}
}
}

@ -0,0 +1,736 @@
{
"ContainerEntity": {
"Id": "ContainerEntity",
"Name": "ocean_trackview",
"Components": {
"Component_[10182366347512475253]": {
"$type": "EditorPrefabComponent",
"Id": 10182366347512475253
},
"Component_[12917798267488243668]": {
"$type": "EditorPendingCompositionComponent",
"Id": 12917798267488243668
},
"Component_[3261249813163778338]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3261249813163778338
},
"Component_[3837204912784440039]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 3837204912784440039
},
"Component_[4272963378099646759]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 4272963378099646759,
"Parent Entity": ""
},
"Component_[4848458548047175816]": {
"$type": "EditorVisibilityComponent",
"Id": 4848458548047175816
},
"Component_[5787060997243919943]": {
"$type": "EditorInspectorComponent",
"Id": 5787060997243919943
},
"Component_[7804170251266531779]": {
"$type": "EditorLockComponent",
"Id": 7804170251266531779
},
"Component_[7874177159288365422]": {
"$type": "EditorEntitySortComponent",
"Id": 7874177159288365422
},
"Component_[8018146290632383969]": {
"$type": "EditorEntityIconComponent",
"Id": 8018146290632383969
},
"Component_[8452360690590857075]": {
"$type": "SelectionComponent",
"Id": 8452360690590857075
}
}
},
"Entities": {
"Entity_[113557230075]": {
"Id": "Entity_[113557230075]",
"Name": "the_ocean",
"Components": {
"Component_[10578707299131614649]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 10578707299131614649,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
55.0,
81.0,
16.0
]
}
},
"Component_[11046344975288527044]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 11046344975288527044
},
"Component_[13465592091248295601]": {
"$type": "EditorInspectorComponent",
"Id": 13465592091248295601,
"ComponentOrderEntryArray": [
{
"ComponentId": 10578707299131614649
},
{
"ComponentId": 8504984791098638268,
"SortIndex": 1
},
{
"ComponentId": 2840515548992536974,
"SortIndex": 2
}
]
},
"Component_[13984822296855598165]": {
"$type": "EditorLockComponent",
"Id": 13984822296855598165
},
"Component_[14230937071328458692]": {
"$type": "EditorEntitySortComponent",
"Id": 14230937071328458692
},
"Component_[1515275142160994114]": {
"$type": "EditorPendingCompositionComponent",
"Id": 1515275142160994114
},
"Component_[16187876448121091850]": {
"$type": "EditorEntityIconComponent",
"Id": 16187876448121091850
},
"Component_[8504984791098638268]": {
"$type": "EditorSequenceAgentComponent",
"Id": 8504984791098638268,
"SequenceComponentEntityIds": [
"Entity_[117514781392]"
]
},
"Component_[9060135739962621874]": {
"$type": "EditorOnlyEntityComponent",
"Id": 9060135739962621874
},
"Component_[9086259058015300489]": {
"$type": "SelectionComponent",
"Id": 9086259058015300489
},
"Component_[9741974704446379447]": {
"$type": "EditorVisibilityComponent",
"Id": 9741974704446379447
}
}
},
"Entity_[117514781392]": {
"Id": "Entity_[117514781392]",
"Name": "the_seq",
"Components": {
"Component_[10651628595557926239]": {
"$type": "EditorPendingCompositionComponent",
"Id": 10651628595557926239
},
"Component_[11623691525514612151]": {
"$type": "EditorInspectorComponent",
"Id": 11623691525514612151,
"ComponentOrderEntryArray": [
{
"ComponentId": 4273477098584349604
},
{
"ComponentId": 5882335637425824535,
"SortIndex": 1
}
]
},
"Component_[12470939899970032484]": {
"$type": "EditorEntityIconComponent",
"Id": 12470939899970032484
},
"Component_[14478010456841775378]": {
"$type": "EditorOnlyEntityComponent",
"Id": 14478010456841775378
},
"Component_[18243888196443202779]": {
"$type": "EditorLockComponent",
"Id": 18243888196443202779
},
"Component_[1910120971488156322]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 1910120971488156322
},
"Component_[2096039468306613876]": {
"$type": "EditorVisibilityComponent",
"Id": 2096039468306613876
},
"Component_[4273477098584349604]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 4273477098584349604,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
61.15132141113281,
82.34228515625,
56.032203674316406
]
}
},
"Component_[4856824333512618654]": {
"$type": "SelectionComponent",
"Id": 4856824333512618654
},
"Component_[5882335637425824535]": {
"$type": "EditorSequenceComponent",
"Id": 5882335637425824535,
"Sequence": {
"$type": "CAnimSequence",
"Name": "the_seq",
"SequenceEntityId": "Entity_[117514781392]",
"Flags": 1,
"ID": 1,
"Nodes": [
{
"$type": "CAnimAzEntityNode",
"ID": 1,
"Name": "the_ocean",
"Flags": 6,
"Entity": "Entity_[113557230075]"
},
{
"$type": "CAnimComponentNode",
"ID": 2,
"Name": "Infinite Ocean",
"Tracks": [
{
"$type": "CCompoundSplineTrack",
"ParamType": {
"Type": 8,
"Name": "FogColor"
},
"NumSubTracks": 3,
"SubTracks": [
{
"$type": "TAnimSplineTrack<Vec2 >",
"DefaultValue": {
"y": 0.01568629965186119
},
"ParamType": {
"Type": 82
},
"Spline": {
"Keys": [
{
"flags": 73,
"ds": {
"x": 1.0
},
"dd": {
"x": 1.0
}
},
{
"time": 3.0,
"flags": 73,
"value": {
"x": 3.0,
"y": 255.0
},
"ds": {
"x": 1.0
},
"dd": {
"x": 1.0
}
},
{
"time": 5.0,
"flags": 73,
"value": {
"x": 5.0,
"y": 255.0
},
"ds": {
"x": 0.6666666865348816
},
"dd": {
"x": 0.6666666865348816
}
},
{
"time": 7.699999809265137,
"flags": 73,
"value": {
"x": 7.699999809265137
},
"ds": {
"x": 0.8999999761581421
},
"dd": {
"x": 0.8999999761581421
}
},
{
"time": 10.0,
"flags": 73,
"value": {
"x": 10.0
},
"ds": {
"x": 0.766666829586029
},
"dd": {
"x": 0.766666829586029
}
}
]
},
"Id": 2
},
{
"$type": "TAnimSplineTrack<Vec2 >",
"DefaultValue": {
"y": 0.09411770105361938
},
"ParamType": {
"Type": 83
},
"Spline": {
"Keys": [
{
"flags": 73,
"ds": {
"x": 1.0
},
"dd": {
"x": 1.0
}
},
{
"time": 3.0,
"flags": 73,
"value": {
"x": 3.0,
"y": 255.0
},
"ds": {
"x": 1.0
},
"dd": {
"x": 1.0
}
},
{
"time": 5.0,
"flags": 73,
"value": {
"x": 5.0,
"y": 102.50434112548828
},
"ds": {
"x": 0.6666666865348816
},
"dd": {
"x": 0.6666666865348816
}
},
{
"time": 7.699999809265137,
"flags": 73,
"value": {
"x": 7.699999809265137
},
"ds": {
"x": 0.8999999761581421
},
"dd": {
"x": 0.8999999761581421
}
},
{
"time": 10.0,
"flags": 73,
"value": {
"x": 10.0,
"y": 23.16463851928711
},
"ds": {
"x": 0.766666829586029
},
"dd": {
"x": 0.766666829586029
}
}
]
},
"Id": 3
},
{
"$type": "TAnimSplineTrack<Vec2 >",
"DefaultValue": {
"y": 0.1411765068769455
},
"ParamType": {
"Type": 84
},
"Spline": {
"Keys": [
{
"flags": 73,
"ds": {
"x": 1.0
},
"dd": {
"x": 1.0
}
},
{
"time": 3.0,
"flags": 73,
"value": {
"x": 3.0,
"y": 255.0
},
"ds": {
"x": 1.0
},
"dd": {
"x": 1.0
}
},
{
"time": 5.0,
"flags": 73,
"value": {
"x": 5.0,
"y": 255.0
},
"ds": {
"x": 0.6666666865348816
},
"dd": {
"x": 0.6666666865348816
}
},
{
"time": 7.699999809265137,
"flags": 73,
"value": {
"x": 7.699999809265137,
"y": 54.11885070800781
},
"ds": {
"x": 0.8999999761581421
},
"dd": {
"x": 0.8999999761581421
}
},
{
"time": 10.0,
"flags": 73,
"value": {
"x": 10.0
},
"ds": {
"x": 0.766666829586029
},
"dd": {
"x": 0.766666829586029
}
}
]
},
"Id": 4
},
null
],
"SubTrackNames": [
"Red",
"Green",
"Blue",
"W"
],
"ValueType": 20,
"Id": 1
}
],
"Parent": 1,
"ComponentID": 2840515548992536974,
"ComponentTypeID": "{961C77CC-CB98-49B8-83C4-CB7FD6D9AB5B}"
},
{
"$type": "CAnimComponentNode",
"ID": 3,
"Name": "Transform",
"Tracks": [
{
"$type": "CCompoundSplineTrack",
"ParamType": {
"Type": 1,
"Name": "Position"
},
"NumSubTracks": 3,
"SubTracks": [
{
"$type": "TAnimSplineTrack<Vec2 >",
"DefaultValue": {
"x": -8029758706415567000.0,
"y": 55.0
},
"ParamType": {
"Type": 51
},
"Id": 6
},
{
"$type": "TAnimSplineTrack<Vec2 >",
"DefaultValue": {
"x": -8029758706415567000.0,
"y": 81.0
},
"ParamType": {
"Type": 52
},
"Id": 7
},
{
"$type": "TAnimSplineTrack<Vec2 >",
"DefaultValue": {
"x": -8029758706415567000.0,
"y": 57.0
},
"ParamType": {
"Type": 53
},
"Id": 8
},
null
],
"SubTrackNames": [
"X",
"Y",
"Z",
"W"
],
"ValueType": 1,
"Id": 5
},
{
"$type": "CCompoundSplineTrack",
"ParamType": {
"Type": 2,
"Name": "Rotation"
},
"NumSubTracks": 3,
"SubTracks": [
{
"$type": "TAnimSplineTrack<Vec2 >",
"DefaultValue": {
"x": -8029758706415567000.0
},
"ParamType": {
"Type": 54
},
"Id": 10
},
{
"$type": "TAnimSplineTrack<Vec2 >",
"DefaultValue": {
"x": -8029758706415567000.0
},
"ParamType": {
"Type": 55
},
"Id": 11
},
{
"$type": "TAnimSplineTrack<Vec2 >",
"DefaultValue": {
"x": -8029758706415567000.0
},
"ParamType": {
"Type": 56
},
"Id": 12
},
null
],
"SubTrackNames": [
"X",
"Y",
"Z",
"W"
],
"ValueType": 2,
"Id": 9
}
],
"Parent": 1,
"ComponentID": 10578707299131614649,
"ComponentTypeID": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0}"
}
],
"Events": [
"start"
]
}
},
"Component_[8277927932072884141]": {
"$type": "EditorEntitySortComponent",
"Id": 8277927932072884141
}
}
},
"Entity_[310788309712]": {
"Id": "Entity_[310788309712]",
"Name": "the_comments",
"Components": {
"Component_[10820736773970990934]": {
"$type": "SelectionComponent",
"Id": 10820736773970990934
},
"Component_[16460362337690040728]": {
"$type": "EditorVisibilityComponent",
"Id": 16460362337690040728
},
"Component_[1711788818167604478]": {
"$type": "EditorInspectorComponent",
"Id": 1711788818167604478,
"ComponentOrderEntryArray": [
{
"ComponentId": 17162444099898225645
},
{
"ComponentId": 4524863805502269700,
"SortIndex": 1
}
]
},
"Component_[17162444099898225645]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 17162444099898225645,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
61.0,
82.0,
56.0
]
}
},
"Component_[17783575382365366340]": {
"$type": "EditorOnlyEntityComponent",
"Id": 17783575382365366340
},
"Component_[2087049458930367042]": {
"$type": "EditorLockComponent",
"Id": 2087049458930367042
},
"Component_[2711019276572888356]": {
"$type": "EditorEntitySortComponent",
"Id": 2711019276572888356
},
"Component_[4524863805502269700]": {
"$type": "EditorCommentComponent",
"Id": 4524863805502269700,
"Configuration": "This level is meant to test track view with the ocean component."
},
"Component_[6476444408609098475]": {
"$type": "EditorPendingCompositionComponent",
"Id": 6476444408609098475
},
"Component_[7805954804953628853]": {
"$type": "EditorEntityIconComponent",
"Id": 7805954804953628853
},
"Component_[8159544250366547808]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 8159544250366547808
}
}
},
"Entity_[315083277008]": {
"Id": "Entity_[315083277008]",
"Name": "the_camera",
"Components": {
"Component_[0]": {
"$type": "{CA11DA46-29FF-4083-B5F6-E02C3A8C3A3D} EditorCameraComponent"
},
"Component_[11755705402873798069]": {
"$type": "EditorVisibilityComponent",
"Id": 11755705402873798069
},
"Component_[11939241802298470223]": {
"$type": "EditorInspectorComponent",
"Id": 11939241802298470223,
"ComponentOrderEntryArray": [
{
"ComponentId": 13678215694230152557
},
{
"ComponentId": 7780955726439597543,
"SortIndex": 1
},
{
"ComponentId": 14118047423140175065,
"SortIndex": 2
}
]
},
"Component_[1263945907594972096]": {
"$type": "EditorPendingCompositionComponent",
"Id": 1263945907594972096
},
"Component_[13678215694230152557]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 13678215694230152557,
"Parent Entity": "ContainerEntity",
"Transform Data": {
"Translate": [
5.279235363006592,
89.93304443359375,
41.92418670654297
],
"Rotate": [
8.572165489196777,
351.0418701171875,
134.06057739257813
],
"Scale": [
0.9999998807907104,
0.9999998807907104,
1.0
]
}
},
"Component_[16694969224252903921]": {
"$type": "SelectionComponent",
"Id": 16694969224252903921
},
"Component_[16770043767194988305]": {
"$type": "EditorLockComponent",
"Id": 16770043767194988305
},
"Component_[17615022962377688621]": {
"$type": "EditorEntityIconComponent",
"Id": 17615022962377688621
},
"Component_[4781886688900343222]": {
"$type": "EditorEntitySortComponent",
"Id": 4781886688900343222
},
"Component_[8790131188175752902]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 8790131188175752902
},
"Component_[9731263833327927165]": {
"$type": "EditorOnlyEntityComponent",
"Id": 9731263833327927165
}
}
}
}
}

@ -25,6 +25,11 @@ extern "C" {
# include <Lua/lualib.h>
# include <Lua/lauxlib.h>
# include <Lua/lobject.h>
// versions of LUA before 5.3.x used to define a union that contained a double, a pointer, and a long
// as L_Umaxalign. Newer versions define those inner types in the macro LUAI_MAXALIGN instead but
// no longer actually declare a union around it. For backward compatibility we define the same one here
union L_Umaxalign { LUAI_MAXALIGN; };
}
#include <limits>
@ -1687,6 +1692,11 @@ LUA_API const Node* lua_getDummyNode()
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
const char* ScriptDataContext::GetInterpreterVersion()
{
return LUA_VERSION;
}
//////////////////////////////////////////////////////////////////////////
ScriptContext*
ScriptDataContext::GetScriptContext() const
@ -4367,7 +4377,7 @@ LUA_API const Node* lua_getDummyNode()
lua_pushlightuserdata(m_lua, m_owner);
int tableRef = luaL_ref(m_lua, LUA_REGISTRYINDEX);
(void)tableRef;
AZ_Assert(tableRef == AZ_LUA_SCRIPT_CONTEXT_REF, "Table referece should match %d !", AZ_LUA_SCRIPT_CONTEXT_REF);
AZ_Assert(tableRef == AZ_LUA_SCRIPT_CONTEXT_REF, "Table reference should match %d but is instead %d!", AZ_LUA_SCRIPT_CONTEXT_REF, tableRef);
// create a AZGlobals table, we can use internal unodered_map if it's faster (TODO: test which is faster, or if there is a benefit keeping in la)
lua_createtable(m_lua, 0, 1024); // pre allocate some values in the hash

@ -212,6 +212,10 @@ namespace AZ
~ScriptDataContext() { Reset(); }
//! Retrieve a string representing the current version of the interpreter.
//! Example of use: To signal incompatibility with previously emitted bytecode, to invalidate
static const char* GetInterpreterVersion();
ScriptContext* GetScriptContext() const;
lua_State* GetNativeContext() const { return m_nativeContext; }

@ -14,38 +14,13 @@ extern "C" {
# include <Lua/lauxlib.h>
}
// Currently we support Lua 5.1 and later (we have tested with 5.2)
#if LUA_VERSION_NUM <= 502
inline void lua_pushunsigned(lua_State* l, unsigned int v)
{
lua_pushnumber(l, static_cast<lua_Number>(v));
}
inline unsigned int lua_tounsigned(lua_State* l, int idx)
{
return static_cast<unsigned int>(lua_tonumber(l, idx));
}
#define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX)
inline LUA_API int lua_load(lua_State* L, lua_Reader reader, void* data, const char* chunkname, const char* mode)
{
(void)mode;
return lua_load(L, reader, data, chunkname);
}
#define LUA_RIDX_LAST 0
#define LUA_NUMTAGS 9
#endif
#define AZ_LUA_SCRIPT_CONTEXT_REF LUA_RIDX_LAST + 1
#define AZ_LUA_GLOBALS_TABLE_REF LUA_RIDX_LAST + 2
#define AZ_LUA_CLASS_TABLE_REF LUA_RIDX_LAST + 3
#define AZ_LUA_WEAK_CACHE_TABLE_REF LUA_RIDX_LAST + 4
#define AZ_LUA_ERROR_HANDLER_FUN_REF LUA_RIDX_LAST + 5
// Currently we support Lua 5.4.4 and later
// note that Lua 5.x defines LUA_RID_LAST + 1 to be an index of a free-list.
#define AZ_LUA_SCRIPT_CONTEXT_REF LUA_RIDX_LAST + 2
#define AZ_LUA_GLOBALS_TABLE_REF LUA_RIDX_LAST + 3
#define AZ_LUA_CLASS_TABLE_REF LUA_RIDX_LAST + 4
#define AZ_LUA_WEAK_CACHE_TABLE_REF LUA_RIDX_LAST + 5
#define AZ_LUA_ERROR_HANDLER_FUN_REF LUA_RIDX_LAST + 6
#define AZ_LUA_CLASS_METATABLE_NAME_INDEX 1 // can we always read the name from the behavior class???
#define AZ_LUA_CLASS_METATABLE_BEHAVIOR_CLASS 2

@ -117,11 +117,7 @@ namespace UnitTest
EXPECT_EQ(param2[0], "param2val");
}
#if AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS
TEST_F(ProcessLaunchParseTests, DISABLED_ProcessLauncher_StringsWithCommas_Success)
#else
TEST_F(ProcessLaunchParseTests, ProcessLauncher_WithCommas_Success)
#endif // AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS
{
ProcessLaunchParseTests::ParsedArgMap argMap;
AzFramework::ProcessOutput processOutput;
@ -155,11 +151,7 @@ namespace UnitTest
EXPECT_EQ(param2[1], "al");
}
#if AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS
TEST_F(ProcessLaunchParseTests, DISABLED_ProcessLauncher_StringsWithSpaces_Success)
#else
TEST_F(ProcessLaunchParseTests, ProcessLauncher_WithSpaces_Success)
#endif // AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS
{
ProcessLaunchParseTests::ParsedArgMap argMap;
AzFramework::ProcessOutput processOutput;
@ -191,11 +183,7 @@ namespace UnitTest
EXPECT_EQ(param2[0], "param2v al");
}
#if AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS
TEST_F(ProcessLaunchParseTests, DISABLED_ProcessLauncher_StringsWithSpacesAndComma_Success)
#else
TEST_F(ProcessLaunchParseTests, ProcessLauncher_WithSpacesAndComma_Success)
#endif // AZ_TRAIT_DISABLE_FAILED_PROCESS_LAUNCHER_TESTS
{
ProcessLaunchParseTests::ParsedArgMap argMap;
AzFramework::ProcessOutput processOutput;

@ -73,7 +73,7 @@ namespace AzToolsFramework
settings.m_keepDefaults = true;
}
if ((flags & StoreFlags::StoreLinkIds) != StoreFlags::None)
if ((flags & StoreFlags::StripLinkIds) != StoreFlags::StripLinkIds)
{
settings.m_metadata.Create<LinkIdMetadata>();
}

@ -52,7 +52,7 @@ namespace AzToolsFramework
//! We do not save linkIds to file. However when loading a level we want to temporarily save
//! linkIds to instance dom so any nested prefabs will have linkIds correctly set.
StoreLinkIds = 1 << 1
StripLinkIds = 1 << 1
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(StoreFlags);

@ -292,7 +292,7 @@ namespace AzToolsFramework::Prefab
return false;
}
const InstanceOptionalConstReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
InstanceOptionalReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
if (!instance.has_value())
{
return false;
@ -308,7 +308,7 @@ namespace AzToolsFramework::Prefab
return false;
}
InstanceOptionalConstReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
InstanceOptionalReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
while (instance.has_value())
{
if (instance->get().GetAbsoluteInstanceAliasPath() == m_rootAliasFocusPath)

@ -331,7 +331,7 @@ namespace AzToolsFramework
}
PrefabDom storedPrefabDom(&loadedTemplateDom->get().GetAllocator());
if (!PrefabDomUtils::StoreInstanceInPrefabDom(loadedPrefabInstance, storedPrefabDom, PrefabDomUtils::StoreFlags::StoreLinkIds))
if (!PrefabDomUtils::StoreInstanceInPrefabDom(loadedPrefabInstance, storedPrefabDom))
{
return false;
}
@ -359,7 +359,7 @@ namespace AzToolsFramework
PrefabDom storedPrefabDom(&savingTemplateDom->get().GetAllocator());
if (!PrefabDomUtils::StoreInstanceInPrefabDom(savingPrefabInstance, storedPrefabDom,
PrefabDomUtils::StoreFlags::StripDefaultValues))
PrefabDomUtils::StoreFlags::StripDefaultValues | PrefabDomUtils::StoreFlags::StripLinkIds))
{
return false;
}

@ -197,7 +197,7 @@ namespace AzToolsFramework
// Update the template of the instance since the entities are modified since the template creation.
Prefab::PrefabDom serializedInstance;
if (Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(instanceToCreate->get(), serializedInstance))
if (m_instanceToTemplateInterface->GenerateDomForInstance(serializedInstance, instanceToCreate->get()))
{
m_prefabSystemComponentInterface->UpdatePrefabTemplate(instanceToCreate->get().GetTemplateId(), serializedInstance);
}

@ -163,17 +163,21 @@ namespace AzToolsFramework
void PrefabSystemComponent::PropagateTemplateChanges(TemplateId templateId, InstanceOptionalConstReference instanceToExclude)
{
auto templateIdToLinkIdsIterator = m_templateToLinkIdsMap.find(templateId);
if (templateIdToLinkIdsIterator != m_templateToLinkIdsMap.end())
TemplateReference findTemplateResult = FindTemplate(templateId);
if (findTemplateResult.has_value())
{
// We need to initialize a queue here because once all linked instances of a template are updated,
// we will find all the linkIds corresponding to the updated template and add them to this queue again.
AZStd::queue<LinkIds> linkIdsToUpdateQueue;
linkIdsToUpdateQueue.push(LinkIds(templateIdToLinkIdsIterator->second.begin(),
templateIdToLinkIdsIterator->second.end()));
UpdateLinkedInstances(linkIdsToUpdateQueue);
auto templateIdToLinkIdsIterator = m_templateToLinkIdsMap.find(templateId);
if (templateIdToLinkIdsIterator != m_templateToLinkIdsMap.end())
{
// We need to initialize a queue here because once all linked instances of a template are updated,
// we will find all the linkIds corresponding to the updated template and add them to this queue again.
AZStd::queue<LinkIds> linkIdsToUpdateQueue;
linkIdsToUpdateQueue.push(
LinkIds(templateIdToLinkIdsIterator->second.begin(), templateIdToLinkIdsIterator->second.end()));
UpdateLinkedInstances(linkIdsToUpdateQueue);
}
UpdatePrefabInstances(templateId, instanceToExclude);
}
UpdatePrefabInstances(templateId, instanceToExclude);
}
void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom)

@ -256,7 +256,7 @@ namespace AzToolsFramework
return;
}
PrefabDomReference sourceDom = sourceTemplate->get().GetPrefabDom();
PrefabDom& sourceDom = sourceTemplate->get().GetPrefabDom();
//use instance pointer to reach position
PrefabDomValueReference instanceDomRef = link->get().GetLinkedInstanceDom();
@ -274,16 +274,14 @@ namespace AzToolsFramework
(result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::PartialSkip),
"Some of the patches are not successfully applied.");
//remove the link id placed into the instance
auto linkIdIter = instanceDom.FindMember(PrefabDomUtils::LinkIdName);
if (linkIdIter != instanceDom.MemberEnd())
{
instanceDom.RemoveMember(PrefabDomUtils::LinkIdName);
}
// Remove the link ids if present in the doms. We don't want any overrides to be created on top of linkIds because
// linkIds are not persistent and will be created dynamically when prefabs are loaded into the editor.
instanceDom.RemoveMember(PrefabDomUtils::LinkIdName);
sourceDom.RemoveMember(PrefabDomUtils::LinkIdName);
//we use this to diff our copy against the vanilla template (source template)
PrefabDom patchLink;
m_instanceToTemplateInterface->GeneratePatch(patchLink, sourceDom->get(), instanceDom);
m_instanceToTemplateInterface->GeneratePatch(patchLink, sourceDom, instanceDom);
// Create a copy of patchLink by providing the allocator of m_linkDomNext so that the patch doesn't become invalid when
// the patch goes out of scope in this function.

@ -29,7 +29,7 @@
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
#include <AzToolsFramework/ToolsComponents/TransformComponentBus.h>
#include <AzToolsFramework/ToolsComponents/TransformComponentSerializer.h>
#include <AzToolsFramework/ToolsComponents/EditorInspectorComponentBus.h>
@ -963,18 +963,22 @@ namespace AzToolsFramework
if (!m_parentEntityId.IsValid())
{
// If Prefabs are enabled, reroute the invalid id to the level root
// If Prefabs are enabled, reroute the invalid id to the focused prefab container entity id
bool isPrefabSystemEnabled = false;
AzFramework::ApplicationRequests::Bus::BroadcastResult(
isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
if (isPrefabSystemEnabled)
{
auto prefabPublicInterface = AZ::Interface<Prefab::PrefabPublicInterface>::Get();
auto prefabFocusPublicInterface = AZ::Interface<Prefab::PrefabFocusPublicInterface>::Get();
if (prefabPublicInterface)
if (prefabFocusPublicInterface)
{
m_parentEntityId = prefabPublicInterface->GetLevelInstanceContainerEntityId();
auto editorEntityContextId = AzFramework::EntityContextId::CreateNull();
EditorEntityContextRequestBus::BroadcastResult(
editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
m_parentEntityId = prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId);
refreshLevel = AZ::Edit::PropertyRefreshLevels::ValuesOnly;
}
}

@ -1280,48 +1280,72 @@ namespace Detail
#endif
#define ASSERT_CONSOLE_EXISTS 0
// the following macros allow the help text to be easily stripped out
// Summary:
// Preferred way to register a CVar
#define REGISTER_CVAR(_var, _def_val, _flags, _comment) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? 0 : gEnv->pConsole->Register((#_var), &(_var), (_def_val), (_flags), CVARHELP(_comment)))
#define REGISTER_CVAR(_var, _def_val, _flags, _comment) \
(gEnv->pConsole == 0 ? 0 : gEnv->pConsole->Register((#_var), &(_var), (_def_val), (_flags), CVARHELP(_comment)))
// Summary:
// Preferred way to register a CVar with a callback
#define REGISTER_CVAR_CB(_var, _def_val, _flags, _comment, _onchangefunction) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? 0 : gEnv->pConsole->Register((#_var), &(_var), (_def_val), (_flags), CVARHELP(_comment), _onchangefunction))
#define REGISTER_CVAR_CB(_var, _def_val, _flags, _comment, _onchangefunction) \
(gEnv->pConsole == 0 ? 0 : gEnv->pConsole->Register((#_var), &(_var), (_def_val), (_flags), CVARHELP(_comment), _onchangefunction))
// Summary:
// Preferred way to register a string CVar
#define REGISTER_STRING(_name, _def_val, _flags, _comment) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? 0 : gEnv->pConsole->RegisterString(_name, (_def_val), (_flags), CVARHELP(_comment)))
#define REGISTER_STRING(_name, _def_val, _flags, _comment) \
(gEnv->pConsole == 0 ? 0 : gEnv->pConsole->RegisterString(_name, (_def_val), (_flags), CVARHELP(_comment)))
// Summary:
// Preferred way to register a string CVar with a callback
#define REGISTER_STRING_CB(_name, _def_val, _flags, _comment, _onchangefunction) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? 0 : gEnv->pConsole->RegisterString(_name, (_def_val), (_flags), CVARHELP(_comment), _onchangefunction))
#define REGISTER_STRING_CB(_name, _def_val, _flags, _comment, _onchangefunction) \
(gEnv->pConsole == 0 ? 0 : gEnv->pConsole->RegisterString(_name, (_def_val), (_flags), CVARHELP(_comment), _onchangefunction))
// Summary:
// Preferred way to register an int CVar
#define REGISTER_INT(_name, _def_val, _flags, _comment) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? 0 : gEnv->pConsole->RegisterInt(_name, (_def_val), (_flags), CVARHELP(_comment)))
#define REGISTER_INT(_name, _def_val, _flags, _comment) \
(gEnv->pConsole == 0 ? 0 : gEnv->pConsole->RegisterInt(_name, (_def_val), (_flags), CVARHELP(_comment)))
// Summary:
// Preferred way to register an int CVar with a callback
#define REGISTER_INT_CB(_name, _def_val, _flags, _comment, _onchangefunction) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? 0 : gEnv->pConsole->RegisterInt(_name, (_def_val), (_flags), CVARHELP(_comment), _onchangefunction))
#define REGISTER_INT_CB(_name, _def_val, _flags, _comment, _onchangefunction) \
(gEnv->pConsole == 0 ? 0 : gEnv->pConsole->RegisterInt(_name, (_def_val), (_flags), CVARHELP(_comment), _onchangefunction))
// Summary:
// Preferred way to register a float CVar
#define REGISTER_FLOAT(_name, _def_val, _flags, _comment) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? 0 : gEnv->pConsole->RegisterFloat(_name, (_def_val), (_flags), CVARHELP(_comment)))
#define REGISTER_FLOAT(_name, _def_val, _flags, _comment) \
(gEnv->pConsole == 0 ? 0 : gEnv->pConsole->RegisterFloat(_name, (_def_val), (_flags), CVARHELP(_comment)))
// Summary:
// Offers more flexibility but more code is required
#define REGISTER_CVAR2(_name, _var, _def_val, _flags, _comment) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? 0 : gEnv->pConsole->Register(_name, _var, (_def_val), (_flags), CVARHELP(_comment)))
#define REGISTER_CVAR2(_name, _var, _def_val, _flags, _comment) \
(gEnv->pConsole == 0 ? 0 : gEnv->pConsole->Register(_name, _var, (_def_val), (_flags), CVARHELP(_comment)))
// Summary:
// Offers more flexibility but more code is required
#define REGISTER_CVAR2_CB(_name, _var, _def_val, _flags, _comment, _onchangefunction) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? 0 : gEnv->pConsole->Register(_name, _var, (_def_val), (_flags), CVARHELP(_comment), _onchangefunction))
#define REGISTER_CVAR2_CB(_name, _var, _def_val, _flags, _comment, _onchangefunction) \
(gEnv->pConsole == 0 ? 0 : gEnv->pConsole->Register(_name, _var, (_def_val), (_flags), CVARHELP(_comment), _onchangefunction))
// Summary:
// Offers more flexibility but more code is required, explicit address taking of destination variable
#define REGISTER_CVAR3(_name, _var, _def_val, _flags, _comment) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? 0 : gEnv->pConsole->Register(_name, &(_var), (_def_val), (_flags), CVARHELP(_comment)))
#define REGISTER_CVAR3(_name, _var, _def_val, _flags, _comment) \
(gEnv->pConsole == 0 ? 0 : gEnv->pConsole->Register(_name, &(_var), (_def_val), (_flags), CVARHELP(_comment)))
// Summary:
// Preferred way to register a console command
#define REGISTER_COMMAND(_name, _func, _flags, _comment) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? false : gEnv->pConsole->AddCommand(_name, _func, (_flags), CVARHELP(_comment)))
#define REGISTER_COMMAND(_name, _func, _flags, _comment) \
(gEnv->pConsole == 0 ? false : gEnv->pConsole->AddCommand(_name, _func, (_flags), CVARHELP(_comment)))
// Summary:
// Preferred way to unregister a CVar
#define UNREGISTER_CVAR(_name) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? (void)0 : gEnv->pConsole->UnregisterVariable(_name))
#define UNREGISTER_CVAR(_name) \
(gEnv->pConsole == 0 ? (void)0 : gEnv->pConsole->UnregisterVariable(_name))
// Summary:
// Preferred way to unregister a console command
#define UNREGISTER_COMMAND(_name) (ASSERT_CONSOLE_EXISTS, gEnv->pConsole == 0 ? (void)0 : gEnv->pConsole->RemoveCommand(_name))
#define UNREGISTER_COMMAND(_name) \
(gEnv->pConsole == 0 ? (void)0 : gEnv->pConsole->RemoveCommand(_name))
////////////////////////////////////////////////////////////////////////////////
//

@ -106,7 +106,7 @@ typedef uint8 byte;
#ifdef _RELEASE
#define __debugbreak()
#else
#define __debugbreak() "_asm int 3"
#define __debugbreak() asm("int3")
#endif
#define __assume(x)

@ -21,6 +21,8 @@
#define mallocAligned(sze) _aligned_malloc(sze, 16)
#define freeAligned(ptr) _aligned_free(ptr)
AZ_PUSH_DISABLE_WARNING_GCC("-Wunused-value")
/* ####################################################################################################################
*/
@ -1279,3 +1281,5 @@ namespace ImageProcessingAtom
FilterImage(filterIndex, filterOp, blurH, blurV, srcImg, srcMip, dstImg, dstMip, srcRect, dstRect);
}
}
AZ_POP_DISABLE_WARNING_GCC

@ -1154,7 +1154,7 @@
{
"name": "thickness",
"displayName": " Thickness",
"description": "Normalized global thickness, the maxima between this value (multiplied by thickness map if enabled) and thickness from shadow map (if applicable) will be used as final thickness of pixel",
"description": "In thick transmission mode: Normalized global thickness, the maxima between this value (multiplied by thickness map if enabled) and thickness from shadow map (if applicable) will be used as final thickness of pixel\n\nIn thin transmission mode: This value modulates the distance traversed by light inside an object.",
"type": "float",
"defaultValue": 0.5,
"min": 0.0,
@ -1223,14 +1223,41 @@
"min": 0.0,
"softMax": 20.0
},
{
"name": "shrinkFactor",
"displayName": " Shrink Factor",
"description": "Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection",
"type": "float",
"defaultValue": 0.005,
"min": 0.0,
"softMax": 0.05
},
{
"name": "transmissionNdLBias",
"displayName": " Angle Bias",
"description": "cosine of angle to extend below (N . L = 0) in scattering through thin objects",
"type": "float",
"defaultValue": 0.1,
"min": -1.0,
"softMax": 1.0
},
{
"name": "distanceAttenuation",
"displayName": " Distance Attenuation",
"description": "Attenuation of the transmission effect, used to hide artifacts due to low-res shadow maps\nFor directional lights: attenuation proportional to the distance from the object to the camera.\nFor other light sources: attenuation proportional to the distance from the object to the light source.",
"type": "float",
"defaultValue": 0.5,
"min": 0.0,
"softMax": 4.0
},
{
"name": "transmissionScale",
"displayName": " Scale",
"description": "Strength of transmission",
"type": "float",
"defaultValue": 3.0,
"defaultValue": 1.0,
"min": 0.0,
"softMax": 20.0
"softMax": 5.0
}
],
"detailLayerGroup": [
@ -1555,6 +1582,9 @@
"power": "subsurfaceScattering.transmissionPower",
"distortion": "subsurfaceScattering.transmissionDistortion",
"attenuation": "subsurfaceScattering.transmissionAttenuation",
"shrinkFactor": "subsurfaceScattering.shrinkFactor",
"transmissionNdLBias": "subsurfaceScattering.transmissionNdLBias",
"distanceAttenuation": "subsurfaceScattering.distanceAttenuation",
"tintColor": "subsurfaceScattering.transmissionTint",
"thickness": "subsurfaceScattering.thickness",
"enabled": "subsurfaceScattering.enableSubsurfaceScattering",

@ -93,7 +93,7 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial
// Elements of m_transmissionParams:
// Thick object mode: (attenuation coefficient, power, distortion, scale)
// Thin object mode: (float3 scatter distance, scale)
// Thin object mode: (shrinkFactor, transmissionNdLBias, distanceAttenuation, scale)
float4 m_transmissionParams;
// (float3 TintColor, thickness)

@ -243,6 +243,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
surface.transmission.tint = transmissionTintThickness.rgb;
surface.transmission.thickness = transmissionTintThickness.w;
surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams;
surface.transmission.scatterDistance = MaterialSrg::m_scatterDistance;
// ------- Anisotropy -------
@ -275,6 +276,17 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture);
lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture);
// ------- Thin Object Light Transmission -------
// Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection
lightingData.shrinkFactor = surface.transmission.transmissionParams.x;
// Angle offset for subsurface scattering through thin objects
lightingData.transmissionNdLBias = surface.transmission.transmissionParams.y;
// Attenuation applied to hide artifacts due to low-res shadow maps
lightingData.distanceAttenuation = surface.transmission.transmissionParams.z;
// ------- Clearcoat -------
// [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags

@ -92,23 +92,34 @@ function ProcessEditor(context)
-- Update visibility for transmission...
local transmissionEnabled = TransmissionMode_None ~= context:GetMaterialPropertyValue_enum("subsurfaceScattering.transmissionMode")
local thickTransmissionEnabled = TransmissionMode_ThickObject == context:GetMaterialPropertyValue_enum("subsurfaceScattering.transmissionMode")
local thinTransmissionEnabled = TransmissionMode_ThinObject == context:GetMaterialPropertyValue_enum("subsurfaceScattering.transmissionMode")
local commonTrasmissionVisibility
if(transmissionEnabled) then
local commonTrasmissionVisibility = MaterialPropertyVisibility_Hidden
local thickTransmissionVisibility = MaterialPropertyVisibility_Hidden
local thinTransmissionVisibility = MaterialPropertyVisibility_Hidden
if (thickTransmissionEnabled or thinTransmissionEnabled) then
commonTrasmissionVisibility = MaterialPropertyVisibility_Enabled
else
commonTrasmissionVisibility = MaterialPropertyVisibility_Hidden
if(thickTransmissionEnabled) then
thickTransmissionVisibility = MaterialPropertyVisibility_Enabled
else -- thin transmission enabled
thinTransmissionVisibility = MaterialPropertyVisibility_Enabled
end
end
context:SetMaterialPropertyVisibility("subsurfaceScattering.thickness", commonTrasmissionVisibility)
context:SetMaterialPropertyVisibility("subsurfaceScattering.thicknessMap", commonTrasmissionVisibility)
context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionTint", commonTrasmissionVisibility)
context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionPower", commonTrasmissionVisibility)
context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionDistortion", commonTrasmissionVisibility)
context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionAttenuation", commonTrasmissionVisibility)
context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionPower", thickTransmissionVisibility)
context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionDistortion", thickTransmissionVisibility)
context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionAttenuation", thickTransmissionVisibility)
context:SetMaterialPropertyVisibility("subsurfaceScattering.shrinkFactor", thinTransmissionVisibility)
context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionNdLBias", thinTransmissionVisibility)
context:SetMaterialPropertyVisibility("subsurfaceScattering.distanceAttenuation", thinTransmissionVisibility)
context:SetMaterialPropertyVisibility("subsurfaceScattering.transmissionScale", commonTrasmissionVisibility)
UpdateTextureDependentPropertyVisibility(context, transmissionEnabled, "subsurfaceScattering.thicknessMap", "subsurfaceScattering.useThicknessMap", "subsurfaceScattering.thicknessMapUv")
UpdateTextureDependentPropertyVisibility(context, thickTransmissionEnabled or thinTransmissionEnabled, "subsurfaceScattering.thicknessMap", "subsurfaceScattering.useThicknessMap", "subsurfaceScattering.thicknessMapUv")
end

@ -325,6 +325,7 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
surface.transmission.tint = transmissionTintThickness.rgb;
surface.transmission.thickness = transmissionTintThickness.w;
surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams;
surface.transmission.scatterDistance = MaterialSrg::m_scatterDistance;
// ------- Lighting Data -------
@ -341,6 +342,17 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear);
lightingData.diffuseResponse = 1.0 - lightingData.specularResponse;
// ------- Thin Object Light Transmission -------
// Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection
lightingData.shrinkFactor = surface.transmission.transmissionParams.x;
// Angle offset for subsurface scattering through thin objects
lightingData.transmissionNdLBias = surface.transmission.transmissionParams.y;
// Attenuation applied to hide artifacts due to low-res shadow maps
lightingData.distanceAttenuation = surface.transmission.transmissionParams.z;
// ------- Occlusion -------
lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture);

@ -568,7 +568,7 @@
{
"name": "thickness",
"displayName": " Thickness",
"description": "Normalized global thickness, the maxima between this value (multiplied by thickness map if enabled) and thickness from shadow map (if applicable) will be used as final thickness of pixel",
"description": "In thick transmission mode: Normalized global thickness, the maxima between this value (multiplied by thickness map if enabled) and thickness from shadow map (if applicable) will be used as final thickness of pixel\n\nIn thin transmission mode: This value modulates the distance traversed by light inside an object.",
"type": "float",
"defaultValue": 0.5,
"min": 0.0,
@ -637,14 +637,41 @@
"min": 0.0,
"softMax": 20.0
},
{
"name": "shrinkFactor",
"displayName": " Shrink Factor",
"description": "Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection",
"type": "float",
"defaultValue": 0.005,
"min": 0.0,
"softMax": 0.05
},
{
"name": "transmissionNdLBias",
"displayName": " Angle Bias",
"description": "cosine of angle to extend below (N . L = 0) in scattering through thin objects",
"type": "float",
"defaultValue": 0.1,
"min": -1.0,
"softMax": 1.0
},
{
"name": "distanceAttenuation",
"displayName": " Distance Attenuation",
"description": "Attenuation of the transmission effect, used to hide artifacts due to low-res shadow maps\nFor directional lights: attenuation proportional to the distance from the object to the camera.\nFor other light sources: attenuation proportional to the distance from the object to the light source.",
"type": "float",
"defaultValue": 0.5,
"min": 0.0,
"softMax": 4.0
},
{
"name": "transmissionScale",
"displayName": " Scale",
"description": "Strength of transmission",
"type": "float",
"defaultValue": 3.0,
"defaultValue": 1.0,
"min": 0.0,
"softMax": 20.0
"softMax": 5.0
}
],
"wrinkleLayers": [
@ -1011,6 +1038,9 @@
"power": "subsurfaceScattering.transmissionPower",
"distortion": "subsurfaceScattering.transmissionDistortion",
"attenuation": "subsurfaceScattering.transmissionAttenuation",
"shrinkFactor": "subsurfaceScattering.shrinkFactor",
"transmissionNdLBias": "subsurfaceScattering.transmissionNdLBias",
"distanceAttenuation": "subsurfaceScattering.distanceAttenuation",
"tintColor": "subsurfaceScattering.transmissionTint",
"thickness": "subsurfaceScattering.thickness",
"enabled": "subsurfaceScattering.enableSubsurfaceScattering",

@ -22,6 +22,10 @@
#include "MaterialInputs/UvSetCount.azsli"
#include "MaterialInputs/DetailMapsInput.azsli"
// Use human skin profile for thin object transmission (if enabled)
// Remove this line to use a custom profile based on the scatter color
#define USE_HUMAN_SKIN_PROFILE
ShaderResourceGroup MaterialSrg : SRG_PerMaterial
{
// Auto-generate material SRG fields for common inputs
@ -64,7 +68,7 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial
// Elements of m_transmissionParams:
// Thick object mode: (attenuation coefficient, power, distortion, scale)
// Thin object mode: (float3 scatter distance, scale)
// Thin object mode: (shrinkFactor, transmissionNdLBias, distanceAttenuation, scale)
float4 m_transmissionParams;
// (float3 TintColor, thickness)

@ -16,24 +16,28 @@
#include <Atom/Features/PBR/LightingOptions.azsli>
// Analytical integation (approximation) of diffusion profile over radius, could be replaced by other pre integrated kernels
// such as sum of Gaussian
// such as sum of Gaussian (see T(s))
float3 TransmissionKernel(float t, float3 s)
{
float3 exponent = s * t;
return 0.25 * (1.0 / exp(exponent) + 3.0 / exp(exponent / 3.0));
}
float ThinObjectFalloff(const float3 surfaceNormal, const float3 dirToLight)
// [specific profile for human skin]
// Analytical integation (approximation) of diffusion profile over radius, could be precomputed in a LUT
// From d'Eon and Luebke (https://developer.nvidia.com/gpugems/gpugems3/part-iii-rendering/chapter-14-advanced-techniques-realistic-real-time-skin, section 14.4.7)
float3 T(float s)
{
const float ndl = saturate(dot(-surfaceNormal, dirToLight));
// ndl works decently well but it can produce a harsh discontinuity in the area just before
// the shadow starts appearing on objects like cylinder and tubes.
// Smoothing out ndl does a decent enough job of removing this artifact.
return smoothstep(0, 1, ndl * ndl);
// dipoles and multipoles are approximated with sums of a small number of Gaussians with variable weights and variances
return float3(0.233, 0.455, 0.649) * exp(-s*s/0.0064) +
float3(0.1, 0.336, 0.344) * exp(-s*s/0.0484) +
float3(0.118, 0.198, 0.0) * exp(-s*s/0.187) +
float3(0.113, 0.007, 0.007) * exp(-s*s/0.567) +
float3(0.358, 0.004, 0.0) * exp(-s*s/1.99) +
float3(0.078, 0.0, 0.0) * exp(-s*s/7.41);
}
float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight, float shadowRatio)
float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight, float transmissionDistance, float attenuationDistance)
{
float3 result = float3(0.0, 0.0, 0.0);
@ -52,7 +56,7 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI
// https://colinbarrebrisebois.com/2011/03/07/gdc-2011-approximating-translucency-for-a-fast-cheap-and-convincing-subsurface-scattering-look/
{
thickness = max(shadowRatio, surface.transmission.thickness);
thickness = max(transmissionDistance, surface.transmission.thickness);
float transmittance = pow( saturate( dot( lightingData.dirToCamera, -normalize( dirToLight + surface.normal * transmissionParams.z ) ) ), transmissionParams.y ) * transmissionParams.w;
float lamberAttenuation = exp(-thickness * transmissionParams.x) * saturate(1.0 - thickness);
result = transmittance * lamberAttenuation * lightIntensity;
@ -60,18 +64,39 @@ float3 GetBackLighting(Surface surface, LightingData lightingData, float3 lightI
break;
case TransmissionMode::ThinObject:
// Thin object mode, using thin-film assumption proposed by Jimenez J. et al, 2010, "Real-Time Realistic Skin Translucency"
// Thin object mode, based on Jimenez J. et al, 2010, "Real-Time Realistic Skin Translucency"
// http://www.iryoku.com/translucency/downloads/Real-Time-Realistic-Skin-Translucency.pdf
float litRatio = 1.0 - shadowRatio;
if (litRatio)
{
const float thickness = surface.transmission.thickness * transmissionParams.w;
const float3 invScattering = rcp(transmissionParams.xyz);
const float falloff = ThinObjectFalloff(surface.normal, dirToLight);
result = TransmissionKernel(thickness, invScattering) * falloff * lightIntensity * litRatio;
}
// transmissionDistance < 0.0f means shadows are not enabled --> avoid unnecessary computation
if (transmissionDistance < 0.0f)
{
break;
}
// Irradiance arround surface point.
// Albedo at front (surface point) is used to approximate irradiance at the back of the object (observation 4 in [Jimenez J. et al, 2010])
// Increase angle of influence to smooth transition regions
float3 E = surface.albedo * saturate(lightingData.transmissionNdLBias + dot(-surface.normal, dirToLight));
// Transmission distance modulated by hardcoded constant C and the thickness exposed parameter (in this case modulating the distance traversed by the light inside the object)
const float C = 300.0f;
float s = transmissionDistance * C * surface.transmission.thickness;
// Use scattering color to weight thin object transmission color
const float3 invScattering = rcp(max(surface.transmission.scatterDistance, float(0.00001)));
#ifndef USE_HUMAN_SKIN_PROFILE
// Generic profile based on scatter color
result = TransmissionKernel(s, invScattering) * lightIntensity * E * transmissionParams.w;
#else // USE_HUMAN_SKIN_PROFILE
// Profile specific to human skin
result = T(s) * lightIntensity * E * transmissionParams.w;
#endif
// Distance attenuation applied to hide artifacts due to low-res projected areas onto shadowmaps (might need some work in the future)
result /= max(1.0, attenuationDistance * attenuationDistance * lightingData.distanceAttenuation);
}
break;
}

@ -28,6 +28,15 @@ class LightingData
// Direction light shadow coordinates
float3 shadowCoords[ViewSrg::MaxCascadeCount];
// (N . L) to accept below (N . L = 0) in scattering through thin objects
float transmissionNdLBias;
// Shrink (absolute) offset towards the normal opposite direction to ensure correct shadow map projection
float shrinkFactor;
// Attenuation applied to hide artifacts due to low-res shadow maps
float distanceAttenuation;
// Normalized direction from surface to camera
float3 dirToCamera;

@ -135,8 +135,15 @@ void ApplyCapsuleLight(ViewSrg::CapsuleLight light, Surface surface, inout Light
float3 closestIntersectionPoint = startPoint + closestT * startToEnd;
float3 posToLight = closestIntersectionPoint - surface.position;
// Tranmission contribution
lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), 0.0);
// Transmission contribution
// We cannot compute the actual transmission distance so we want to:
// - If transmission mode is thick object -> use transmission thickness parameter instead
// - If transmission mode is thin object -> ignore back lighting
// To detect and apply this behavior in the GetBackLighting function, we need to use a negative transmissionDistance
const float transmissionDistance = -1.0f;
// If the transmissionDistance is ignored then the attenuation distance (only used on thin objects) does not have any influence
const float attenuationDistance = 0.0f;
lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), transmissionDistance, attenuationDistance);
// Calculate the offset from the nearest point on the reflection vector to the nearest point on the capsule light
float3 posToClosestPointAlongReflection = dot(posToLight, reflectionDir) * reflectionDir;

@ -18,7 +18,13 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData)
// Shadowed check
const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight;
float litRatio = 1.0f;
float backShadowRatio = 0.0f;
float camToSurfDist = distance(ViewSrg::m_worldPosition, surface.position);
// Distance travelled by the light inside the object. If not redefined to a non-negative value, it will take the following behavior:
// - If transmission mode is thick object -> use transmission thickness parameter instead
// - If transmission mode is thin object -> ignore back lighting
float transmissionDistance = -1.0f;
if (o_enableShadows && shadowIndex < SceneSrg::m_directionalLightCount)
{
litRatio = DirectionalLightShadow::GetVisibility(
@ -30,7 +36,19 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData)
#if ENABLE_TRANSMISSION
if (o_transmission_mode == TransmissionMode::ThickObject)
{
backShadowRatio = DirectionalLightShadow::GetThickness(shadowIndex, lightingData.shadowCoords);
transmissionDistance = DirectionalLightShadow::GetThickness(shadowIndex, lightingData.shadowCoords);
}
else if (o_transmission_mode == TransmissionMode::ThinObject)
{
// Fetch and use shrinked positions for thin object transmission to ensure they fall onto the object when querying
DirectionalLightShadow::GetShadowCoords(
shadowIndex,
surface.position - lightingData.shrinkFactor * surface.vertexNormal,
surface.normal,
lightingData.shadowCoords);
// the depth from the shadow map
transmissionDistance = DirectionalLightShadow::GetThickness(shadowIndex, lightingData.shadowCoords);
}
#endif
}
@ -52,23 +70,20 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData)
// [GFX TODO][ATOM-2012] care of multiple directional light
// Currently shadow check is done only for index == shadowIndex.
float currentLitRatio = 1.0f;
float currentBackShadowRatio = 1.0f;
if (o_enableShadows)
{
currentLitRatio = (index == shadowIndex) ? litRatio : 1.;
float currentTransmissionDistance = -1.0f;
currentBackShadowRatio = 1.0 - currentLitRatio;
#if ENABLE_TRANSMISSION
if (o_transmission_mode == TransmissionMode::ThickObject)
{
currentBackShadowRatio = (index == shadowIndex) ? backShadowRatio : 0.;
}
#endif
if (o_enableShadows && index == shadowIndex)
{
// Add contribution only if current directional light is the active one for shadows
currentLitRatio = litRatio;
currentTransmissionDistance = transmissionDistance;
}
// Transmission contribution
lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentTransmissionDistance, camToSurfDist);
lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio;
lightingData.specularLighting += GetSpecularLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight) * currentLitRatio;
lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, light.m_rgbIntensityLux, dirToLight, currentBackShadowRatio);
}
// Add debug coloring for directional light shadow

@ -77,8 +77,11 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat
// shadow
float litRatio = 1.0;
// How much is back face shadowed, it's set to the reverse of litRatio to share the same default value with thickness, which should be 0 if no shadow map available
float backShadowRatio = 0.0;
// Distance travelled by the light inside the object. If not redefined to a non-negative value, it will take the following behavior:
// - If transmission mode is thick object -> use transmission thickness parameter instead
// - If transmission mode is thin object -> ignore back lighting
float transmissionDistance = -1.0f;
if (o_enableShadows)
{
litRatio = ProjectedShadow::GetVisibility(
@ -88,14 +91,16 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat
-dirToConeTip,
surface.vertexNormal);
// Use backShadowRatio to carry thickness from shadow map for thick mode
backShadowRatio = 1.0 - litRatio;
// o_transmission_mode == NONE is not taken into account because GetBackLighting already ignores this case
#if ENABLE_TRANSMISSION
if (o_transmission_mode == TransmissionMode::ThickObject)
{
backShadowRatio = ProjectedShadow::GetThickness(
light.m_shadowIndex,
surface.position);
transmissionDistance = ProjectedShadow::GetThickness(light.m_shadowIndex, surface.position);
}
else if (o_transmission_mode == TransmissionMode::ThinObject)
{
transmissionDistance = ProjectedShadow::GetThickness(light.m_shadowIndex, surface.position - lightingData.shrinkFactor * surface.vertexNormal);
}
#endif
}
@ -115,7 +120,7 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat
lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, posToLightDir) * litRatio;
// Transmission contribution
lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, posToLightDir, backShadowRatio);
lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, posToLightDir, transmissionDistance, distanceToLight2);
// Adjust the light direction for specular based on disk size

@ -46,6 +46,16 @@ void AddSampleContribution(
float3 intensityRgb = float3(intensity, intensity, intensity);
diffuseAcc += GetDiffuseLighting(surface, lightingData, intensityRgb, posToLightSampleDir);
translucentAcc += GetBackLighting(surface, lightingData, intensityRgb, posToLightSampleDir, 0.0);
// Transmission contribution
// We cannot compute the actual transmission distance so we want to:
// - If transmission mode is thick object -> use transmission thickness parameter instead
// - If transmission mode is thin object -> ignore back lighting
// To detect and apply this behavior in the GetBackLighting function, we need to use a negative transmissionDistance
const float transmissionDistance = -1.0f;
// If the transmissionDistance is ignored then the attenuation distance (only used on thin objects) does not have any influence
const float attenuationDistance = 0.0f;
translucentAcc += GetBackLighting(surface, lightingData, intensityRgb, posToLightSampleDir, transmissionDistance, attenuationDistance);
specularAcc += GetSpecularLighting(surface, lightingData, intensityRgb, posToLightSampleDir);
}

@ -67,6 +67,7 @@ uint ComputeShadowIndex(const ViewSrg::PointLight light, const Surface surface)
void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingData lightingData)
{
float3 posToLight = light.m_position - surface.position;
float posToLightDist = length(posToLight);
float d2 = dot(posToLight, posToLight); // light distance squared
float falloff = d2 * light.m_invAttenuationRadiusSquared;
@ -84,8 +85,11 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD
// shadow
float litRatio = 1.0;
// How much is back face shadowed, it's set to the reverse of litRatio to share the same default value with thickness, which should be 0 if no shadow map available
float backShadowRatio = 0.0;
// Distance travelled by the light inside the object. If not redefined to a non-negative value, it will take the following behavior:
// - If transmission mode is thick object -> use transmission thickness parameter instead
// - If transmission mode is thin object -> ignore back lighting
float transmissionDistance = -1.0f;
if (o_enableShadows)
{
const float3 lightDir = normalize(light.m_position - surface.position);
@ -97,14 +101,15 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD
lightDir,
surface.vertexNormal);
// Use backShadowRatio to carry thickness from shadow map for thick mode
backShadowRatio = 1.0 - litRatio;
#if ENABLE_TRANSMISSION
// o_transmission_mode == NONE is not taken into account because GetBackLighting already ignores this case
if (o_transmission_mode == TransmissionMode::ThickObject)
{
backShadowRatio = ProjectedShadow::GetThickness(
shadowIndex,
surface.position);
transmissionDistance = ProjectedShadow::GetThickness(shadowIndex, surface.position);
}
else if (o_transmission_mode == TransmissionMode::ThinObject)
{
transmissionDistance = ProjectedShadow::GetThickness(shadowIndex, surface.position - lightingData.shrinkFactor * surface.vertexNormal);
}
#endif
}
@ -113,7 +118,7 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD
lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, normalize(posToLight)) * litRatio;
// Transmission contribution
lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), backShadowRatio);
lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), transmissionDistance, posToLightDist);
// Adjust the light direcion for specular based on bulb size

@ -148,13 +148,21 @@ void ApplyQuadLight(ViewSrg::QuadLight light, Surface surface, inout LightingDat
GetDiffuseLighting(surface, lightingData, intensity, dirToLightCenter)
);
// Transmission contribution
// We cannot compute the actual transmission distance so we want to:
// - If transmission mode is thick object -> use transmission thickness parameter instead
// - If transmission mode is thin object -> ignore back lighting
// To detect and apply this behavior in the GetBackLighting function, we need to use a negative transmissionDistance
const float transmissionDistance = -1.0f;
// If the transmissionDistance is ignored then the attenuation distance (only used on thin objects) does not have any influence
const float attenuationDistance = 0.0f;
lightingData.translucentBackLighting +=
(
GetBackLighting(surface, lightingData, intensity, p0, 0.0) +
GetBackLighting(surface, lightingData, intensity, p1, 0.0) +
GetBackLighting(surface, lightingData, intensity, p2, 0.0) +
GetBackLighting(surface, lightingData, intensity, p3, 0.0) +
GetBackLighting(surface, lightingData, intensity, dirToLightCenter, 0.0)
GetBackLighting(surface, lightingData, intensity, p0, transmissionDistance, attenuationDistance) +
GetBackLighting(surface, lightingData, intensity, p1, transmissionDistance, attenuationDistance) +
GetBackLighting(surface, lightingData, intensity, p2, transmissionDistance, attenuationDistance) +
GetBackLighting(surface, lightingData, intensity, p3, transmissionDistance, attenuationDistance) +
GetBackLighting(surface, lightingData, intensity, dirToLightCenter, transmissionDistance, attenuationDistance)
);
// Calculate specular by choosing a single representative point on the light's surface based on the reflection ray

@ -14,7 +14,8 @@ class TransmissionSurfaceData
{
float3 tint;
float thickness; //!< pre baked local thickness, used for transmission
float4 transmissionParams; //!< parameters: thick mode->(attenuation coefficient, power, distortion, scale), thin mode: (float3 scatter distance, scale)
float4 transmissionParams; //!< parameters: thick mode->(attenuation coefficient, power, distortion, scale), thin mode: (shrinkFactor, transmissionNdLBias, distanceAttenuation, scale)
float3 scatterDistance; //!< scatter distance (same as in MaterialSrg) >
void InitializeToZero();
};
@ -24,6 +25,7 @@ void TransmissionSurfaceData::InitializeToZero()
tint = float3(0.0f, 0.0f, 0.0f);
thickness = 0.0f;
transmissionParams = float4(0.0f, 0.0f, 0.0f, 0.0f);
scatterDistance = float3(0.0f, 0.0f, 0.0f);
}
#endif

@ -161,7 +161,10 @@ float DirectionalLightShadow::GetThickness(uint lightIndex, float3 shadowCoords[
shadowCoord.y >= 0. && shadowCoord.y * size < size - PixelMargin && shadowCoord.z < (1. - DepthMargin))
{
const float depthBufferValue = shadowmap.Sample(PassSrg::LinearSampler, float3(shadowCoord.xy, indexOfCascade)).r;
const float deltaDepth = abs(shadowCoord.z - depthBufferValue);
// Normalized thickness (avoid negative values given by precision errors or shrinking offsets)
const float deltaDepth = max(shadowCoord.z - depthBufferValue,0.0);
const float viewSpaceThickness = ViewSrg::m_directionalLightShadows[lightIndex].m_far_minus_near * deltaDepth;
return viewSpaceThickness;
}

@ -275,7 +275,8 @@ float ProjectedShadow::GetThickness()
/*LOD=*/0
).r;
const float viewSpaceThickness = abs(UnprojectDepth(m_shadowIndex, m_shadowPosition.z) - UnprojectDepth(m_shadowIndex, depthValue));
// Denormalized thickness (avoid negative values given by precision errors or shrinking offsets)
const float viewSpaceThickness = max(UnprojectDepth(m_shadowIndex, depthValue) - UnprojectDepth(m_shadowIndex, m_shadowPosition.z), 0.0);
return viewSpaceThickness;
}

@ -100,7 +100,8 @@ namespace AZ
//! Sets all of the the disk data for the provided LightHandle.
virtual void SetDiskData(LightHandle handle, const DiskLightData& data) = 0;
//! Get a read only copy of a disk lights data, useful for debug rendering
virtual const DiskLightData& GetDiskData(LightHandle handle) const = 0;
};
} // namespace Render
} // namespace AZ

@ -255,6 +255,13 @@ namespace AZ
UpdateShadow(handle);
}
const DiskLightData& DiskLightFeatureProcessor::GetDiskData(LightHandle handle) const
{
AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to DiskLightFeatureProcessor::GetDiskData().");
return m_diskLightData.GetData(handle.GetIndex());
}
const Data::Instance<RPI::Buffer> DiskLightFeatureProcessor::GetLightBuffer()const
{
return m_lightBufferHandler.GetBuffer();

@ -58,6 +58,7 @@ namespace AZ
void SetEsmExponent(LightHandle handle, float esmExponent) override;
void SetDiskData(LightHandle handle, const DiskLightData& data) override;
const DiskLightData& GetDiskData(LightHandle handle) const override;
const Data::Instance<RPI::Buffer> GetLightBuffer()const;
uint32_t GetLightCount()const;

@ -26,6 +26,9 @@ namespace AZ
->Field("m_power", &SubsurfaceTransmissionParameterFunctor::m_power)
->Field("m_distortion", &SubsurfaceTransmissionParameterFunctor::m_distortion)
->Field("m_attenuation", &SubsurfaceTransmissionParameterFunctor::m_attenuation)
->Field("m_shrinkFactor", &SubsurfaceTransmissionParameterFunctor::m_shrinkFactor)
->Field("m_transmissionNdLBias", &SubsurfaceTransmissionParameterFunctor::m_transmissionNdLBias)
->Field("m_distanceAttenuation", &SubsurfaceTransmissionParameterFunctor::m_distanceAttenuation)
->Field("m_tintColor", &SubsurfaceTransmissionParameterFunctor::m_tintColor)
->Field("m_thickness", &SubsurfaceTransmissionParameterFunctor::m_thickness)
->Field("m_enabled", &SubsurfaceTransmissionParameterFunctor::m_enabled)
@ -50,6 +53,9 @@ namespace AZ
auto power = context.GetMaterialPropertyValue<float>(m_power);
auto distortion = context.GetMaterialPropertyValue<float>(m_distortion);
auto attenuation = context.GetMaterialPropertyValue<float>(m_attenuation);
auto shrinkFactor = context.GetMaterialPropertyValue<float>(m_shrinkFactor);
auto transmissionNdLBias = context.GetMaterialPropertyValue<float>(m_transmissionNdLBias);
auto distanceAttenuation = context.GetMaterialPropertyValue<float>(m_distanceAttenuation);
auto tintColor = context.GetMaterialPropertyValue<Color>(m_tintColor);
auto thickness = context.GetMaterialPropertyValue<float>(m_thickness);
auto scatterDistanceColor = context.GetMaterialPropertyValue<Color>(m_scatterDistanceColor);
@ -67,7 +73,9 @@ namespace AZ
}
else
{
transmissionParams.Set(scatterDistance);
transmissionParams.SetX(shrinkFactor);
transmissionParams.SetY(transmissionNdLBias);
transmissionParams.SetZ(distanceAttenuation);
transmissionParams.SetW(scale);
}

@ -37,6 +37,9 @@ namespace AZ
RPI::MaterialPropertyIndex m_power;
RPI::MaterialPropertyIndex m_distortion;
RPI::MaterialPropertyIndex m_attenuation;
RPI::MaterialPropertyIndex m_shrinkFactor;
RPI::MaterialPropertyIndex m_transmissionNdLBias;
RPI::MaterialPropertyIndex m_distanceAttenuation;
RPI::MaterialPropertyIndex m_tintColor;
RPI::MaterialPropertyIndex m_thickness;
RPI::MaterialPropertyIndex m_enabled;

@ -25,6 +25,9 @@ namespace AZ
->Field("power", &SubsurfaceTransmissionParameterFunctorSourceData::m_power)
->Field("distortion", &SubsurfaceTransmissionParameterFunctorSourceData::m_distortion)
->Field("attenuation", &SubsurfaceTransmissionParameterFunctorSourceData::m_attenuation)
->Field("shrinkFactor", &SubsurfaceTransmissionParameterFunctorSourceData::m_shrinkFactor)
->Field("transmissionNdLBias", &SubsurfaceTransmissionParameterFunctorSourceData::m_transmissionNdLBias)
->Field("distanceAttenuation", &SubsurfaceTransmissionParameterFunctorSourceData::m_distanceAttenuation)
->Field("tintColor", &SubsurfaceTransmissionParameterFunctorSourceData::m_tintColor)
->Field("thickness", &SubsurfaceTransmissionParameterFunctorSourceData::m_thickness)
->Field("enabled", &SubsurfaceTransmissionParameterFunctorSourceData::m_enabled)
@ -48,6 +51,9 @@ namespace AZ
functor->m_power = context.FindMaterialPropertyIndex(Name{ m_power });
functor->m_distortion = context.FindMaterialPropertyIndex(Name{ m_distortion });
functor->m_attenuation = context.FindMaterialPropertyIndex(Name{ m_attenuation });
functor->m_shrinkFactor = context.FindMaterialPropertyIndex(Name{ m_shrinkFactor });
functor->m_transmissionNdLBias = context.FindMaterialPropertyIndex(Name{ m_transmissionNdLBias });
functor->m_distanceAttenuation = context.FindMaterialPropertyIndex(Name{ m_distanceAttenuation });
functor->m_tintColor = context.FindMaterialPropertyIndex(Name{ m_tintColor });
functor->m_thickness = context.FindMaterialPropertyIndex(Name{ m_thickness });
functor->m_enabled = context.FindMaterialPropertyIndex(Name{ m_enabled });
@ -56,7 +62,8 @@ namespace AZ
if (functor->m_mode.IsNull() || functor->m_scale.IsNull() || functor->m_power.IsNull() || functor->m_distortion.IsNull() ||
functor->m_tintColor.IsNull() || functor->m_thickness.IsNull() || functor->m_enabled.IsNull() || functor->m_attenuation.IsNull() || functor->m_scatterDistanceColor.IsNull() ||
functor->m_scatterDistanceIntensity.IsNull())
functor->m_scatterDistanceIntensity.IsNull() || functor->m_shrinkFactor.IsNull() || functor->m_transmissionNdLBias.IsNull() ||
functor->m_distanceAttenuation.IsNull())
{
return Failure();
}
@ -66,6 +73,9 @@ namespace AZ
AddMaterialPropertyDependency(functor, functor->m_power);
AddMaterialPropertyDependency(functor, functor->m_distortion);
AddMaterialPropertyDependency(functor, functor->m_attenuation);
AddMaterialPropertyDependency(functor, functor->m_shrinkFactor);
AddMaterialPropertyDependency(functor, functor->m_transmissionNdLBias);
AddMaterialPropertyDependency(functor, functor->m_distanceAttenuation);
AddMaterialPropertyDependency(functor, functor->m_tintColor);
AddMaterialPropertyDependency(functor, functor->m_thickness);
AddMaterialPropertyDependency(functor, functor->m_enabled);

@ -36,6 +36,9 @@ namespace AZ
AZStd::string m_power; //!< material property for thick transmission power
AZStd::string m_distortion; //!< material property for thick transmission distortion towards surface normal
AZStd::string m_attenuation; //!< material property for thick transmission volume absorption
AZStd::string m_shrinkFactor; //!< material property for thin transmission position shrink factor towards surface normal
AZStd::string m_transmissionNdLBias; //!< material property for thin transmission bias of the NdL value
AZStd::string m_distanceAttenuation; //!< material property for thin transmission attenuation with distance
AZStd::string m_tintColor; //!< material property for transmission tint
AZStd::string m_thickness; //!< material property for normalized object thickness
AZStd::string m_enabled; //!< material property for subsurface scattering feature switch (enabled or disabled)

@ -23,7 +23,7 @@ namespace UnitTest
AZStd::unordered_map<uint64_t, const AZ::RHI::PipelineState*> m_pipelineStates;
private:
AZ::RHI::ResultCode InitInternal(AZ::RHI::Device&, const RHI::PipelineLibraryDescriptor&) override { return AZ::RHI::ResultCode::Success; }
AZ::RHI::ResultCode InitInternal(AZ::RHI::Device&, const AZ::RHI::PipelineLibraryDescriptor&) override { return AZ::RHI::ResultCode::Success; }
void ShutdownInternal() override;
AZ::RHI::ResultCode MergeIntoInternal(AZStd::span<const AZ::RHI::PipelineLibrary* const>) override;
AZ::RHI::ConstPtr<AZ::RHI::PipelineLibraryData> GetSerializedDataInternal() const override { return nullptr; }

@ -184,8 +184,8 @@ namespace AZ
virtual void DrawDisk(const AZ::Vector3& center, const AZ::Vector3& direction, float radius, const AZ::Color& color, DrawStyle style = DrawStyle::Shaded, DepthTest depthTest = DepthTest::On, DepthWrite depthWrite = DepthWrite::On, FaceCullMode faceCull = FaceCullMode::Back, int32_t viewProjOverrideIndex = -1) = 0;
//! Draw a cone.
//! @param center The center of the base circle.
//! @param direction The direction vector. The tip of the cone will point along this vector.
//! @param center The center of the cone base.
//! @param direction The direction vector. This is the vector from the center of the base to the point at the tip.
//! @param radius The radius.
//! @param height The height of the cone (the distance from the base center to the tip).
//! @param color The color to draw the cone.

@ -0,0 +1,65 @@
/*
* 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
*
*/
#pragma once
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
class QWidget;
class QMenu;
class QAction;
namespace AzToolsFramework
{
namespace AssetBrowser
{
class AssetBrowserEntry;
} // namespace AssetBrowser
} // namespace AzToolsFramework
namespace AtomToolsFramework
{
//! Provides common asset browser interactions, source control integration, and functionality to add custom menu actions
class AtomToolsAssetBrowserInteractions : public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(AtomToolsAssetBrowserInteractions, AZ::SystemAllocator, 0);
AtomToolsAssetBrowserInteractions();
~AtomToolsAssetBrowserInteractions();
using AssetBrowserEntryVector = AZStd::vector<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>;
using FilterCallback = AZStd::function<bool(const AssetBrowserEntryVector&)>;
using ActionCallback = AZStd::function<void(QWidget* caller, QMenu* menu, const AssetBrowserEntryVector&)>;
//! Add a filter and handler for custom context menu entries that will be added to the top of the context menu
void RegisterContextMenuActions(const FilterCallback& filterCallback, const ActionCallback& actionCallback);
private:
//! AssetBrowserInteractionNotificationBus::Handler overrides...
void AddContextMenuActions(QWidget* caller, QMenu* menu, const AssetBrowserEntryVector& entries) override;
void AddContextMenuActionsForSourceEntries(
QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry);
void AddContextMenuActionsForFolderEntries(
QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry);
void AddContextMenuActionsForAllEntries(
QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry);
void AddContextMenuActionsForSourceControl(
QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry);
void UpdateContextMenuActionsForSourceControl(bool success, AzToolsFramework::SourceControlFileInfo info);
QWidget* m_caller = {};
QAction* m_addAction = {};
QAction* m_checkOutAction = {};
QAction* m_undoCheckOutAction = {};
QAction* m_getLatestAction = {};
AZStd::vector<AZStd::pair<FilterCallback, ActionCallback>> m_contextMenuCallbacks;
};
} // namespace AtomToolsFramework

@ -1,30 +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
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/Memory/Memory.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/UserSettings/UserSettings.h>
#endif
namespace AtomToolsFramework
{
struct AtomToolsDocumentSystemSettings
: public AZ::UserSettings
{
AZ_RTTI(AtomToolsDocumentSystemSettings, "{9E576D4F-A74A-4326-9135-C07284D0A3B9}", AZ::UserSettings);
AZ_CLASS_ALLOCATOR(AtomToolsDocumentSystemSettings, AZ::SystemAllocator, 0);
static void Reflect(AZ::ReflectContext* context);
bool m_showReloadDocumentPrompt = true;
};
} // namespace AtomToolsFramework

@ -189,8 +189,9 @@ namespace AtomToolsFramework
AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast(
&AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized);
const bool enableSourceControl = GetSettingOrDefault("/O3DE/AtomToolsFramework/Application/EnableSourceControl", true);
AzToolsFramework::SourceControlConnectionRequestBus::Broadcast(
&AzToolsFramework::SourceControlConnectionRequests::EnableSourceControl, true);
&AzToolsFramework::SourceControlConnectionRequests::EnableSourceControl, enableSourceControl);
if (!AZ::RPI::RPISystemInterface::Get()->IsInitialized())
{

@ -8,6 +8,7 @@
#include <AssetBrowser/ui_AtomToolsAssetBrowser.h>
#include <AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowser.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
@ -103,8 +104,12 @@ namespace AtomToolsFramework
{
const AZStd::vector<AssetBrowserEntry*> entries = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
const int multiSelectPromptThreshold = 10;
if (entries.size() >= multiSelectPromptThreshold)
const bool promptToOpenMultipleFiles =
GetSettingOrDefault<bool>("/O3DE/AtomToolsFramework/AssetBrowser/PromptToOpenMultipleFiles", true);
const AZ::u64 promptToOpenMultipleFilesThreshold =
GetSettingOrDefault<AZ::u64>("/O3DE/AtomToolsFramework/AssetBrowser/PromptToOpenMultipleFilesThreshold", 10);
if (promptToOpenMultipleFiles && promptToOpenMultipleFilesThreshold <= entries.size())
{
QMessageBox::StandardButton result = QMessageBox::question(
QApplication::activeWindow(),

@ -7,44 +7,47 @@
*/
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowserInteractions.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzCore/Utils/Utils.h>
#include <AzCore/std/string/wildcard.h>
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/Thumbnails/SourceControlThumbnail.h>
#include <Window/CreateMaterialDialog/CreateMaterialDialog.h>
#include <Window/MaterialEditorBrowserInteractions.h>
#include <QApplication>
#include <QClipboard>
#include <QDesktopServices>
#include <QDir>
#include <QFileDialog>
#include <QFileInfo>
#include <QInputDialog>
#include <QMenu>
#include <QMessageBox>
namespace MaterialEditor
namespace AtomToolsFramework
{
MaterialEditorBrowserInteractions::MaterialEditorBrowserInteractions()
AtomToolsAssetBrowserInteractions::AtomToolsAssetBrowserInteractions()
{
using namespace AzToolsFramework::AssetBrowser;
AssetBrowserInteractionNotificationBus::Handler::BusConnect();
}
MaterialEditorBrowserInteractions::~MaterialEditorBrowserInteractions()
AtomToolsAssetBrowserInteractions::~AtomToolsAssetBrowserInteractions()
{
AssetBrowserInteractionNotificationBus::Handler::BusDisconnect();
}
void MaterialEditorBrowserInteractions::AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>& entries)
void AtomToolsAssetBrowserInteractions::RegisterContextMenuActions(
const FilterCallback& filterCallback, const ActionCallback& actionCallback)
{
m_contextMenuCallbacks.emplace_back(filterCallback, actionCallback);
}
void AtomToolsAssetBrowserInteractions::AddContextMenuActions(
QWidget* caller, QMenu* menu, const AssetBrowserEntryVector& entries)
{
AssetBrowserEntry* entry = entries.empty() ? nullptr : entries.front();
if (!entry)
@ -53,79 +56,33 @@ namespace MaterialEditor
}
m_caller = caller;
QObject::connect(m_caller, &QObject::destroyed, [this]()
{
m_caller = nullptr;
});
AddGenericContextMenuActions(caller, menu, entry);
QObject::connect(m_caller, &QObject::destroyed, [this]() { m_caller = nullptr; });
if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source)
// Add all of the custom context menu entries first
for (const auto& contextMenuCallbackPair : m_contextMenuCallbacks)
{
const auto source = azalias_cast<const SourceAssetBrowserEntry*>(entry);
if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialSourceData::Extension))
{
AddContextMenuActionsForMaterialSource(caller, menu, source);
}
else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialTypeSourceData::Extension))
if (contextMenuCallbackPair.first(entries))
{
AddContextMenuActionsForMaterialTypeSource(caller, menu, source);
}
else
{
AddContextMenuActionsForOtherSource(caller, menu, source);
contextMenuCallbackPair.second(caller, menu, entries);
}
}
if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source)
{
AddContextMenuActionsForSourceEntries(caller, menu, entry);
}
else if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder)
{
const auto folder = azalias_cast<const FolderAssetBrowserEntry*>(entry);
AddContextMenuActionsForFolder(caller, menu, folder);
AddContextMenuActionsForFolderEntries(caller, menu, entry);
}
}
void MaterialEditorBrowserInteractions::AddGenericContextMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
{
menu->addAction(QObject::tr("Copy Name To Clipboard"), [=]()
{
QApplication::clipboard()->setText(entry->GetName().c_str());
});
menu->addAction(QObject::tr("Copy Path To Clipboard"), [=]()
{
QApplication::clipboard()->setText(entry->GetFullPath().c_str());
});
AddContextMenuActionsForAllEntries(caller, menu, entry);
AddContextMenuActionsForSourceControl(caller, menu, entry);
}
void MaterialEditorBrowserInteractions::AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry)
void AtomToolsAssetBrowserInteractions::AddContextMenuActionsForSourceEntries(
[[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
{
menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]()
{
AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str());
});
menu->addSeparator();
menu->addAction("Create Material...", [entry]()
{
const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo(
QString(AZ::Utils::GetProjectPath().c_str()) +
AZ_CORRECT_FILESYSTEM_SEPARATOR + "Assets" +
AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." +
AZ::RPI::MaterialSourceData::Extension).absoluteFilePath();
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile,
entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData());
});
AddPerforceMenuActions(caller, menu, entry);
}
void MaterialEditorBrowserInteractions::AddContextMenuActionsForOtherSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry)
{
menu->addAction("Open", [entry]()
{
QDesktopServices::openUrl(QUrl::fromLocalFile(entry->GetFullPath().c_str()));
});
menu->addAction("Duplicate...", [entry]()
{
const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str()));
@ -142,79 +99,26 @@ namespace MaterialEditor
}
});
menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]()
{
AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str());
});
AddPerforceMenuActions(caller, menu, entry);
}
void MaterialEditorBrowserInteractions::AddContextMenuActionsForMaterialSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry)
{
menu->addAction("Open", [entry]()
{
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath());
});
menu->addAction("Duplicate...", [entry]()
{
const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str()));
if (!duplicateFileInfo.absoluteFilePath().isEmpty())
menu->addAction("Run Python on File...", [caller, entry]()
{
const QString script = QFileDialog::getOpenFileName(
caller, QObject::tr("Run Script"), QString(AZ::Utils::GetProjectPath().c_str()), QString("*.py"));
if (!script.isEmpty())
{
if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath()))
{
QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther);
// Auto add file to source control
AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit,
duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {});
}
AZStd::vector<AZStd::string_view> pythonArgs{ entry->GetFullPath() };
AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast(
&AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs, script.toUtf8().constData(),
pythonArgs);
}
});
menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]()
{
AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str());
});
menu->addSeparator();
menu->addAction("Create Child Material...", [entry]()
{
const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo(
QString(AZ::Utils::GetProjectPath().c_str()) +
AZ_CORRECT_FILESYSTEM_SEPARATOR + "Assets" +
AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." +
AZ::RPI::MaterialSourceData::Extension).absoluteFilePath();
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile,
entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData());
});
menu->addSeparator();
QAction* openParentAction = menu->addAction("Open Parent Material", [entry]()
{
AZ_UNUSED(entry);
// ToDo
});
openParentAction->setEnabled(false);
AddPerforceMenuActions(caller, menu, entry);
}
void MaterialEditorBrowserInteractions::AddContextMenuActionsForFolder(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::FolderAssetBrowserEntry* entry)
void AtomToolsAssetBrowserInteractions::AddContextMenuActionsForFolderEntries(
QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
{
menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]()
menu->addAction(QObject::tr("Create new sub folder..."), [caller, entry]()
{
AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str());
});
QAction* createFolderAction = menu->addAction(QObject::tr("Create new sub folder..."));
QObject::connect(createFolderAction, &QAction::triggered, caller, [caller, entry]()
{
bool ok;
bool ok = false;
QString newFolderName = QInputDialog::getText(caller, "Enter new folder name", "name:", QLineEdit::Normal, "NewFolder", &ok);
if (ok)
{
@ -242,27 +146,29 @@ namespace MaterialEditor
}
}
});
}
menu->addSeparator();
QAction* createMaterialAction = menu->addAction(QObject::tr("Create Material..."));
QObject::connect(createMaterialAction, &QAction::triggered, caller, [caller, entry]()
void AtomToolsAssetBrowserInteractions::AddContextMenuActionsForAllEntries(
[[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
{
menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]()
{
CreateMaterialDialog createDialog(entry->GetFullPath().c_str(), caller);
createDialog.adjustSize();
AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str());
});
if (createDialog.exec() == QDialog::Accepted &&
!createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() &&
!createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty())
{
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::CreateDocumentFromFile,
createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData(),
createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData());
}
menu->addSeparator();
menu->addAction(QObject::tr("Copy Name To Clipboard"), [=]()
{
QApplication::clipboard()->setText(entry->GetName().c_str());
});
menu->addAction(QObject::tr("Copy Path To Clipboard"), [=]()
{
QApplication::clipboard()->setText(entry->GetFullPath().c_str());
});
}
void MaterialEditorBrowserInteractions::AddPerforceMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
void AtomToolsAssetBrowserInteractions::AddContextMenuActionsForSourceControl(
[[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry)
{
using namespace AzToolsFramework;
@ -282,7 +188,7 @@ namespace MaterialEditor
QMenu::connect(sourceControlMenu, &QMenu::aboutToShow, [this, path]()
{
SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::GetFileInfo, path.c_str(),
[this](bool success, const SourceControlFileInfo& info) { UpdateSourceControlActions(success, info); });
[this](bool success, const SourceControlFileInfo& info) { UpdateContextMenuActionsForSourceControl(success, info); });
});
// add get latest action
@ -344,7 +250,7 @@ namespace MaterialEditor
}
}
void MaterialEditorBrowserInteractions::UpdateSourceControlActions(bool success, AzToolsFramework::SourceControlFileInfo info)
void AtomToolsAssetBrowserInteractions::UpdateContextMenuActionsForSourceControl(bool success, AzToolsFramework::SourceControlFileInfo info)
{
if (!success && m_caller)
{
@ -367,4 +273,4 @@ namespace MaterialEditor
m_undoCheckOutAction->setEnabled(info.IsManaged() && !info.IsReadOnly());
}
}
} // namespace MaterialEditor
} // namespace AtomToolsFramework

@ -10,7 +10,6 @@
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
@ -35,8 +34,6 @@ namespace AtomToolsFramework
void AtomToolsDocumentSystemComponent::Reflect(AZ::ReflectContext* context)
{
AtomToolsDocumentSystemSettings::Reflect(context);
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
serialize->Class<AtomToolsDocumentSystemComponent, AZ::Component>()
@ -113,7 +110,6 @@ namespace AtomToolsFramework
void AtomToolsDocumentSystemComponent::Activate()
{
m_documentMap.clear();
m_settings = AZ::UserSettings::CreateFind<AtomToolsDocumentSystemSettings>(AZ_CRC_CE("AtomToolsDocumentSystemSettings"), AZ::UserSettings::CT_GLOBAL);
AtomToolsDocumentSystemRequestBus::Handler::BusConnect();
AtomToolsDocumentNotificationBus::Handler::BusConnect();
}
@ -178,6 +174,17 @@ namespace AtomToolsFramework
void AtomToolsDocumentSystemComponent::ReopenDocuments()
{
const bool enableHotReload = GetSettingOrDefault<bool>("/O3DE/AtomToolsFramework/DocumentSystem/EnableHotReload", true);
if (!enableHotReload)
{
m_documentIdsWithDependencyChanges.clear();
m_documentIdsWithExternalChanges.clear();
m_queueReopenDocuments = false;
}
const bool enableHotReloadPrompts =
GetSettingOrDefault<bool>("/O3DE/AtomToolsFramework/DocumentSystem/EnableHotReloadPrompts", true);
for (const AZ::Uuid& documentId : m_documentIdsWithExternalChanges)
{
m_documentIdsWithDependencyChanges.erase(documentId);
@ -185,7 +192,7 @@ namespace AtomToolsFramework
AZStd::string documentPath;
AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (m_settings->m_showReloadDocumentPrompt &&
if (enableHotReloadPrompts &&
(QMessageBox::question(QApplication::activeWindow(),
QString("Document was externally modified"),
QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()),
@ -212,7 +219,7 @@ namespace AtomToolsFramework
AZStd::string documentPath;
AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (m_settings->m_showReloadDocumentPrompt &&
if (enableHotReloadPrompts &&
(QMessageBox::question(QApplication::activeWindow(),
QString("Document dependencies have changed"),
QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()),

@ -15,7 +15,6 @@
#include <AtomToolsFramework/Document/AtomToolsDocument.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QFileInfo>
@ -79,7 +78,6 @@ namespace AtomToolsFramework
AZ::Uuid OpenDocumentImpl(AZStd::string_view sourcePath, bool checkIfAlreadyOpen);
AZStd::intrusive_ptr<AtomToolsDocumentSystemSettings> m_settings;
AZStd::function<AtomToolsDocument*()> m_documentCreator;
AZStd::unordered_map<AZ::Uuid, AZStd::shared_ptr<AtomToolsDocument>> m_documentMap;
AZStd::unordered_set<AZ::Uuid> m_documentIdsWithExternalChanges;

@ -1,47 +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
*
*/
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
namespace AtomToolsFramework
{
void AtomToolsDocumentSystemSettings::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<AtomToolsDocumentSystemSettings, AZ::UserSettings>()
->Version(1)
->Field("showReloadDocumentPrompt", &AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<AtomToolsDocumentSystemSettings>(
"AtomToolsDocumentSystemSettings", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt, "Show Reload Document Prompt", "")
;
}
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<AtomToolsDocumentSystemSettings>("AtomToolsDocumentSystemSettings")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "atomtools")
->Constructor()
->Constructor<const AtomToolsDocumentSystemSettings&>()
->Property("showReloadDocumentPrompt", BehaviorValueProperty(&AtomToolsDocumentSystemSettings::m_showReloadDocumentPrompt))
;
}
}
} // namespace AtomToolsFramework

@ -9,6 +9,7 @@
set(FILES
Include/AtomToolsFramework/Application/AtomToolsApplication.h
Include/AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowser.h
Include/AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowserInteractions.h
Include/AtomToolsFramework/AssetGridDialog/AssetGridDialog.h
Include/AtomToolsFramework/Communication/LocalServer.h
Include/AtomToolsFramework/Communication/LocalSocket.h
@ -16,7 +17,6 @@ set(FILES
Include/AtomToolsFramework/Document/AtomToolsDocument.h
Include/AtomToolsFramework/Document/AtomToolsDocumentApplication.h
Include/AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h
Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h
Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h
Include/AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h
Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h
@ -44,6 +44,7 @@ set(FILES
Source/AssetBrowser/AtomToolsAssetBrowser.cpp
Source/AssetBrowser/AtomToolsAssetBrowser.qrc
Source/AssetBrowser/AtomToolsAssetBrowser.ui
Source/AssetBrowser/AtomToolsAssetBrowserInteractions.cpp
Source/AssetGridDialog/AssetGridDialog.cpp
Source/AssetGridDialog/AssetGridDialog.ui
Source/Communication/LocalServer.cpp
@ -52,7 +53,6 @@ set(FILES
Source/Document/AtomToolsDocument.cpp
Source/Document/AtomToolsDocumentApplication.cpp
Source/Document/AtomToolsDocumentMainWindow.cpp
Source/Document/AtomToolsDocumentSystemSettings.cpp
Source/Document/AtomToolsDocumentSystemComponent.cpp
Source/Document/AtomToolsDocumentSystemComponent.h
Source/DynamicProperty/DynamicProperty.cpp

@ -1,47 +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
*
*/
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <Document/MaterialDocumentSettings.h>
namespace MaterialEditor
{
void MaterialDocumentSettings::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<MaterialDocumentSettings, AZ::UserSettings>()
->Version(1)
->Field("defaultMaterialTypeName", &MaterialDocumentSettings::m_defaultMaterialTypeName)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<MaterialDocumentSettings>(
"MaterialDocumentSettings", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialDocumentSettings::m_defaultMaterialTypeName, "Default Material Type Name", "")
;
}
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<MaterialDocumentSettings>("MaterialDocumentSettings")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Category, "Editor")
->Attribute(AZ::Script::Attributes::Module, "materialeditor")
->Constructor()
->Constructor<const MaterialDocumentSettings&>()
->Property("defaultMaterialTypeName", BehaviorValueProperty(&MaterialDocumentSettings::m_defaultMaterialTypeName))
;
}
}
} // namespace MaterialEditor

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

Loading…
Cancel
Save