Merge branch 'development' into MuteAudioButtonMightBeBroken
Signed-off-by: John Jones-Steele <jjjoness@amazon.com>
This commit is contained in:
+5
-5
@@ -6,13 +6,13 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import psutil
|
||||||
|
|
||||||
import ly_test_tools.log.log_monitor
|
import ly_test_tools.log.log_monitor
|
||||||
import ly_test_tools.environment.process_utils as process_utils
|
import ly_test_tools.environment.process_utils as process_utils
|
||||||
import ly_test_tools.environment.waiter as waiter
|
import ly_test_tools.environment.waiter as waiter
|
||||||
from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole
|
|
||||||
from ly_remote_console.remote_console_commands import send_command_and_expect_response as send_command_and_expect_response
|
from ly_remote_console.remote_console_commands import send_command_and_expect_response as send_command_and_expect_response
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ def launch_and_validate_results_launcher(launcher, level, remote_console_instanc
|
|||||||
return port_listening
|
return port_listening
|
||||||
|
|
||||||
if null_renderer:
|
if null_renderer:
|
||||||
launcher.args.extend(["-NullRenderer"])
|
launcher.args.extend(["-rhi=Null"])
|
||||||
|
|
||||||
# Start the Launcher
|
# Start the Launcher
|
||||||
with launcher.start():
|
with launcher.start():
|
||||||
@@ -110,8 +110,8 @@ def launch_and_validate_results_launcher(launcher, level, remote_console_instanc
|
|||||||
|
|
||||||
# Load the specified level in the launcher
|
# Load the specified level in the launcher
|
||||||
send_command_and_expect_response(remote_console_instance,
|
send_command_and_expect_response(remote_console_instance,
|
||||||
f"map {level}",
|
f"LoadLevel {level}",
|
||||||
"LEVEL_LOAD_COMPLETE", timeout=30)
|
"LEVEL_LOAD_END", timeout=30)
|
||||||
|
|
||||||
# Monitor the console for expected lines
|
# Monitor the console for expected lines
|
||||||
for line in expected_lines:
|
for line in expected_lines:
|
||||||
|
|||||||
+3
-21
@@ -36,8 +36,8 @@ class TestAltitudeFilterFilterStageToggle(EditorTestHelper):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
PREPROCESS_INSTANCE_COUNT = 24
|
PREPROCESS_INSTANCE_COUNT = 44
|
||||||
POSTPROCESS_INSTANCE_COUNT = 18
|
POSTPROCESS_INSTANCE_COUNT = 34
|
||||||
|
|
||||||
# Create empty level
|
# Create empty level
|
||||||
self.test_success = self.create_level(
|
self.test_success = self.create_level(
|
||||||
@@ -62,25 +62,7 @@ class TestAltitudeFilterFilterStageToggle(EditorTestHelper):
|
|||||||
dynveg.create_surface_entity("Surface_Entity_Parent", position, 16.0, 16.0, 1.0)
|
dynveg.create_surface_entity("Surface_Entity_Parent", position, 16.0, 16.0, 1.0)
|
||||||
|
|
||||||
# Add entity with Mesh to replicate creation of hills
|
# Add entity with Mesh to replicate creation of hills
|
||||||
hill_entity = dynveg.create_mesh_surface_entity_with_slopes("hill", position, 40.0, 40.0, 40.0)
|
hill_entity = dynveg.create_mesh_surface_entity_with_slopes("hill", position, 10.0)
|
||||||
|
|
||||||
# Disable/Re-enable Mesh component due to ATOM-14299
|
|
||||||
general.idle_wait(1.0)
|
|
||||||
editor.EditorComponentAPIBus(bus.Broadcast, 'DisableComponents', [hill_entity.components[0]])
|
|
||||||
is_enabled = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', hill_entity.components[0])
|
|
||||||
if is_enabled:
|
|
||||||
print("Mesh component is still enabled")
|
|
||||||
else:
|
|
||||||
print("Mesh component was disabled")
|
|
||||||
editor.EditorComponentAPIBus(bus.Broadcast, 'EnableComponents', [hill_entity.components[0]])
|
|
||||||
is_enabled = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', hill_entity.components[0])
|
|
||||||
if is_enabled:
|
|
||||||
print("Mesh component is now enabled")
|
|
||||||
else:
|
|
||||||
print("Mesh component is still disabled")
|
|
||||||
|
|
||||||
# Increase Box Shape size to encompass the hills
|
|
||||||
vegetation.get_set_test(1, "Box Shape|Box Configuration|Dimensions", math.Vector3(100.0, 100.0, 100.0))
|
|
||||||
|
|
||||||
# Set a Min Altitude of 38 and Max of 40 in Vegetation Altitude Filter
|
# Set a Min Altitude of 38 and Max of 40 in Vegetation Altitude Filter
|
||||||
vegetation.get_set_test(3, "Configuration|Altitude Min", 38.0)
|
vegetation.get_set_test(3, "Configuration|Altitude Min", 38.0)
|
||||||
|
|||||||
+7
-12
@@ -9,9 +9,10 @@ import sys
|
|||||||
|
|
||||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||||
import azlmbr.asset as asset
|
import azlmbr.asset as asset
|
||||||
|
import azlmbr.components as components
|
||||||
import azlmbr.legacy.general as general
|
import azlmbr.legacy.general as general
|
||||||
import azlmbr.bus as bus
|
import azlmbr.bus as bus
|
||||||
import azlmbr.entity as EntityId
|
import azlmbr.entity as entity
|
||||||
import azlmbr.editor as editor
|
import azlmbr.editor as editor
|
||||||
import azlmbr.math as math
|
import azlmbr.math as math
|
||||||
import azlmbr.paths
|
import azlmbr.paths
|
||||||
@@ -83,18 +84,12 @@ class TestDynamicSliceInstanceSpawnerEmbeddedEditor(EditorTestHelper):
|
|||||||
self.log(f"Expected {num_expected_instances} instances - Found {num_found} instances")
|
self.log(f"Expected {num_expected_instances} instances - Found {num_found} instances")
|
||||||
self.test_success = self.test_success and num_found == num_expected_instances
|
self.test_success = self.test_success and num_found == num_expected_instances
|
||||||
|
|
||||||
# 5) Create a new entity with a Camera component for testing in the launcher
|
# 5) Move the default Camera entity for testing in the launcher
|
||||||
cam_position = math.Vector3(512.0, 500.0, 35.0)
|
cam_position = math.Vector3(512.0, 500.0, 35.0)
|
||||||
camera_component = ["Camera"]
|
search_filter = entity.SearchFilter()
|
||||||
new_entity_id2 = editor.ToolsApplicationRequestBus(
|
search_filter.names = ["Camera"]
|
||||||
bus.Broadcast, "CreateNewEntityAtPosition", cam_position, EntityId.EntityId()
|
search_entity_ids = entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)
|
||||||
)
|
components.TransformBus(bus.Event, "MoveEntity", search_entity_ids[0], cam_position)
|
||||||
if new_entity_id2.IsValid():
|
|
||||||
self.log("Camera entity created")
|
|
||||||
camera_entity = hydra.Entity("Camera Entity", new_entity_id2)
|
|
||||||
camera_entity.components = []
|
|
||||||
for component in camera_component:
|
|
||||||
camera_entity.components.append(hydra.add_component(component, new_entity_id2))
|
|
||||||
|
|
||||||
# 6) Save and export to engine
|
# 6) Save and export to engine
|
||||||
general.save_level()
|
general.save_level()
|
||||||
|
|||||||
+9
-14
@@ -11,7 +11,8 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|||||||
import azlmbr.legacy.general as general
|
import azlmbr.legacy.general as general
|
||||||
import azlmbr.asset as asset
|
import azlmbr.asset as asset
|
||||||
import azlmbr.bus as bus
|
import azlmbr.bus as bus
|
||||||
import azlmbr.entity as EntityId
|
import azlmbr.components as components
|
||||||
|
import azlmbr.entity as entity
|
||||||
import azlmbr.editor as editor
|
import azlmbr.editor as editor
|
||||||
import azlmbr.math as math
|
import azlmbr.math as math
|
||||||
import azlmbr.paths
|
import azlmbr.paths
|
||||||
@@ -68,7 +69,7 @@ class TestDynamicSliceInstanceSpawnerExternalEditor(EditorTestHelper):
|
|||||||
veg_area_required_components = ["Vegetation Layer Spawner", "Box Shape", "Vegetation Asset List",
|
veg_area_required_components = ["Vegetation Layer Spawner", "Box Shape", "Vegetation Asset List",
|
||||||
"Script Canvas"]
|
"Script Canvas"]
|
||||||
new_entity_id = editor.ToolsApplicationRequestBus(
|
new_entity_id = editor.ToolsApplicationRequestBus(
|
||||||
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
|
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, entity.EntityId()
|
||||||
)
|
)
|
||||||
if new_entity_id.IsValid():
|
if new_entity_id.IsValid():
|
||||||
self.log("Spawner entity created")
|
self.log("Spawner entity created")
|
||||||
@@ -106,18 +107,12 @@ class TestDynamicSliceInstanceSpawnerExternalEditor(EditorTestHelper):
|
|||||||
self.log(f"Expected {num_expected_instances} instances - Found {num_found} instances")
|
self.log(f"Expected {num_expected_instances} instances - Found {num_found} instances")
|
||||||
self.test_success = self.test_success and num_found == num_expected_instances
|
self.test_success = self.test_success and num_found == num_expected_instances
|
||||||
|
|
||||||
# 5) Create a new entity with a Camera component for testing in the launcher
|
# 5) Move the default Camera entity for testing in the launcher
|
||||||
entity_position = math.Vector3(512.0, 500.0, 35.0)
|
cam_position = math.Vector3(512.0, 500.0, 35.0)
|
||||||
camera_component = ["Camera"]
|
search_filter = entity.SearchFilter()
|
||||||
new_entity_id2 = editor.ToolsApplicationRequestBus(
|
search_filter.names = ["Camera"]
|
||||||
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
|
search_entity_ids = entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)
|
||||||
)
|
components.TransformBus(bus.Event, "MoveEntity", search_entity_ids[0], cam_position)
|
||||||
if new_entity_id2.IsValid():
|
|
||||||
self.log("Camera entity created")
|
|
||||||
camera_entity = hydra.Entity("Camera Entity", new_entity_id2)
|
|
||||||
camera_entity.components = []
|
|
||||||
for component in camera_component:
|
|
||||||
camera_entity.components.append(hydra.add_component(component, new_entity_id2))
|
|
||||||
|
|
||||||
# 6) Save and export to engine
|
# 6) Save and export to engine
|
||||||
general.save_level()
|
general.save_level()
|
||||||
|
|||||||
+10
-16
@@ -18,9 +18,9 @@ import azlmbr.areasystem as areasystem
|
|||||||
import azlmbr.legacy.general as general
|
import azlmbr.legacy.general as general
|
||||||
import azlmbr
|
import azlmbr
|
||||||
import azlmbr.bus as bus
|
import azlmbr.bus as bus
|
||||||
import azlmbr.editor as editor
|
import azlmbr.components as components
|
||||||
import azlmbr.math as math
|
import azlmbr.math as math
|
||||||
import azlmbr.entity as EntityId
|
import azlmbr.entity as entity
|
||||||
import azlmbr.paths
|
import azlmbr.paths
|
||||||
|
|
||||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||||
@@ -134,20 +134,14 @@ class TestVegLayerBlenderCreated(EditorTestHelper):
|
|||||||
purple_count += 1
|
purple_count += 1
|
||||||
self.test_success = pink_count == purple_count and (pink_count + purple_count == num_expected) and self.test_success
|
self.test_success = pink_count == purple_count and (pink_count + purple_count == num_expected) and self.test_success
|
||||||
|
|
||||||
# 5) Create a new entity with a Camera component for testing in the launcher
|
# 5) Move the default Camera entity for testing in the launcher
|
||||||
entity_position = math.Vector3(500.0, 500.0, 47.0)
|
cam_position = math.Vector3(500.0, 500.0, 47.0)
|
||||||
rot_degrees_vector = math.Vector3(radians(-55.0), radians(28.5), radians(-17.0))
|
cam_rot_degrees_vector = math.Vector3(radians(-55.0), radians(28.5), radians(-17.0))
|
||||||
camera_component = ["Camera"]
|
search_filter = entity.SearchFilter()
|
||||||
camera_id = editor.ToolsApplicationRequestBus(
|
search_filter.names = ["Camera"]
|
||||||
bus.Broadcast, "CreateNewEntityAtPosition", entity_position, EntityId.EntityId()
|
search_entity_ids = entity.SearchBus(bus.Broadcast, 'SearchEntities', search_filter)
|
||||||
)
|
components.TransformBus(bus.Event, "MoveEntity", search_entity_ids[0], cam_position)
|
||||||
if camera_id.IsValid():
|
azlmbr.components.TransformBus(bus.Event, "SetLocalRotation", search_entity_ids[0], cam_rot_degrees_vector)
|
||||||
self.log("Camera entity created")
|
|
||||||
camera_entity = hydra.Entity("Camera Entity", camera_id)
|
|
||||||
camera_entity.components = []
|
|
||||||
for component in camera_component:
|
|
||||||
camera_entity.components.append(hydra.add_component(component, camera_id))
|
|
||||||
azlmbr.components.TransformBus(bus.Event, "SetLocalRotation", camera_id, rot_degrees_vector)
|
|
||||||
|
|
||||||
# 6) Save and export level
|
# 6) Save and export level
|
||||||
general.save_level()
|
general.save_level()
|
||||||
|
|||||||
+5
-22
@@ -34,8 +34,8 @@ class TestLayerSpawnerFilterStageToggle(EditorTestHelper):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
PREPROCESS_INSTANCE_COUNT = 425
|
PREPROCESS_INSTANCE_COUNT = 21
|
||||||
POSTPROCESS_INSTANCE_COUNT = 430
|
POSTPROCESS_INSTANCE_COUNT = 19
|
||||||
|
|
||||||
# Create empty level
|
# Create empty level
|
||||||
self.test_success = self.create_level(
|
self.test_success = self.create_level(
|
||||||
@@ -56,7 +56,6 @@ class TestLayerSpawnerFilterStageToggle(EditorTestHelper):
|
|||||||
vegetation_entity.add_component("Vegetation Altitude Filter")
|
vegetation_entity.add_component("Vegetation Altitude Filter")
|
||||||
vegetation_entity.add_component("Vegetation Position Modifier")
|
vegetation_entity.add_component("Vegetation Position Modifier")
|
||||||
|
|
||||||
|
|
||||||
# Create a child entity under vegetation area
|
# Create a child entity under vegetation area
|
||||||
child_entity = hydra.Entity("child_entity")
|
child_entity = hydra.Entity("child_entity")
|
||||||
components_to_add = ["Random Noise Gradient", "Gradient Transform Modifier", "Box Shape"]
|
components_to_add = ["Random Noise Gradient", "Gradient Transform Modifier", "Box Shape"]
|
||||||
@@ -66,29 +65,13 @@ class TestLayerSpawnerFilterStageToggle(EditorTestHelper):
|
|||||||
vegetation_entity.get_set_test(4, "Configuration|Position X|Gradient|Gradient Entity Id", child_entity.id)
|
vegetation_entity.get_set_test(4, "Configuration|Position X|Gradient|Gradient Entity Id", child_entity.id)
|
||||||
vegetation_entity.get_set_test(4, "Configuration|Position Y|Gradient|Gradient Entity Id", child_entity.id)
|
vegetation_entity.get_set_test(4, "Configuration|Position Y|Gradient|Gradient Entity Id", child_entity.id)
|
||||||
|
|
||||||
|
|
||||||
# Set the min and max values for Altitude Filter
|
# Set the min and max values for Altitude Filter
|
||||||
vegetation_entity.get_set_test(3, "Configuration|Altitude Min", 32.0)
|
vegetation_entity.get_set_test(3, "Configuration|Altitude Min", 34.0)
|
||||||
vegetation_entity.get_set_test(3, "Configuration|Altitude Max", 35.0)
|
vegetation_entity.get_set_test(3, "Configuration|Altitude Max", 38.0)
|
||||||
|
|
||||||
# Add entity with Mesh to replicate creation of hills and a flat surface to plant on
|
# Add entity with Mesh to replicate creation of hills and a flat surface to plant on
|
||||||
dynveg.create_surface_entity("Flat Surface", position, 32.0, 32.0, 1.0)
|
dynveg.create_surface_entity("Flat Surface", position, 32.0, 32.0, 1.0)
|
||||||
hill_entity = dynveg.create_mesh_surface_entity_with_slopes("hill", position, 4.0, 4.0, 4.0)
|
hill_entity = dynveg.create_mesh_surface_entity_with_slopes("hill", position, 4.0)
|
||||||
|
|
||||||
# Disable/Re-enable Mesh component due to ATOM-14299
|
|
||||||
general.idle_wait(1.0)
|
|
||||||
editor.EditorComponentAPIBus(bus.Broadcast, 'DisableComponents', [hill_entity.components[0]])
|
|
||||||
is_enabled = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', hill_entity.components[0])
|
|
||||||
if is_enabled:
|
|
||||||
print("Mesh component is still enabled")
|
|
||||||
else:
|
|
||||||
print("Mesh component was disabled")
|
|
||||||
editor.EditorComponentAPIBus(bus.Broadcast, 'EnableComponents', [hill_entity.components[0]])
|
|
||||||
is_enabled = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', hill_entity.components[0])
|
|
||||||
if is_enabled:
|
|
||||||
print("Mesh component is now enabled")
|
|
||||||
else:
|
|
||||||
print("Mesh component is still disabled")
|
|
||||||
|
|
||||||
# Set the filter stage to preprocess and postprocess respectively and verify instance count
|
# Set the filter stage to preprocess and postprocess respectively and verify instance count
|
||||||
vegetation_entity.get_set_test(0, "Configuration|Filter Stage", 1)
|
vegetation_entity.get_set_test(0, "Configuration|Filter Stage", 1)
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ import azlmbr.legacy.general as general
|
|||||||
import azlmbr.math as math
|
import azlmbr.math as math
|
||||||
|
|
||||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
from editor_python_test_tools.editor_test_helper import EditorTestHelper
|
||||||
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-16
@@ -82,22 +82,7 @@ class test_MeshBlocker_InstancesBlockedByMesh(EditorTestHelper):
|
|||||||
bus.Broadcast, "GetAssetIdByPath", os.path.join("objects", "_primitives", "_box_1x1.azmodel"), math.Uuid(),
|
bus.Broadcast, "GetAssetIdByPath", os.path.join("objects", "_primitives", "_box_1x1.azmodel"), math.Uuid(),
|
||||||
False)
|
False)
|
||||||
blocker_entity.get_set_test(1, "Controller|Configuration|Mesh Asset", cubeId)
|
blocker_entity.get_set_test(1, "Controller|Configuration|Mesh Asset", cubeId)
|
||||||
components.TransformBus(bus.Event, "SetLocalScale", blocker_entity.id, math.Vector3(2.0, 2.0, 2.0))
|
components.TransformBus(bus.Event, "SetLocalUniformScale", blocker_entity.id, 2.0)
|
||||||
|
|
||||||
# Disable/Re-enable Mesh component due to ATOM-14299
|
|
||||||
general.idle_wait(1.0)
|
|
||||||
editor.EditorComponentAPIBus(bus.Broadcast, 'DisableComponents', [blocker_entity.components[1]])
|
|
||||||
is_enabled = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', blocker_entity.components[1])
|
|
||||||
if is_enabled:
|
|
||||||
print("Mesh component is still enabled")
|
|
||||||
else:
|
|
||||||
print("Mesh component was disabled")
|
|
||||||
editor.EditorComponentAPIBus(bus.Broadcast, 'EnableComponents', [blocker_entity.components[1]])
|
|
||||||
is_enabled = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', blocker_entity.components[1])
|
|
||||||
if is_enabled:
|
|
||||||
print("Mesh component is now enabled")
|
|
||||||
else:
|
|
||||||
print("Mesh component is still disabled")
|
|
||||||
|
|
||||||
# Verify spawned instance counts are accurate after addition of Blocker Entity
|
# Verify spawned instance counts are accurate after addition of Blocker Entity
|
||||||
num_expected = 160 # Number of "PurpleFlower"s that plant on a 10 x 10 surface minus 2m blocker cube
|
num_expected = 160 # Number of "PurpleFlower"s that plant on a 10 x 10 surface minus 2m blocker cube
|
||||||
|
|||||||
+1
-16
@@ -88,24 +88,9 @@ class test_MeshBlocker_InstancesBlockedByMeshHeightTuning(EditorTestHelper):
|
|||||||
bus.Broadcast, "GetAssetIdByPath", os.path.join("objects", "_primitives", "_box_1x1.azmodel"), math.Uuid(),
|
bus.Broadcast, "GetAssetIdByPath", os.path.join("objects", "_primitives", "_box_1x1.azmodel"), math.Uuid(),
|
||||||
False)
|
False)
|
||||||
blocker_entity.get_set_test(1, "Controller|Configuration|Mesh Asset", sphere_id)
|
blocker_entity.get_set_test(1, "Controller|Configuration|Mesh Asset", sphere_id)
|
||||||
components.TransformBus(bus.Event, "SetLocalScale", blocker_entity.id, math.Vector3(5.0, 5.0, 5.0))
|
components.TransformBus(bus.Event, "SetLocalUniformScale", blocker_entity.id, 5.0)
|
||||||
components.TransformBus(bus.Event, "SetLocalRotation", blocker_entity.id, math.Vector3(0.0, y_rotation, 0.0))
|
components.TransformBus(bus.Event, "SetLocalRotation", blocker_entity.id, math.Vector3(0.0, y_rotation, 0.0))
|
||||||
|
|
||||||
# Disable/Re-enable Mesh component due to ATOM-14299
|
|
||||||
general.idle_wait(1.0)
|
|
||||||
editor.EditorComponentAPIBus(bus.Broadcast, 'DisableComponents', [blocker_entity.components[1]])
|
|
||||||
is_enabled = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', blocker_entity.components[1])
|
|
||||||
if is_enabled:
|
|
||||||
print("Mesh component is still enabled")
|
|
||||||
else:
|
|
||||||
print("Mesh component was disabled")
|
|
||||||
editor.EditorComponentAPIBus(bus.Broadcast, 'EnableComponents', [blocker_entity.components[1]])
|
|
||||||
is_enabled = editor.EditorComponentAPIBus(bus.Broadcast, 'IsComponentEnabled', blocker_entity.components[1])
|
|
||||||
if is_enabled:
|
|
||||||
print("Mesh component is now enabled")
|
|
||||||
else:
|
|
||||||
print("Mesh component is still disabled")
|
|
||||||
|
|
||||||
# 5) Adjust the height Max percentage values of blocker
|
# 5) Adjust the height Max percentage values of blocker
|
||||||
blocker_entity.get_set_test(0, "Configuration|Mesh Height Percent Max", 0.8)
|
blocker_entity.get_set_test(0, "Configuration|Mesh Height Percent Max", 0.8)
|
||||||
|
|
||||||
|
|||||||
-2
@@ -90,7 +90,6 @@ class TestDynamicSliceInstanceSpawner(object):
|
|||||||
@pytest.mark.SUITE_periodic
|
@pytest.mark.SUITE_periodic
|
||||||
@pytest.mark.dynveg_area
|
@pytest.mark.dynveg_area
|
||||||
@pytest.mark.parametrize("launcher_platform", ['windows'])
|
@pytest.mark.parametrize("launcher_platform", ['windows'])
|
||||||
@pytest.mark.skip # ATOM-14703
|
|
||||||
def test_DynamicSliceInstanceSpawner_Embedded_E2E_Launcher(self, workspace, launcher, level,
|
def test_DynamicSliceInstanceSpawner_Embedded_E2E_Launcher(self, workspace, launcher, level,
|
||||||
remote_console_instance, project, launcher_platform):
|
remote_console_instance, project, launcher_platform):
|
||||||
|
|
||||||
@@ -126,7 +125,6 @@ class TestDynamicSliceInstanceSpawner(object):
|
|||||||
@pytest.mark.SUITE_periodic
|
@pytest.mark.SUITE_periodic
|
||||||
@pytest.mark.dynveg_area
|
@pytest.mark.dynveg_area
|
||||||
@pytest.mark.parametrize("launcher_platform", ['windows'])
|
@pytest.mark.parametrize("launcher_platform", ['windows'])
|
||||||
@pytest.mark.skip # ATOM-14703
|
|
||||||
def test_DynamicSliceInstanceSpawner_External_E2E_Launcher(self, workspace, launcher, level,
|
def test_DynamicSliceInstanceSpawner_External_E2E_Launcher(self, workspace, launcher, level,
|
||||||
remote_console_instance, project, launcher_platform):
|
remote_console_instance, project, launcher_platform):
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ class TestLayerBlender(object):
|
|||||||
"Entity has a Box Shape component",
|
"Entity has a Box Shape component",
|
||||||
"Blender Configuration|Vegetation Areas: SUCCESS",
|
"Blender Configuration|Vegetation Areas: SUCCESS",
|
||||||
"Blender Box Shape|Box Configuration|Dimensions: SUCCESS",
|
"Blender Box Shape|Box Configuration|Dimensions: SUCCESS",
|
||||||
"Camera entity created",
|
|
||||||
"LayerBlender_E2E_Editor: result=SUCCESS"
|
"LayerBlender_E2E_Editor: result=SUCCESS"
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -85,12 +84,11 @@ class TestLayerBlender(object):
|
|||||||
@pytest.mark.BAT
|
@pytest.mark.BAT
|
||||||
@pytest.mark.SUITE_periodic
|
@pytest.mark.SUITE_periodic
|
||||||
@pytest.mark.dynveg_area
|
@pytest.mark.dynveg_area
|
||||||
@pytest.mark.xfail
|
|
||||||
@pytest.mark.parametrize("launcher_platform", ['windows'])
|
@pytest.mark.parametrize("launcher_platform", ['windows'])
|
||||||
def test_LayerBlender_E2E_Launcher(self, workspace, project, launcher, level, remote_console_instance,
|
def test_LayerBlender_E2E_Launcher(self, workspace, project, launcher, level, remote_console_instance,
|
||||||
launcher_platform):
|
launcher_platform):
|
||||||
|
|
||||||
launcher.args.extend(["-NullRenderer"])
|
launcher.args.extend(["-rhi=Null"])
|
||||||
launcher.start()
|
launcher.start()
|
||||||
assert launcher.is_alive(), "Launcher failed to start"
|
assert launcher.is_alive(), "Launcher failed to start"
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ class TestLayerSpawner(object):
|
|||||||
@pytest.mark.test_case_id("C30000751")
|
@pytest.mark.test_case_id("C30000751")
|
||||||
@pytest.mark.SUITE_sandbox
|
@pytest.mark.SUITE_sandbox
|
||||||
@pytest.mark.dynveg_misc
|
@pytest.mark.dynveg_misc
|
||||||
@pytest.mark.skip # ATOM-14828
|
@pytest.mark.skip # https://github.com/o3de/o3de/issues/2038
|
||||||
def test_LayerSpawner_InstancesRefreshUsingCorrectViewportCamera(self, request, editor, level, launcher_platform):
|
def test_LayerSpawner_InstancesRefreshUsingCorrectViewportCamera(self, request, editor, level, launcher_platform):
|
||||||
|
|
||||||
expected_lines = [
|
expected_lines = [
|
||||||
@@ -136,5 +136,6 @@ class TestLayerSpawner(object):
|
|||||||
editor,
|
editor,
|
||||||
"LayerSpawner_InstancesRefreshUsingCorrectViewportCamera.py",
|
"LayerSpawner_InstancesRefreshUsingCorrectViewportCamera.py",
|
||||||
expected_lines,
|
expected_lines,
|
||||||
cfg_args=[level]
|
cfg_args=[level],
|
||||||
|
null_renderer=False
|
||||||
)
|
)
|
||||||
|
|||||||
+2
-2
@@ -34,7 +34,7 @@ def create_surface_entity(name, center_point, box_size_x, box_size_y, box_size_z
|
|||||||
return surface_entity
|
return surface_entity
|
||||||
|
|
||||||
|
|
||||||
def create_mesh_surface_entity_with_slopes(name, center_point, scale_x, scale_y, scale_z):
|
def create_mesh_surface_entity_with_slopes(name, center_point, uniform_scale):
|
||||||
# Creates an entity with the assigned mesh_asset as the specified scale and sets up as a planting surface
|
# Creates an entity with the assigned mesh_asset as the specified scale and sets up as a planting surface
|
||||||
mesh_asset_path = os.path.join("models", "sphere.azmodel")
|
mesh_asset_path = os.path.join("models", "sphere.azmodel")
|
||||||
mesh_asset = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", mesh_asset_path, math.Uuid(),
|
mesh_asset = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", mesh_asset_path, math.Uuid(),
|
||||||
@@ -47,7 +47,7 @@ def create_mesh_surface_entity_with_slopes(name, center_point, scale_x, scale_y,
|
|||||||
if surface_entity.id.IsValid():
|
if surface_entity.id.IsValid():
|
||||||
print(f"'{surface_entity.name}' created")
|
print(f"'{surface_entity.name}' created")
|
||||||
hydra.get_set_test(surface_entity, 0, "Controller|Configuration|Mesh Asset", mesh_asset)
|
hydra.get_set_test(surface_entity, 0, "Controller|Configuration|Mesh Asset", mesh_asset)
|
||||||
components.TransformBus(bus.Event, "SetLocalScale", surface_entity.id, math.Vector3(scale_x, scale_y, scale_z))
|
components.TransformBus(bus.Event, "SetLocalUniformScale", surface_entity.id, uniform_scale)
|
||||||
return surface_entity
|
return surface_entity
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -742,14 +742,14 @@
|
|||||||
</Class>
|
</Class>
|
||||||
<Class name="int" field="methodType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
<Class name="int" field="methodType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||||
<Class name="AZStd::string" field="methodName" value="GetOnPostsimulateEvent" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
<Class name="AZStd::string" field="methodName" value="GetOnPostsimulateEvent" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||||
<Class name="AZStd::string" field="className" value="System Interface" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
<Class name="AZStd::string" field="className" value="PhysicsSystemInterface" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||||
<Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/>
|
<Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/>
|
||||||
<Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}">
|
<Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}">
|
||||||
<Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}">
|
<Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}">
|
||||||
<Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
|
<Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
|
||||||
</Class>
|
</Class>
|
||||||
</Class>
|
</Class>
|
||||||
<Class name="AZStd::string" field="prettyClassName" value="System Interface" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
<Class name="AZStd::string" field="prettyClassName" value="PhysicsSystemInterface" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||||
</Class>
|
</Class>
|
||||||
</Class>
|
</Class>
|
||||||
<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
|
<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
|
||||||
|
|||||||
@@ -1045,14 +1045,14 @@
|
|||||||
</Class>
|
</Class>
|
||||||
<Class name="int" field="methodType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
<Class name="int" field="methodType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||||
<Class name="AZStd::string" field="methodName" value="GetOnPostsimulateEvent" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
<Class name="AZStd::string" field="methodName" value="GetOnPostsimulateEvent" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||||
<Class name="AZStd::string" field="className" value="System Interface" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
<Class name="AZStd::string" field="className" value="PhysicsSystemInterface" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||||
<Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/>
|
<Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/>
|
||||||
<Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}">
|
<Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}">
|
||||||
<Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}">
|
<Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}">
|
||||||
<Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
|
<Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
|
||||||
</Class>
|
</Class>
|
||||||
</Class>
|
</Class>
|
||||||
<Class name="AZStd::string" field="prettyClassName" value="System Interface" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
<Class name="AZStd::string" field="prettyClassName" value="PhysicsSystemInterface" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||||
</Class>
|
</Class>
|
||||||
</Class>
|
</Class>
|
||||||
<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
|
<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
|
||||||
|
|||||||
@@ -1085,14 +1085,14 @@
|
|||||||
</Class>
|
</Class>
|
||||||
<Class name="int" field="methodType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
<Class name="int" field="methodType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
|
||||||
<Class name="AZStd::string" field="methodName" value="GetOnPresimulateEvent" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
<Class name="AZStd::string" field="methodName" value="GetOnPresimulateEvent" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||||
<Class name="AZStd::string" field="className" value="System Interface" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
<Class name="AZStd::string" field="className" value="PhysicsSystemInterface" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||||
<Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/>
|
<Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/>
|
||||||
<Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}">
|
<Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}">
|
||||||
<Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}">
|
<Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}">
|
||||||
<Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
|
<Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
|
||||||
</Class>
|
</Class>
|
||||||
</Class>
|
</Class>
|
||||||
<Class name="AZStd::string" field="prettyClassName" value="System Interface" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
<Class name="AZStd::string" field="prettyClassName" value="PhysicsSystemInterface" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||||
</Class>
|
</Class>
|
||||||
</Class>
|
</Class>
|
||||||
<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
|
<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
|
||||||
|
|||||||
@@ -1896,7 +1896,7 @@ void EditorViewportWidget::SetViewTM(const Matrix34& viewTM, bool bMoveOnly)
|
|||||||
|
|
||||||
if (m_pressedKeyState != KeyPressedState::PressedInPreviousFrame)
|
if (m_pressedKeyState != KeyPressedState::PressedInPreviousFrame)
|
||||||
{
|
{
|
||||||
CUndo undo("Move Camera");
|
AzToolsFramework::ScopedUndoBatch undo("Move Camera");
|
||||||
if (bMoveOnly)
|
if (bMoveOnly)
|
||||||
{
|
{
|
||||||
// specify eObjectUpdateFlags_UserInput so that an undo command gets logged
|
// specify eObjectUpdateFlags_UserInput so that an undo command gets logged
|
||||||
@@ -1932,7 +1932,7 @@ void EditorViewportWidget::SetViewTM(const Matrix34& viewTM, bool bMoveOnly)
|
|||||||
|
|
||||||
if (m_pressedKeyState != KeyPressedState::PressedInPreviousFrame)
|
if (m_pressedKeyState != KeyPressedState::PressedInPreviousFrame)
|
||||||
{
|
{
|
||||||
CUndo undo("Move Camera");
|
AzToolsFramework::ScopedUndoBatch undo("Move Camera");
|
||||||
if (bMoveOnly)
|
if (bMoveOnly)
|
||||||
{
|
{
|
||||||
AZ::TransformBus::Event(
|
AZ::TransformBus::Event(
|
||||||
@@ -1945,6 +1945,8 @@ void EditorViewportWidget::SetViewTM(const Matrix34& viewTM, bool bMoveOnly)
|
|||||||
m_viewEntityId, &AZ::TransformInterface::SetWorldTM,
|
m_viewEntityId, &AZ::TransformInterface::SetWorldTM,
|
||||||
LYTransformToAZTransform(camMatrix));
|
LYTransformToAZTransform(camMatrix));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequests::AddDirtyEntity, m_viewEntityId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>Editor</string>
|
<string>Editor</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>com.Amazon.Lumberyard.Editor</string>
|
<string>org.O3DE.Editor</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
|
|||||||
@@ -46,4 +46,8 @@ ly_add_target(
|
|||||||
AZ::AzCore
|
AZ::AzCore
|
||||||
AZ::AzToolsFramework
|
AZ::AzToolsFramework
|
||||||
AZ::AzQtComponents
|
AZ::AzQtComponents
|
||||||
|
RUNTIME_DEPENDENCIES
|
||||||
|
AZ::AzCore
|
||||||
|
AZ::AzToolsFramework
|
||||||
|
AZ::AzQtComponents
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,12 +20,12 @@
|
|||||||
#include "ValidationHandler.h"
|
#include "ValidationHandler.h"
|
||||||
|
|
||||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||||
|
#include <AzCore/IO/Path/Path.h>
|
||||||
|
|
||||||
#include "AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.h"
|
#include <AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.h>
|
||||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h>
|
#include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h>
|
||||||
#include <AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx>
|
#include <AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx>
|
||||||
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
|
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
|
||||||
#include <Util/FileUtil.h>
|
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
@@ -52,7 +52,7 @@ namespace ProjectSettingsTool
|
|||||||
PlatformEnabled(PlatformId::Ios) ?
|
PlatformEnabled(PlatformId::Ios) ?
|
||||||
ProjectSettingsContainer::PlistInitVector({
|
ProjectSettingsContainer::PlistInitVector({
|
||||||
ProjectSettingsContainer::PlatformAndPath
|
ProjectSettingsContainer::PlatformAndPath
|
||||||
{ PlatformId::Ios, m_projectRoot + PlatformResourcesFolder(PlatformId::Ios) }
|
{ PlatformId::Ios, GetPlatformResource(PlatformId::Ios) }
|
||||||
})
|
})
|
||||||
:
|
:
|
||||||
ProjectSettingsContainer::PlistInitVector())
|
ProjectSettingsContainer::PlistInitVector())
|
||||||
@@ -647,33 +647,38 @@ namespace ProjectSettingsTool
|
|||||||
// iOS can be disabled if the plist file is missing
|
// iOS can be disabled if the plist file is missing
|
||||||
if (platformId == PlatformId::Ios)
|
if (platformId == PlatformId::Ios)
|
||||||
{
|
{
|
||||||
const AZStd::string filename = m_projectRoot + PlatformResourcesFolder(platformId);
|
AZStd::string plistPath = GetPlatformResource(platformId);
|
||||||
return CFileUtil::FileExists(filename.c_str());
|
return !plistPath.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ProjectSettingsToolWindow::PlatformResourcesFolder(PlatformId platformId)
|
AZStd::string ProjectSettingsToolWindow::GetPlatformResource(PlatformId platformId)
|
||||||
{
|
{
|
||||||
if (platformId == PlatformId::Ios)
|
if (platformId == PlatformId::Ios)
|
||||||
{
|
{
|
||||||
const AZStd::string firstfilename = m_projectRoot + "/Gem/Resources/Platform/iOS/Info.plist";
|
const char* searchPaths[] = {
|
||||||
if (CFileUtil::FileExists(firstfilename.c_str()))
|
"Resources/Platform/iOS/Info.plist",
|
||||||
|
|
||||||
|
// legacy paths
|
||||||
|
"Gem/Resources/Platform/iOS/Info.plist",
|
||||||
|
"Gem/Resources/IOSLauncher/Info.plist",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto relPath : searchPaths)
|
||||||
{
|
{
|
||||||
return "/Gem/Resources/Platform/iOS/Info.plist";
|
AZ::IO::FixedMaxPath projectPlist{ m_projectRoot };
|
||||||
}
|
projectPlist /= relPath;
|
||||||
else
|
|
||||||
{
|
if (AZ::IO::SystemFile::Exists(projectPlist.c_str()))
|
||||||
const AZStd::string filename = m_projectRoot + "/Gem/Resources/IOSLauncher/Info.plist";
|
|
||||||
if (CFileUtil::FileExists(filename.c_str()))
|
|
||||||
{
|
{
|
||||||
return "/Gem/Resources/IOSLauncher/Info.plist";
|
return projectPlist.LexicallyNormal().String();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return AZStd::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <moc_ProjectSettingsToolWindow.cpp>
|
#include <moc_ProjectSettingsToolWindow.cpp>
|
||||||
|
|||||||
@@ -137,8 +137,8 @@ namespace ProjectSettingsTool
|
|||||||
// returns true if the platform is enabled
|
// returns true if the platform is enabled
|
||||||
bool PlatformEnabled(PlatformId platformId);
|
bool PlatformEnabled(PlatformId platformId);
|
||||||
|
|
||||||
// returns the resource folder
|
// returns the main platform specific resource file e.g. for iOS it would be the Info.plist
|
||||||
const char* PlatformResourcesFolder(PlatformId platformId);
|
AZStd::string GetPlatformResource(PlatformId platformId);
|
||||||
|
|
||||||
// The ui for the window
|
// The ui for the window
|
||||||
QScopedPointer<Ui::ProjectSettingsToolWidget> m_ui;
|
QScopedPointer<Ui::ProjectSettingsToolWidget> m_ui;
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ namespace AZ
|
|||||||
{
|
{
|
||||||
const char* uuidString = nullptr;
|
const char* uuidString = nullptr;
|
||||||
unsigned int uuidStringLength = 0;
|
unsigned int uuidStringLength = 0;
|
||||||
if (dc.ReadArg(0, uuidString) && dc.ReadValue(1, uuidStringLength))
|
if (dc.ReadArg(0, uuidString) && dc.ReadArg(1, uuidStringLength))
|
||||||
{
|
{
|
||||||
dc.PushResult(Uuid(uuidString, uuidStringLength));
|
dc.PushResult(Uuid(uuidString, uuidStringLength));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,8 +157,11 @@ ScriptContextDebug::EnumRegisteredClasses(EnumClass enumClass, EnumMethod enumMe
|
|||||||
lua_pop(l, 2); // pop the Class name and behaviorClass
|
lua_pop(l, 2); // pop the Class name and behaviorClass
|
||||||
|
|
||||||
lua_pushnil(l);
|
lua_pushnil(l);
|
||||||
|
|
||||||
|
// iterate over the key/value pairs
|
||||||
while (lua_next(l, -2) != 0)
|
while (lua_next(l, -2) != 0)
|
||||||
{
|
{
|
||||||
|
// if key: string value: function
|
||||||
if (lua_isstring(l, -2) && lua_isfunction(l, -1))
|
if (lua_isstring(l, -2) && lua_isfunction(l, -1))
|
||||||
{
|
{
|
||||||
const char* name = lua_tostring(l, -2);
|
const char* name = lua_tostring(l, -2);
|
||||||
@@ -167,6 +170,7 @@ ScriptContextDebug::EnumRegisteredClasses(EnumClass enumClass, EnumMethod enumMe
|
|||||||
bool isRead = true;
|
bool isRead = true;
|
||||||
bool isWrite = true;
|
bool isWrite = true;
|
||||||
|
|
||||||
|
// check if there is a getter provided
|
||||||
lua_getupvalue(l, -1, 1);
|
lua_getupvalue(l, -1, 1);
|
||||||
if (lua_isnil(l, -1))
|
if (lua_isnil(l, -1))
|
||||||
{
|
{
|
||||||
@@ -174,6 +178,7 @@ ScriptContextDebug::EnumRegisteredClasses(EnumClass enumClass, EnumMethod enumMe
|
|||||||
}
|
}
|
||||||
lua_pop(l, 1);
|
lua_pop(l, 1);
|
||||||
|
|
||||||
|
// check if there is a setter provided
|
||||||
lua_getupvalue(l, -1, 2);
|
lua_getupvalue(l, -1, 2);
|
||||||
if (lua_isnil(l, -1))
|
if (lua_isnil(l, -1))
|
||||||
{
|
{
|
||||||
@@ -181,6 +186,7 @@ ScriptContextDebug::EnumRegisteredClasses(EnumClass enumClass, EnumMethod enumMe
|
|||||||
}
|
}
|
||||||
lua_pop(l, 1);
|
lua_pop(l, 1);
|
||||||
|
|
||||||
|
// enumerate the remaining property
|
||||||
if (!enumProperty(&behaviorClass->m_typeId, name, isRead, isWrite, userData))
|
if (!enumProperty(&behaviorClass->m_typeId, name, isRead, isWrite, userData))
|
||||||
{
|
{
|
||||||
lua_pop(l, 5);
|
lua_pop(l, 5);
|
||||||
@@ -189,21 +195,30 @@ ScriptContextDebug::EnumRegisteredClasses(EnumClass enumClass, EnumMethod enumMe
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// for any non-built in methods
|
||||||
if (strncmp(name, "__", 2) != 0)
|
if (strncmp(name, "__", 2) != 0)
|
||||||
{
|
{
|
||||||
const char* dbgParamInfo = NULL;
|
const char* dbgParamInfo = NULL;
|
||||||
lua_getupvalue(l, -1, 2);
|
|
||||||
|
// attempt to get the name
|
||||||
|
bool popDebugName = lua_getupvalue(l, -1, 2) != nullptr;
|
||||||
if (lua_isstring(l, -1))
|
if (lua_isstring(l, -1))
|
||||||
{
|
{
|
||||||
dbgParamInfo = lua_tostring(l, -1);
|
dbgParamInfo = lua_tostring(l, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// enumerate the method's parameters
|
||||||
if (!enumMethod(&behaviorClass->m_typeId, name, dbgParamInfo, userData))
|
if (!enumMethod(&behaviorClass->m_typeId, name, dbgParamInfo, userData))
|
||||||
{
|
{
|
||||||
lua_pop(l, 6);
|
lua_pop(l, 6);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lua_pop(l, 1); // pop the DBG name
|
|
||||||
|
// if we were able to get the name, pop it from the stack
|
||||||
|
if (popDebugName)
|
||||||
|
{
|
||||||
|
lua_pop(l, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-5
@@ -205,6 +205,25 @@ namespace AzFramework
|
|||||||
class InputDeviceImplementationRequest : public AZ::EBusTraits
|
class InputDeviceImplementationRequest : public AZ::EBusTraits
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//! EBus Trait: requests can be addressed to a specific InputDeviceId so that they are only
|
||||||
|
//! handled by one input device that has connected to the bus using that unique id, or they
|
||||||
|
//! can be broadcast to all input devices that have connected to the bus, regardless of id.
|
||||||
|
//! Connected input devices are ordered by their local player index from lowest to highest.
|
||||||
|
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ByIdAndOrdered;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//! EBus Trait: requests should be handled by only one input device connected to each id
|
||||||
|
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//! EBus Trait: requests can be addressed to a specific InputDeviceId
|
||||||
|
using BusIdType = InputDeviceId;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//! EBus Trait: requests are handled by connected devices in the order of local player index
|
||||||
|
using BusIdOrderCompare = AZStd::less<BusIdType>;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//! Alias for the EBus implementation of this interface
|
//! Alias for the EBus implementation of this interface
|
||||||
using Bus = AZ::EBus<InputDeviceImplementationRequest<InputDeviceType>>;
|
using Bus = AZ::EBus<InputDeviceImplementationRequest<InputDeviceType>>;
|
||||||
@@ -214,11 +233,12 @@ namespace AzFramework
|
|||||||
using CreateFunctionType = typename InputDeviceType::Implementation*(*)(InputDeviceType&);
|
using CreateFunctionType = typename InputDeviceType::Implementation*(*)(InputDeviceType&);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//! Create a custom implementation for all the existing instances of this input device type.
|
//! Set a custom implementation for this input device type, either for a specific instance
|
||||||
|
//! by addressing the call to an InputDeviceId, or for all existing instances by broadcast.
|
||||||
//! Passing InputDeviceType::Implementation::Create as the argument will create the default
|
//! Passing InputDeviceType::Implementation::Create as the argument will create the default
|
||||||
//! device implementation, while passing nullptr will delete any existing implementation.
|
//! device implementation, while passing nullptr will delete any existing implementation.
|
||||||
//! \param[in] createFunction Pointer to the function that will create the implementation.
|
//! \param[in] createFunction Pointer to the function that will create the implementation.
|
||||||
virtual void CreateCustomImplementation(CreateFunctionType createFunction) = 0;
|
virtual void SetCustomImplementation(CreateFunctionType createFunction) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -238,7 +258,7 @@ namespace AzFramework
|
|||||||
AZ_INLINE InputDeviceImplementationRequestHandler(InputDeviceType& inputDevice)
|
AZ_INLINE InputDeviceImplementationRequestHandler(InputDeviceType& inputDevice)
|
||||||
: m_inputDevice(inputDevice)
|
: m_inputDevice(inputDevice)
|
||||||
{
|
{
|
||||||
InputDeviceImplementationRequest<InputDeviceType>::Bus::Handler::BusConnect();
|
InputDeviceImplementationRequest<InputDeviceType>::Bus::Handler::BusConnect(m_inputDevice.GetInputDeviceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -251,8 +271,8 @@ namespace AzFramework
|
|||||||
using CreateFunctionType = typename InputDeviceType::Implementation*(*)(InputDeviceType&);
|
using CreateFunctionType = typename InputDeviceType::Implementation*(*)(InputDeviceType&);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//! \ref InputDeviceImplementationRequest<InputDeviceType>::CreateCustomImplementation
|
//! \ref InputDeviceImplementationRequest<InputDeviceType>::SetCustomImplementation
|
||||||
AZ_INLINE void CreateCustomImplementation(CreateFunctionType createFunction) override
|
AZ_INLINE void SetCustomImplementation(CreateFunctionType createFunction) override
|
||||||
{
|
{
|
||||||
AZStd::unique_ptr<typename InputDeviceType::Implementation> newImplementation;
|
AZStd::unique_ptr<typename InputDeviceType::Implementation> newImplementation;
|
||||||
if (createFunction)
|
if (createFunction)
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ namespace AzToolsFramework
|
|||||||
//! Signal the Python handler to stop
|
//! Signal the Python handler to stop
|
||||||
virtual bool StopPython(bool silenceWarnings = false) = 0;
|
virtual bool StopPython(bool silenceWarnings = false) = 0;
|
||||||
|
|
||||||
|
//! Query to determine if the Python VM has been initialized indicating an active state
|
||||||
|
virtual bool IsPythonActive() = 0;
|
||||||
|
|
||||||
//! Determines if the caller needs to wait for the Python VM to initialize (non-main thread only)
|
//! Determines if the caller needs to wait for the Python VM to initialize (non-main thread only)
|
||||||
virtual void WaitForInitialization() {}
|
virtual void WaitForInitialization() {}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include <AzCore/Serialization/SerializeContext.h>
|
#include <AzCore/Serialization/SerializeContext.h>
|
||||||
#include <SceneAPI/SceneCore/Components/ExportingComponent.h>
|
#include <SceneAPI/SceneCore/Components/ExportingComponent.h>
|
||||||
|
#include <SceneAPI/SceneCore/Events/ExportProductList.h>
|
||||||
|
#include <AzCore/RTTI/BehaviorContext.h>
|
||||||
|
|
||||||
namespace AZ
|
namespace AZ
|
||||||
{
|
{
|
||||||
@@ -31,6 +33,12 @@ namespace AZ
|
|||||||
{
|
{
|
||||||
serializeContext->Class<ExportingComponent, AZ::Component>()->Version(2);
|
serializeContext->Class<ExportingComponent, AZ::Component>()->Version(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
|
||||||
|
if (behaviorContext)
|
||||||
|
{
|
||||||
|
Events::ExportProductList::Reflect(behaviorContext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace SceneCore
|
} // namespace SceneCore
|
||||||
} // namespace SceneAPI
|
} // namespace SceneAPI
|
||||||
|
|||||||
@@ -211,6 +211,7 @@ namespace AZ
|
|||||||
AZ::SceneAPI::Containers::SceneGraph::Reflect(context);
|
AZ::SceneAPI::Containers::SceneGraph::Reflect(context);
|
||||||
AZ::SceneAPI::Containers::SceneManifest::Reflect(context);
|
AZ::SceneAPI::Containers::SceneManifest::Reflect(context);
|
||||||
AZ::SceneAPI::Containers::RuleContainer::Reflect(context);
|
AZ::SceneAPI::Containers::RuleContainer::Reflect(context);
|
||||||
|
AZ::SceneAPI::SceneCore::ExportingComponent::Reflect(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Activate()
|
void Activate()
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <SceneAPI/SceneCore/Events/ExportProductList.h>
|
#include <SceneAPI/SceneCore/Events/ExportProductList.h>
|
||||||
|
#include <AzCore/RTTI/BehaviorContext.h>
|
||||||
|
#include <AzCore/std/limits.h>
|
||||||
|
|
||||||
namespace AZ
|
namespace AZ
|
||||||
{
|
{
|
||||||
@@ -49,6 +51,45 @@ namespace AZ
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExportProductList::Reflect(ReflectContext* context)
|
||||||
|
{
|
||||||
|
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||||
|
{
|
||||||
|
serializeContext->Class<ExportProduct>()->Version(1);
|
||||||
|
serializeContext->Class<ExportProductList>()->Version(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||||
|
{
|
||||||
|
behaviorContext->Class<ExportProduct>("ExportProduct")
|
||||||
|
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||||
|
->Attribute(AZ::Script::Attributes::Module, "scene")
|
||||||
|
->Property("filename", BehaviorValueProperty(&ExportProduct::m_filename))
|
||||||
|
->Property("sourceId", BehaviorValueProperty(&ExportProduct::m_id))
|
||||||
|
->Property("assetType", BehaviorValueProperty(&ExportProduct::m_assetType))
|
||||||
|
->Property("productDependencies", BehaviorValueProperty(&ExportProduct::m_productDependencies))
|
||||||
|
->Property("subId",
|
||||||
|
[](ExportProduct* self) { return self->m_subId.has_value() ? self->m_subId.value() : 0; },
|
||||||
|
[](ExportProduct* self, u32 subId) { self->m_subId = AZStd::optional<u32>(subId); });
|
||||||
|
|
||||||
|
behaviorContext->Class<ExportProductList>("ExportProductList")
|
||||||
|
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||||
|
->Attribute(AZ::Script::Attributes::Module, "scene")
|
||||||
|
->Method("AddProduct", [](ExportProductList& self, ExportProduct& product)
|
||||||
|
{
|
||||||
|
self.AddProduct(
|
||||||
|
product.m_filename,
|
||||||
|
product.m_id,
|
||||||
|
product.m_assetType,
|
||||||
|
product.m_lod,
|
||||||
|
product.m_subId,
|
||||||
|
product.m_dependencyFlags);
|
||||||
|
})
|
||||||
|
->Method("GetProducts", &ExportProductList::GetProducts)
|
||||||
|
->Method("AddDependencyToProduct", &ExportProductList::AddDependencyToProduct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ExportProduct& ExportProductList::AddProduct(const AZStd::string& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
|
ExportProduct& ExportProductList::AddProduct(const AZStd::string& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
|
||||||
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags)
|
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
namespace AZ
|
namespace AZ
|
||||||
{
|
{
|
||||||
|
class ReflectContext;
|
||||||
|
|
||||||
namespace SceneAPI
|
namespace SceneAPI
|
||||||
{
|
{
|
||||||
namespace Events
|
namespace Events
|
||||||
@@ -24,6 +26,7 @@ namespace AZ
|
|||||||
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
|
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
|
||||||
SCENE_CORE_API ExportProduct(AZStd::string&& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
|
SCENE_CORE_API ExportProduct(AZStd::string&& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
|
||||||
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
|
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
|
||||||
|
ExportProduct() = default;
|
||||||
ExportProduct(const ExportProduct& rhs) = default;
|
ExportProduct(const ExportProduct& rhs) = default;
|
||||||
SCENE_CORE_API ExportProduct(ExportProduct&& rhs);
|
SCENE_CORE_API ExportProduct(ExportProduct&& rhs);
|
||||||
|
|
||||||
@@ -54,6 +57,8 @@ namespace AZ
|
|||||||
class ExportProductList
|
class ExportProductList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static void Reflect(ReflectContext* context);
|
||||||
|
|
||||||
SCENE_CORE_API ExportProduct& AddProduct(const AZStd::string& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
|
SCENE_CORE_API ExportProduct& AddProduct(const AZStd::string& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
|
||||||
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
|
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
|
||||||
SCENE_CORE_API ExportProduct& AddProduct(AZStd::string&& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
|
SCENE_CORE_API ExportProduct& AddProduct(AZStd::string&& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
|
||||||
@@ -69,3 +74,9 @@ namespace AZ
|
|||||||
} // namespace Events
|
} // namespace Events
|
||||||
} // namespace SceneAPI
|
} // namespace SceneAPI
|
||||||
} // namespace AZ
|
} // namespace AZ
|
||||||
|
|
||||||
|
namespace AZ
|
||||||
|
{
|
||||||
|
AZ_TYPE_INFO_SPECIALIZE(SceneAPI::Events::ExportProduct, "{6054EDCB-4C04-4D96-BF26-704999FFB725}");
|
||||||
|
AZ_TYPE_INFO_SPECIALIZE(SceneAPI::Events::ExportProductList, "{1C76A51F-431B-4987-B653-CFCC940D0D0F}");
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <AzCore/IO/SystemFile.h>
|
#include <AzCore/IO/SystemFile.h>
|
||||||
#include <AzCore/IO/GenericStreams.h>
|
#include <AzCore/IO/GenericStreams.h>
|
||||||
#include <AzCore/Memory/SystemAllocator.h>
|
#include <AzCore/Memory/SystemAllocator.h>
|
||||||
|
#include <AzCore/Utils/Utils.h>
|
||||||
#include <AzFramework/API/ApplicationAPI.h>
|
#include <AzFramework/API/ApplicationAPI.h>
|
||||||
#include <AzFramework/StringFunc/StringFunc.h>
|
#include <AzFramework/StringFunc/StringFunc.h>
|
||||||
#include <SceneAPI/SceneCore/Import/ManifestImportRequestHandler.h>
|
#include <SceneAPI/SceneCore/Import/ManifestImportRequestHandler.h>
|
||||||
@@ -75,15 +76,16 @@ namespace AZ
|
|||||||
filename += s_extension;
|
filename += s_extension;
|
||||||
filename += s_generated;
|
filename += s_generated;
|
||||||
|
|
||||||
AZStd::string altManifestPath = path;
|
AZStd::string altManifestFolder = path;
|
||||||
AzFramework::ApplicationRequests::Bus::Broadcast(
|
AzFramework::ApplicationRequests::Bus::Broadcast(
|
||||||
&AzFramework::ApplicationRequests::Bus::Events::MakePathRootRelative,
|
&AzFramework::ApplicationRequests::Bus::Events::MakePathRelative,
|
||||||
altManifestPath);
|
altManifestFolder,
|
||||||
|
AZ::Utils::GetProjectPath().c_str());
|
||||||
|
|
||||||
AZ::StringFunc::Path::GetFolderPath(altManifestPath.c_str(), altManifestPath);
|
AZ::StringFunc::Path::GetFolderPath(altManifestFolder.c_str(), altManifestFolder);
|
||||||
|
|
||||||
AZStd::string generatedAssetInfoPath;
|
AZStd::string generatedAssetInfoPath;
|
||||||
AZ::StringFunc::Path::Join(assetCacheRoot.c_str(), altManifestPath.c_str(), generatedAssetInfoPath);
|
AZ::StringFunc::Path::Join(assetCacheRoot.c_str(), altManifestFolder.c_str(), generatedAssetInfoPath);
|
||||||
AZ::StringFunc::Path::ConstructFull(generatedAssetInfoPath.c_str(), filename.c_str(), generatedAssetInfoPath);
|
AZ::StringFunc::Path::ConstructFull(generatedAssetInfoPath.c_str(), filename.c_str(), generatedAssetInfoPath);
|
||||||
|
|
||||||
if (!AZ::IO::FileIOBase::GetInstance()->Exists(generatedAssetInfoPath.c_str()))
|
if (!AZ::IO::FileIOBase::GetInstance()->Exists(generatedAssetInfoPath.c_str()))
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -25,213 +25,319 @@
|
|||||||
#include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
|
#include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
|
||||||
#include <SceneAPI/SceneData/Rules/ScriptProcessorRule.h>
|
#include <SceneAPI/SceneData/Rules/ScriptProcessorRule.h>
|
||||||
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
|
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
|
||||||
|
#include <SceneAPI/SceneCore/Events/ExportProductList.h>
|
||||||
|
|
||||||
namespace AZ
|
namespace AZ::SceneAPI::Behaviors
|
||||||
{
|
{
|
||||||
namespace SceneAPI
|
class EditorPythonConsoleNotificationHandler final
|
||||||
|
: protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler
|
||||||
{
|
{
|
||||||
namespace Behaviors
|
public:
|
||||||
|
EditorPythonConsoleNotificationHandler()
|
||||||
{
|
{
|
||||||
class EditorPythonConsoleNotificationHandler final
|
BusConnect();
|
||||||
: protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler
|
}
|
||||||
|
|
||||||
|
~EditorPythonConsoleNotificationHandler()
|
||||||
|
{
|
||||||
|
BusDisconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AzToolsFramework::EditorPythonConsoleNotifications
|
||||||
|
void OnTraceMessage([[maybe_unused]] AZStd::string_view message) override
|
||||||
|
{
|
||||||
|
using namespace AZ::SceneAPI::Utilities;
|
||||||
|
AZ_TracePrintf(LogWindow, "%.*s \n", AZ_STRING_ARG(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnErrorMessage([[maybe_unused]] AZStd::string_view message) override
|
||||||
|
{
|
||||||
|
using namespace AZ::SceneAPI::Utilities;
|
||||||
|
AZ_TracePrintf(ErrorWindow, "[ERROR] %.*s \n", AZ_STRING_ARG(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnExceptionMessage([[maybe_unused]] AZStd::string_view message) override
|
||||||
|
{
|
||||||
|
using namespace AZ::SceneAPI::Utilities;
|
||||||
|
AZ_TracePrintf(ErrorWindow, "[EXCEPTION] %.*s \n", AZ_STRING_ARG(message));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using ExportProductList = AZ::SceneAPI::Events::ExportProductList;
|
||||||
|
|
||||||
|
// a event bus to signal during scene building
|
||||||
|
struct ScriptBuildingNotifications
|
||||||
|
: public AZ::EBusTraits
|
||||||
|
{
|
||||||
|
virtual AZStd::string OnUpdateManifest(Containers::Scene& scene) = 0;
|
||||||
|
virtual ExportProductList OnPrepareForExport(
|
||||||
|
const Containers::Scene& scene,
|
||||||
|
AZStd::string_view outputDirectory,
|
||||||
|
AZStd::string_view platformIdentifier,
|
||||||
|
const ExportProductList& productList) = 0;
|
||||||
|
};
|
||||||
|
using ScriptBuildingNotificationBus = AZ::EBus<ScriptBuildingNotifications>;
|
||||||
|
|
||||||
|
// a back end to handle scene builder events for a script
|
||||||
|
struct ScriptBuildingNotificationBusHandler final
|
||||||
|
: public ScriptBuildingNotificationBus::Handler
|
||||||
|
, public AZ::BehaviorEBusHandler
|
||||||
|
{
|
||||||
|
AZ_EBUS_BEHAVIOR_BINDER(
|
||||||
|
ScriptBuildingNotificationBusHandler,
|
||||||
|
"{DF2B51DE-A4D0-4139-B5D0-DF185832380D}",
|
||||||
|
AZ::SystemAllocator,
|
||||||
|
OnUpdateManifest,
|
||||||
|
OnPrepareForExport);
|
||||||
|
|
||||||
|
virtual ~ScriptBuildingNotificationBusHandler() = default;
|
||||||
|
|
||||||
|
AZStd::string OnUpdateManifest(Containers::Scene& scene) override
|
||||||
|
{
|
||||||
|
AZStd::string result;
|
||||||
|
CallResult(result, FN_OnUpdateManifest, scene);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExportProductList OnPrepareForExport(
|
||||||
|
const Containers::Scene& scene,
|
||||||
|
AZStd::string_view outputDirectory,
|
||||||
|
AZStd::string_view platformIdentifier,
|
||||||
|
const ExportProductList& productList) override
|
||||||
|
{
|
||||||
|
ExportProductList result;
|
||||||
|
CallResult(result, FN_OnPrepareForExport, scene, outputDirectory, platformIdentifier, productList);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Reflect(AZ::ReflectContext* context)
|
||||||
|
{
|
||||||
|
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||||
{
|
{
|
||||||
public:
|
behaviorContext->EBus<ScriptBuildingNotificationBus>("ScriptBuildingNotificationBus")
|
||||||
EditorPythonConsoleNotificationHandler()
|
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
|
||||||
{
|
->Attribute(AZ::Script::Attributes::Module, "scene")
|
||||||
BusConnect();
|
->Handler<ScriptBuildingNotificationBusHandler>()
|
||||||
}
|
->Event("OnUpdateManifest", &ScriptBuildingNotificationBus::Events::OnUpdateManifest)
|
||||||
|
->Event("OnPrepareForExport", &ScriptBuildingNotificationBus::Events::OnPrepareForExport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
~EditorPythonConsoleNotificationHandler()
|
struct ScriptProcessorRuleBehavior::ExportEventHandler final
|
||||||
{
|
: public AZ::SceneAPI::SceneCore::ExportingComponent
|
||||||
BusDisconnect();
|
{
|
||||||
}
|
using PreExportEventContextFunction = AZStd::function<bool(Events::PreExportEventContext&)>;
|
||||||
|
PreExportEventContextFunction m_preExportEventContextFunction;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
ExportEventHandler(PreExportEventContextFunction preExportEventContextFunction)
|
||||||
// AzToolsFramework::EditorPythonConsoleNotifications
|
: m_preExportEventContextFunction(preExportEventContextFunction)
|
||||||
void OnTraceMessage([[maybe_unused]] AZStd::string_view message) override
|
{
|
||||||
{
|
BindToCall(&ExportEventHandler::PrepareForExport);
|
||||||
using namespace AZ::SceneAPI::Utilities;
|
AZ::SceneAPI::SceneCore::ExportingComponent::Activate();
|
||||||
AZ_TracePrintf(LogWindow, "%.*s \n", AZ_STRING_ARG(message));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void OnErrorMessage([[maybe_unused]] AZStd::string_view message) override
|
~ExportEventHandler()
|
||||||
{
|
{
|
||||||
using namespace AZ::SceneAPI::Utilities;
|
AZ::SceneAPI::SceneCore::ExportingComponent::Deactivate();
|
||||||
AZ_TracePrintf(ErrorWindow, "[ERROR] %.*s \n", AZ_STRING_ARG(message));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void OnExceptionMessage([[maybe_unused]] AZStd::string_view message) override
|
// this allows a Python script to add product assets on "scene export"
|
||||||
{
|
Events::ProcessingResult PrepareForExport(Events::PreExportEventContext& context)
|
||||||
using namespace AZ::SceneAPI::Utilities;
|
{
|
||||||
AZ_TracePrintf(ErrorWindow, "[EXCEPTION] %.*s \n", AZ_STRING_ARG(message));
|
return m_preExportEventContextFunction(context) ? Events::ProcessingResult::Success : Events::ProcessingResult::Failure;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// a event bus to signal during scene building
|
void ScriptProcessorRuleBehavior::Activate()
|
||||||
struct ScriptBuildingNotifications
|
{
|
||||||
: public AZ::EBusTraits
|
Events::AssetImportRequestBus::Handler::BusConnect();
|
||||||
|
m_exportEventHandler = AZStd::make_shared<ExportEventHandler>([this](Events::PreExportEventContext& context)
|
||||||
|
{
|
||||||
|
return this->DoPrepareForExport(context);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptProcessorRuleBehavior::Deactivate()
|
||||||
|
{
|
||||||
|
m_exportEventHandler.reset();
|
||||||
|
Events::AssetImportRequestBus::Handler::BusDisconnect();
|
||||||
|
UnloadPython();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptProcessorRuleBehavior::LoadPython(const AZ::SceneAPI::Containers::Scene& scene)
|
||||||
|
{
|
||||||
|
if (m_editorPythonEventsInterface && !m_scriptFilename.empty())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get project folder
|
||||||
|
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||||
|
AZ::IO::FixedMaxPath projectPath;
|
||||||
|
if (!settingsRegistry->Get(projectPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AZ::SceneAPI::Containers::SceneManifest& manifest = scene.GetManifest();
|
||||||
|
auto view = Containers::MakeDerivedFilterView<DataTypes::IScriptProcessorRule>(manifest.GetValueStorage());
|
||||||
|
for (const auto& scriptItem : view)
|
||||||
|
{
|
||||||
|
AZ::IO::FixedMaxPath scriptFilename(scriptItem.GetScriptFilename());
|
||||||
|
if (scriptFilename.empty())
|
||||||
{
|
{
|
||||||
virtual AZStd::string OnUpdateManifest(Containers::Scene& scene) = 0;
|
AZ_Warning("scene", false, "Skipping an empty script filename in (%s)", scene.GetManifestFilename().c_str());
|
||||||
};
|
continue;
|
||||||
using ScriptBuildingNotificationBus = AZ::EBus<ScriptBuildingNotifications>;
|
}
|
||||||
|
|
||||||
// a back end to handle scene builder events for a script
|
// check for file exist via absolute path
|
||||||
struct ScriptBuildingNotificationBusHandler final
|
if (!IO::FileIOBase::GetInstance()->Exists(scriptFilename.c_str()))
|
||||||
: public ScriptBuildingNotificationBus::Handler
|
|
||||||
, public AZ::BehaviorEBusHandler
|
|
||||||
{
|
{
|
||||||
AZ_EBUS_BEHAVIOR_BINDER(
|
// check for script in the project folder
|
||||||
ScriptBuildingNotificationBusHandler,
|
AZ::IO::FixedMaxPath projectScriptPath = projectPath / scriptFilename;
|
||||||
"{DF2B51DE-A4D0-4139-B5D0-DF185832380D}",
|
if (!IO::FileIOBase::GetInstance()->Exists(projectScriptPath.c_str()))
|
||||||
AZ::SystemAllocator,
|
|
||||||
OnUpdateManifest);
|
|
||||||
|
|
||||||
virtual ~ScriptBuildingNotificationBusHandler() = default;
|
|
||||||
|
|
||||||
AZStd::string OnUpdateManifest(Containers::Scene& scene) override
|
|
||||||
{
|
{
|
||||||
AZStd::string result;
|
AZ_Warning("scene", false, "Skipping a missing script (%s) in manifest file (%s)",
|
||||||
CallResult(result, FN_OnUpdateManifest, scene);
|
scriptFilename.c_str(),
|
||||||
return result;
|
scene.GetManifestFilename().c_str());
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
scriptFilename = AZStd::move(projectScriptPath);
|
||||||
|
}
|
||||||
|
|
||||||
static void Reflect(AZ::ReflectContext* context)
|
// lazy load the Python interface
|
||||||
|
auto editorPythonEventsInterface = AZ::Interface<AzToolsFramework::EditorPythonEventsInterface>::Get();
|
||||||
|
if (editorPythonEventsInterface->IsPythonActive() == false)
|
||||||
|
{
|
||||||
|
const bool silenceWarnings = false;
|
||||||
|
if (editorPythonEventsInterface->StartPython(silenceWarnings) == false)
|
||||||
{
|
{
|
||||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
editorPythonEventsInterface = nullptr;
|
||||||
{
|
|
||||||
behaviorContext->EBus<ScriptBuildingNotificationBus>("ScriptBuildingNotificationBus")
|
|
||||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
|
|
||||||
->Attribute(AZ::Script::Attributes::Module, "scene")
|
|
||||||
->Handler<ScriptBuildingNotificationBusHandler>()
|
|
||||||
->Event("OnUpdateManifest", &ScriptBuildingNotificationBus::Events::OnUpdateManifest);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// both Python and the script need to be ready
|
||||||
|
if (editorPythonEventsInterface == nullptr || scriptFilename.empty())
|
||||||
|
{
|
||||||
|
AZ_Warning("scene", false,"The scene manifest (%s) attempted to use script(%s) but Python is not enabled;"
|
||||||
|
"please add the EditorPythonBinding gem & PythonAssetBuilder gem to your project.",
|
||||||
|
scene.GetManifestFilename().c_str(), scriptFilename.c_str());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_editorPythonEventsInterface = editorPythonEventsInterface;
|
||||||
|
m_scriptFilename = scriptFilename.c_str();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptProcessorRuleBehavior::UnloadPython()
|
||||||
|
{
|
||||||
|
if (m_editorPythonEventsInterface)
|
||||||
|
{
|
||||||
|
const bool silenceWarnings = true;
|
||||||
|
m_editorPythonEventsInterface->StopPython(silenceWarnings);
|
||||||
|
m_editorPythonEventsInterface = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptProcessorRuleBehavior::DoPrepareForExport(Events::PreExportEventContext& context)
|
||||||
|
{
|
||||||
|
using namespace AzToolsFramework;
|
||||||
|
|
||||||
|
auto executeCallback = [this, &context]()
|
||||||
|
{
|
||||||
|
// set up script's hook callback
|
||||||
|
EditorPythonRunnerRequestBus::Broadcast(&EditorPythonRunnerRequestBus::Events::ExecuteByFilename,
|
||||||
|
m_scriptFilename.c_str());
|
||||||
|
|
||||||
|
// call script's callback to allow extra products
|
||||||
|
ExportProductList extraProducts;
|
||||||
|
ScriptBuildingNotificationBus::BroadcastResult(extraProducts, &ScriptBuildingNotificationBus::Events::OnPrepareForExport,
|
||||||
|
context.GetScene(),
|
||||||
|
context.GetOutputDirectory(),
|
||||||
|
context.GetPlatformIdentifier(),
|
||||||
|
context.GetProductList()
|
||||||
|
);
|
||||||
|
|
||||||
|
// add new products
|
||||||
|
for (const auto& product : extraProducts.GetProducts())
|
||||||
|
{
|
||||||
|
context.GetProductList().AddProduct(
|
||||||
|
product.m_filename,
|
||||||
|
product.m_id,
|
||||||
|
product.m_assetType,
|
||||||
|
product.m_lod,
|
||||||
|
product.m_subId,
|
||||||
|
product.m_dependencyFlags);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (LoadPython(context.GetScene()))
|
||||||
|
{
|
||||||
|
EditorPythonConsoleNotificationHandler logger;
|
||||||
|
m_editorPythonEventsInterface->ExecuteWithLock(executeCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptProcessorRuleBehavior::Reflect(ReflectContext* context)
|
||||||
|
{
|
||||||
|
ScriptBuildingNotificationBusHandler::Reflect(context);
|
||||||
|
|
||||||
|
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||||
|
if (serializeContext)
|
||||||
|
{
|
||||||
|
serializeContext->Class<ScriptProcessorRuleBehavior, BehaviorComponent>()->Version(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Events::ProcessingResult ScriptProcessorRuleBehavior::UpdateManifest(
|
||||||
|
Containers::Scene& scene,
|
||||||
|
Events::AssetImportRequest::ManifestAction action,
|
||||||
|
[[maybe_unused]] Events::AssetImportRequest::RequestingApplication requester)
|
||||||
|
{
|
||||||
|
using namespace AzToolsFramework;
|
||||||
|
|
||||||
|
if (action != ManifestAction::Update)
|
||||||
|
{
|
||||||
|
return Events::ProcessingResult::Ignored;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LoadPython(scene))
|
||||||
|
{
|
||||||
|
AZStd::string manifestUpdate;
|
||||||
|
auto executeCallback = [this, &scene, &manifestUpdate]()
|
||||||
|
{
|
||||||
|
EditorPythonRunnerRequestBus::Broadcast(&EditorPythonRunnerRequestBus::Events::ExecuteByFilename,
|
||||||
|
m_scriptFilename.c_str());
|
||||||
|
|
||||||
|
ScriptBuildingNotificationBus::BroadcastResult(manifestUpdate, &ScriptBuildingNotificationBus::Events::OnUpdateManifest,
|
||||||
|
scene);
|
||||||
};
|
};
|
||||||
|
|
||||||
void ScriptProcessorRuleBehavior::Activate()
|
EditorPythonConsoleNotificationHandler logger;
|
||||||
|
m_editorPythonEventsInterface->ExecuteWithLock(executeCallback);
|
||||||
|
|
||||||
|
// attempt to load the manifest string back to a JSON-scene-manifest
|
||||||
|
auto sceneManifestLoader = AZStd::make_unique<AZ::SceneAPI::Containers::SceneManifest>();
|
||||||
|
auto loadOutcome = sceneManifestLoader->LoadFromString(manifestUpdate);
|
||||||
|
if (loadOutcome.IsSuccess())
|
||||||
{
|
{
|
||||||
Events::AssetImportRequestBus::Handler::BusConnect();
|
scene.GetManifest().Clear();
|
||||||
|
for (size_t entryIndex = 0; entryIndex < sceneManifestLoader->GetEntryCount(); ++entryIndex)
|
||||||
|
{
|
||||||
|
scene.GetManifest().AddEntry(sceneManifestLoader->GetValue(entryIndex));
|
||||||
|
}
|
||||||
|
return Events::ProcessingResult::Success;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return Events::ProcessingResult::Ignored;
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptProcessorRuleBehavior::Deactivate()
|
|
||||||
{
|
|
||||||
Events::AssetImportRequestBus::Handler::BusDisconnect();
|
|
||||||
if (m_editorPythonEventsInterface)
|
|
||||||
{
|
|
||||||
const bool silenceWarnings = true;
|
|
||||||
m_editorPythonEventsInterface->StopPython(silenceWarnings);
|
|
||||||
m_editorPythonEventsInterface = nullptr;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptProcessorRuleBehavior::Reflect(ReflectContext* context)
|
|
||||||
{
|
|
||||||
ScriptBuildingNotificationBusHandler::Reflect(context);
|
|
||||||
|
|
||||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
|
||||||
if (serializeContext)
|
|
||||||
{
|
|
||||||
serializeContext->Class<ScriptProcessorRuleBehavior, BehaviorComponent>()->Version(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Events::ProcessingResult ScriptProcessorRuleBehavior::UpdateManifest(
|
|
||||||
Containers::Scene& scene,
|
|
||||||
Events::AssetImportRequest::ManifestAction action,
|
|
||||||
[[maybe_unused]] Events::AssetImportRequest::RequestingApplication requester)
|
|
||||||
{
|
|
||||||
using namespace AzToolsFramework;
|
|
||||||
|
|
||||||
if (action != ManifestAction::Update)
|
|
||||||
{
|
|
||||||
return Events::ProcessingResult::Ignored;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get project folder
|
|
||||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
|
||||||
AZ::IO::FixedMaxPath projectPath;
|
|
||||||
if (!settingsRegistry->Get(projectPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath))
|
|
||||||
{
|
|
||||||
return Events::ProcessingResult::Ignored;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& sceneManifest = scene.GetManifest();
|
|
||||||
auto view = Containers::MakeDerivedFilterView<DataTypes::IScriptProcessorRule>(sceneManifest.GetValueStorage());
|
|
||||||
for (const auto& scriptItem : view)
|
|
||||||
{
|
|
||||||
AZ::IO::FixedMaxPath scriptFilename(scriptItem.GetScriptFilename());
|
|
||||||
if (scriptFilename.empty())
|
|
||||||
{
|
|
||||||
AZ_Warning("scene", false, "Skipping an empty script filename in (%s)", scene.GetManifestFilename().c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for file exist via absolute path
|
|
||||||
if (!IO::FileIOBase::GetInstance()->Exists(scriptFilename.c_str()))
|
|
||||||
{
|
|
||||||
// check for script in the project folder
|
|
||||||
AZ::IO::FixedMaxPath projectScriptPath = projectPath / scriptFilename;
|
|
||||||
if (!IO::FileIOBase::GetInstance()->Exists(projectScriptPath.c_str()))
|
|
||||||
{
|
|
||||||
AZ_Warning("scene", false, "Skipping a missing script (%s) in manifest file (%s)",
|
|
||||||
scriptFilename.c_str(),
|
|
||||||
scene.GetManifestFilename().c_str());
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
scriptFilename = AZStd::move(projectScriptPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// lazy load the Python interface
|
|
||||||
if (!m_editorPythonEventsInterface)
|
|
||||||
{
|
|
||||||
m_editorPythonEventsInterface = AZ::Interface<AzToolsFramework::EditorPythonEventsInterface>::Get();
|
|
||||||
const bool silenceWarnings = true;
|
|
||||||
m_editorPythonEventsInterface->StartPython(silenceWarnings);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_editorPythonEventsInterface && !scriptFilename.empty())
|
|
||||||
{
|
|
||||||
AZ_Warning("scene", false,
|
|
||||||
"The scene manifest (%s) attempted to use script(%s) but Python is not enabled;"
|
|
||||||
"please add the EditorPythonBinding gem & PythonAssetBuilder gem to your project.",
|
|
||||||
scene.GetManifestFilename().c_str(), scriptFilename.c_str());
|
|
||||||
|
|
||||||
return Events::ProcessingResult::Ignored;
|
|
||||||
}
|
|
||||||
|
|
||||||
AZStd::string manifestUpdate;
|
|
||||||
auto executeCallback = [&scene, &scriptFilename, &manifestUpdate]()
|
|
||||||
{
|
|
||||||
EditorPythonRunnerRequestBus::Broadcast(
|
|
||||||
&EditorPythonRunnerRequestBus::Events::ExecuteByFilename,
|
|
||||||
scriptFilename.c_str());
|
|
||||||
|
|
||||||
ScriptBuildingNotificationBus::BroadcastResult(
|
|
||||||
manifestUpdate,
|
|
||||||
&ScriptBuildingNotificationBus::Events::OnUpdateManifest,
|
|
||||||
scene);
|
|
||||||
};
|
|
||||||
EditorPythonConsoleNotificationHandler logger;
|
|
||||||
m_editorPythonEventsInterface->ExecuteWithLock(executeCallback);
|
|
||||||
|
|
||||||
// attempt to load the manifest string back to a JSON-scene-manifest
|
|
||||||
auto sceneManifestLoader = AZStd::make_unique<AZ::SceneAPI::Containers::SceneManifest>();
|
|
||||||
auto loadOutcome = sceneManifestLoader->LoadFromString(manifestUpdate);
|
|
||||||
if (loadOutcome.IsSuccess())
|
|
||||||
{
|
|
||||||
sceneManifest.Clear();
|
|
||||||
for (size_t entryIndex = 0; entryIndex < sceneManifestLoader->GetEntryCount(); ++entryIndex)
|
|
||||||
{
|
|
||||||
sceneManifest.AddEntry(sceneManifestLoader->GetValue(entryIndex));
|
|
||||||
}
|
|
||||||
return Events::ProcessingResult::Success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Events::ProcessingResult::Ignored;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Behaviors
|
|
||||||
} // namespace SceneAPI
|
|
||||||
} // namespace AZ
|
} // namespace AZ
|
||||||
|
|||||||
@@ -11,40 +11,56 @@
|
|||||||
#include <AzCore/std/string/string.h>
|
#include <AzCore/std/string/string.h>
|
||||||
#include <SceneAPI/SceneCore/Components/BehaviorComponent.h>
|
#include <SceneAPI/SceneCore/Components/BehaviorComponent.h>
|
||||||
#include <SceneAPI/SceneCore/Events/AssetImportRequest.h>
|
#include <SceneAPI/SceneCore/Events/AssetImportRequest.h>
|
||||||
|
#include <SceneAPI/SceneCore/Components/ExportingComponent.h>
|
||||||
|
#include <SceneAPI/SceneCore/Events/ExportEventContext.h>
|
||||||
|
|
||||||
namespace AzToolsFramework
|
namespace AzToolsFramework
|
||||||
{
|
{
|
||||||
class EditorPythonEventsInterface;
|
class EditorPythonEventsInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace AZ
|
namespace AZ::SceneAPI::Events
|
||||||
{
|
{
|
||||||
namespace SceneAPI
|
class PreExportEventContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace AZ::SceneAPI::Containers
|
||||||
|
{
|
||||||
|
class Scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace AZ::SceneAPI::Behaviors
|
||||||
|
{
|
||||||
|
class SCENE_DATA_CLASS ScriptProcessorRuleBehavior
|
||||||
|
: public SceneCore::BehaviorComponent
|
||||||
|
, public Events::AssetImportRequestBus::Handler
|
||||||
{
|
{
|
||||||
namespace Behaviors
|
public:
|
||||||
{
|
AZ_COMPONENT(ScriptProcessorRuleBehavior, "{24054E73-1B92-43B0-AC13-174B2F0E3F66}", SceneCore::BehaviorComponent);
|
||||||
class SCENE_DATA_CLASS ScriptProcessorRuleBehavior
|
|
||||||
: public SceneCore::BehaviorComponent
|
|
||||||
, public Events::AssetImportRequestBus::Handler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AZ_COMPONENT(ScriptProcessorRuleBehavior, "{24054E73-1B92-43B0-AC13-174B2F0E3F66}", SceneCore::BehaviorComponent);
|
|
||||||
|
|
||||||
~ScriptProcessorRuleBehavior() override = default;
|
~ScriptProcessorRuleBehavior() override = default;
|
||||||
|
|
||||||
SCENE_DATA_API void Activate() override;
|
SCENE_DATA_API void Activate() override;
|
||||||
SCENE_DATA_API void Deactivate() override;
|
SCENE_DATA_API void Deactivate() override;
|
||||||
static void Reflect(ReflectContext* context);
|
static void Reflect(ReflectContext* context);
|
||||||
|
|
||||||
// AssetImportRequestBus::Handler
|
// AssetImportRequestBus::Handler
|
||||||
SCENE_DATA_API Events::ProcessingResult UpdateManifest(
|
SCENE_DATA_API Events::ProcessingResult UpdateManifest(
|
||||||
Containers::Scene& scene,
|
Containers::Scene& scene,
|
||||||
ManifestAction action,
|
ManifestAction action,
|
||||||
RequestingApplication requester) override;
|
RequestingApplication requester) override;
|
||||||
|
|
||||||
private:
|
|
||||||
AzToolsFramework::EditorPythonEventsInterface* m_editorPythonEventsInterface = nullptr;
|
protected:
|
||||||
};
|
bool LoadPython(const AZ::SceneAPI::Containers::Scene& scene);
|
||||||
} // namespace SceneData
|
void UnloadPython();
|
||||||
} // namespace SceneAPI
|
bool DoPrepareForExport(Events::PreExportEventContext& context);
|
||||||
} // namespace AZ
|
|
||||||
|
private:
|
||||||
|
AzToolsFramework::EditorPythonEventsInterface* m_editorPythonEventsInterface = nullptr;
|
||||||
|
AZStd::string m_scriptFilename;
|
||||||
|
|
||||||
|
struct ExportEventHandler;
|
||||||
|
AZStd::shared_ptr<ExportEventHandler> m_exportEventHandler;
|
||||||
|
};
|
||||||
|
} // namespace AZ::SceneAPI::Behaviors
|
||||||
|
|||||||
@@ -1,42 +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
|
|
||||||
|
|
||||||
namespace AZ
|
|
||||||
{
|
|
||||||
class BehaviorContext;
|
|
||||||
class EditContext;
|
|
||||||
class SerializeContext;
|
|
||||||
} // namespace AZ
|
|
||||||
|
|
||||||
// this just provides a convenient template to avoid the necessary boilerplate when you derive from AWSScriptBehaviorBase
|
|
||||||
#define AWS_SCRIPT_BEHAVIOR_DEFINITION(className, guidString) \
|
|
||||||
AZ_TYPE_INFO(className, guidString) \
|
|
||||||
AZ_CLASS_ALLOCATOR(className, AZ::SystemAllocator, 0) \
|
|
||||||
void ReflectSerialization(AZ::SerializeContext* serializeContext) override; \
|
|
||||||
void ReflectBehaviors(AZ::BehaviorContext* behaviorContext) override; \
|
|
||||||
void ReflectEditParameters(AZ::EditContext* editContext) override; \
|
|
||||||
className(); \
|
|
||||||
|
|
||||||
namespace AWSCore
|
|
||||||
{
|
|
||||||
//! An interface for AWS ScriptCanvas Behaviors to inherit from
|
|
||||||
class AWSScriptBehaviorBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~AWSScriptBehaviorBase() = default;
|
|
||||||
|
|
||||||
virtual void ReflectSerialization(AZ::SerializeContext* reflectContext) = 0;
|
|
||||||
virtual void ReflectBehaviors(AZ::BehaviorContext* behaviorContext) = 0;
|
|
||||||
virtual void ReflectEditParameters(AZ::EditContext* editContext) = 0;
|
|
||||||
|
|
||||||
virtual void Init() {}
|
|
||||||
virtual void Activate() {}
|
|
||||||
virtual void Deactivate() {}
|
|
||||||
};
|
|
||||||
} // namespace AWSCore
|
|
||||||
@@ -10,8 +10,6 @@
|
|||||||
#include <AzCore/EBus/EBus.h>
|
#include <AzCore/EBus/EBus.h>
|
||||||
#include <AzCore/std/string/string.h>
|
#include <AzCore/std/string/string.h>
|
||||||
|
|
||||||
#include <ScriptCanvas/AWSScriptBehaviorBase.h>
|
|
||||||
|
|
||||||
namespace AWSCore
|
namespace AWSCore
|
||||||
{
|
{
|
||||||
using DynamoDBAttributeValueMap = AZStd::unordered_map<AZStd::string, AZStd::string>;
|
using DynamoDBAttributeValueMap = AZStd::unordered_map<AZStd::string, AZStd::string>;
|
||||||
@@ -55,10 +53,14 @@ namespace AWSCore
|
|||||||
};
|
};
|
||||||
|
|
||||||
class AWSScriptBehaviorDynamoDB
|
class AWSScriptBehaviorDynamoDB
|
||||||
: public AWSScriptBehaviorBase
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AWS_SCRIPT_BEHAVIOR_DEFINITION(AWSScriptBehaviorDynamoDB, "{569E74F6-1268-4199-9653-A3B603FC9F4F}");
|
AZ_RTTI(AWSScriptBehaviorDynamoDB, "{569E74F6-1268-4199-9653-A3B603FC9F4F}");
|
||||||
|
|
||||||
|
AWSScriptBehaviorDynamoDB() = default;
|
||||||
|
virtual ~AWSScriptBehaviorDynamoDB() = default;
|
||||||
|
|
||||||
|
static void Reflect(AZ::ReflectContext* context);
|
||||||
|
|
||||||
static void GetItem(const AZStd::string& tableResourceKey, const DynamoDBAttributeValueMap& keyMap);
|
static void GetItem(const AZStd::string& tableResourceKey, const DynamoDBAttributeValueMap& keyMap);
|
||||||
static void GetItemRaw(const AZStd::string& table, const DynamoDBAttributeValueMap& keyMap, const AZStd::string& region);
|
static void GetItemRaw(const AZStd::string& table, const DynamoDBAttributeValueMap& keyMap, const AZStd::string& region);
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
#include <AzCore/EBus/EBus.h>
|
#include <AzCore/EBus/EBus.h>
|
||||||
#include <AzCore/std/string/string.h>
|
#include <AzCore/std/string/string.h>
|
||||||
|
|
||||||
#include <ScriptCanvas/AWSScriptBehaviorBase.h>
|
|
||||||
|
|
||||||
namespace AWSCore
|
namespace AWSCore
|
||||||
{
|
{
|
||||||
//! AWS Script Behavior notifications for ScriptCanvas behaviors that interact with AWS Lambda
|
//! AWS Script Behavior notifications for ScriptCanvas behaviors that interact with AWS Lambda
|
||||||
@@ -53,10 +51,14 @@ namespace AWSCore
|
|||||||
};
|
};
|
||||||
|
|
||||||
class AWSScriptBehaviorLambda
|
class AWSScriptBehaviorLambda
|
||||||
: public AWSScriptBehaviorBase
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AWS_SCRIPT_BEHAVIOR_DEFINITION(AWSScriptBehaviorLambda, "{9E71534D-34B3-4723-B180-2552513DDA3D}");
|
AZ_RTTI(AWSScriptBehaviorLambda, "{9E71534D-34B3-4723-B180-2552513DDA3D}");
|
||||||
|
|
||||||
|
AWSScriptBehaviorLambda() = default;
|
||||||
|
virtual ~AWSScriptBehaviorLambda() = default;
|
||||||
|
|
||||||
|
static void Reflect(AZ::ReflectContext* context);
|
||||||
|
|
||||||
static void Invoke(const AZStd::string& functionResourceKey, const AZStd::string& payload);
|
static void Invoke(const AZStd::string& functionResourceKey, const AZStd::string& payload);
|
||||||
static void InvokeRaw(const AZStd::string& functionName, const AZStd::string& payload, const AZStd::string& region);
|
static void InvokeRaw(const AZStd::string& functionName, const AZStd::string& payload, const AZStd::string& region);
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
#include <AzCore/EBus/EBus.h>
|
#include <AzCore/EBus/EBus.h>
|
||||||
#include <AzCore/std/string/string.h>
|
#include <AzCore/std/string/string.h>
|
||||||
|
|
||||||
#include <ScriptCanvas/AWSScriptBehaviorBase.h>
|
|
||||||
|
|
||||||
namespace AWSCore
|
namespace AWSCore
|
||||||
{
|
{
|
||||||
//! AWS Script Behavior notifications for ScriptCanvas behaviors that interact with AWS S3
|
//! AWS Script Behavior notifications for ScriptCanvas behaviors that interact with AWS S3
|
||||||
@@ -68,7 +66,6 @@ namespace AWSCore
|
|||||||
};
|
};
|
||||||
|
|
||||||
class AWSScriptBehaviorS3
|
class AWSScriptBehaviorS3
|
||||||
: public AWSScriptBehaviorBase
|
|
||||||
{
|
{
|
||||||
static constexpr const char AWSScriptBehaviorS3Name[] = "AWSScriptBehaviorS3";
|
static constexpr const char AWSScriptBehaviorS3Name[] = "AWSScriptBehaviorS3";
|
||||||
static constexpr const char OutputFileIsEmptyErrorMessage[] = "Request validation failed, output file is empty.";
|
static constexpr const char OutputFileIsEmptyErrorMessage[] = "Request validation failed, output file is empty.";
|
||||||
@@ -81,7 +78,12 @@ namespace AWSCore
|
|||||||
static constexpr const char RegionNameIsEmptyErrorMessage[] = "Request validation failed, region name is empty.";
|
static constexpr const char RegionNameIsEmptyErrorMessage[] = "Request validation failed, region name is empty.";
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AWS_SCRIPT_BEHAVIOR_DEFINITION(AWSScriptBehaviorS3, "{7F4E956C-7463-4236-B320-C992D36A9C6E}");
|
AZ_RTTI(AWSScriptBehaviorS3, "{7F4E956C-7463-4236-B320-C992D36A9C6E}");
|
||||||
|
|
||||||
|
AWSScriptBehaviorS3() = default;
|
||||||
|
virtual ~AWSScriptBehaviorS3() = default;
|
||||||
|
|
||||||
|
static void Reflect(AZ::ReflectContext* context);
|
||||||
|
|
||||||
static void GetObject(const AZStd::string& bucketResourceKey, const AZStd::string& objectKey, const AZStd::string& outFile);
|
static void GetObject(const AZStd::string& bucketResourceKey, const AZStd::string& objectKey, const AZStd::string& outFile);
|
||||||
static void GetObjectRaw(const AZStd::string& bucket, const AZStd::string& objectKey, const AZStd::string& region, const AZStd::string& outFile);
|
static void GetObjectRaw(const AZStd::string& bucket, const AZStd::string& objectKey, const AZStd::string& region, const AZStd::string& outFile);
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include <AzCore/Component/Component.h>
|
#include <AzCore/Component/Component.h>
|
||||||
#include <AzCore/RTTI/BehaviorContext.h>
|
#include <AzCore/RTTI/BehaviorContext.h>
|
||||||
#include <AzCore/Serialization/EditContext.h>
|
#include <AzCore/Serialization/EditContext.h>
|
||||||
#include <AzCore/std/containers/vector.h>
|
|
||||||
|
|
||||||
namespace AWSCore
|
namespace AWSCore
|
||||||
{
|
{
|
||||||
@@ -30,23 +29,8 @@ namespace AWSCore
|
|||||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
|
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
|
||||||
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
|
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
|
||||||
|
|
||||||
static bool AddedBehaviours()
|
|
||||||
{
|
|
||||||
return m_alreadyAddedBehaviors;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
|
||||||
// AZ::Component interface implementation
|
// AZ::Component interface implementation
|
||||||
void Init() override;
|
|
||||||
void Activate() override;
|
void Activate() override;
|
||||||
void Deactivate() override;
|
void Deactivate() override;
|
||||||
////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static void AddBehaviors(); // Add any behaviors you derived from AWSScriptBehaviorBase to the implementation of this function
|
|
||||||
|
|
||||||
static AZStd::vector<AZStd::unique_ptr<AWSScriptBehaviorBase>> m_behaviors;
|
|
||||||
static bool m_alreadyAddedBehaviors;
|
|
||||||
};
|
};
|
||||||
} // namespace AWSCore
|
} // namespace AWSCore
|
||||||
|
|||||||
@@ -20,39 +20,30 @@
|
|||||||
|
|
||||||
namespace AWSCore
|
namespace AWSCore
|
||||||
{
|
{
|
||||||
AWSScriptBehaviorDynamoDB::AWSScriptBehaviorDynamoDB()
|
void AWSScriptBehaviorDynamoDB::Reflect(AZ::ReflectContext* context)
|
||||||
{
|
{
|
||||||
}
|
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||||
|
|
||||||
void AWSScriptBehaviorDynamoDB::ReflectSerialization(AZ::SerializeContext* serializeContext)
|
|
||||||
{
|
|
||||||
if (serializeContext)
|
|
||||||
{
|
{
|
||||||
serializeContext->Class<AWSScriptBehaviorDynamoDB>()
|
serializeContext->Class<AWSScriptBehaviorDynamoDB>()
|
||||||
->Version(0);
|
->Version(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void AWSScriptBehaviorDynamoDB::ReflectBehaviors(AZ::BehaviorContext* behaviorContext)
|
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||||
{
|
{
|
||||||
behaviorContext->Class<AWSScriptBehaviorDynamoDB>("AWSScriptBehaviorDynamoDB")
|
behaviorContext->Class<AWSScriptBehaviorDynamoDB>("AWSScriptBehaviorDynamoDB")
|
||||||
->Attribute(AZ::Script::Attributes::Category, "AWSCore")
|
->Attribute(AZ::Script::Attributes::Category, "AWSCore")
|
||||||
->Method("GetItem", &AWSScriptBehaviorDynamoDB::GetItem,
|
->Method("GetItem", &AWSScriptBehaviorDynamoDB::GetItem,
|
||||||
{{{"Table Resource KeyName", "The name of the table containing the requested item."},
|
{{{"Table Resource KeyName", "The name of the table containing the requested item."},
|
||||||
{"Key Map", "A map of attribute names to AttributeValue objects, representing the primary key of the item to retrieve."}}})
|
{"Key Map", "A map of attribute names to AttributeValue objects, representing the primary key of the item to retrieve."}}})
|
||||||
->Method("GetItemRaw", &AWSScriptBehaviorDynamoDB::GetItemRaw,
|
->Method("GetItemRaw", &AWSScriptBehaviorDynamoDB::GetItemRaw,
|
||||||
{{{"Table Name", "The name of the table containing the requested item."},
|
{{{"Table Name", "The name of the table containing the requested item."},
|
||||||
{"Key Map", "A map of attribute names to AttributeValue objects, representing the primary key of the item to retrieve."},
|
{"Key Map", "A map of attribute names to AttributeValue objects, representing the primary key of the item to retrieve."},
|
||||||
{"Region Name", "The region of the table located in."}}});
|
{"Region Name", "The region of the table located in."}}});
|
||||||
|
|
||||||
behaviorContext->EBus<AWSScriptBehaviorDynamoDBNotificationBus>("AWSDynamoDBBehaviorNotificationBus")
|
behaviorContext->EBus<AWSScriptBehaviorDynamoDBNotificationBus>("AWSDynamoDBBehaviorNotificationBus")
|
||||||
->Attribute(AZ::Script::Attributes::Category, "AWSCore")
|
->Attribute(AZ::Script::Attributes::Category, "AWSCore")
|
||||||
->Handler<AWSScriptBehaviorDynamoDBNotificationBusHandler>();
|
->Handler<AWSScriptBehaviorDynamoDBNotificationBusHandler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AWSScriptBehaviorDynamoDB::ReflectEditParameters(AZ::EditContext* editContext)
|
|
||||||
{
|
|
||||||
AZ_UNUSED(editContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AWSScriptBehaviorDynamoDB::GetItem(const AZStd::string& tableResourceKey, const DynamoDBAttributeValueMap& keyMap)
|
void AWSScriptBehaviorDynamoDB::GetItem(const AZStd::string& tableResourceKey, const DynamoDBAttributeValueMap& keyMap)
|
||||||
|
|||||||
@@ -21,39 +21,30 @@
|
|||||||
|
|
||||||
namespace AWSCore
|
namespace AWSCore
|
||||||
{
|
{
|
||||||
AWSScriptBehaviorLambda::AWSScriptBehaviorLambda()
|
void AWSScriptBehaviorLambda::Reflect(AZ::ReflectContext* context)
|
||||||
{
|
{
|
||||||
}
|
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||||
|
|
||||||
void AWSScriptBehaviorLambda::ReflectSerialization(AZ::SerializeContext* serializeContext)
|
|
||||||
{
|
|
||||||
if (serializeContext)
|
|
||||||
{
|
{
|
||||||
serializeContext->Class<AWSScriptBehaviorLambda>()
|
serializeContext->Class<AWSScriptBehaviorLambda>()
|
||||||
->Version(0);
|
->Version(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void AWSScriptBehaviorLambda::ReflectBehaviors(AZ::BehaviorContext* behaviorContext)
|
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||||
{
|
{
|
||||||
behaviorContext->Class<AWSScriptBehaviorLambda>("AWSScriptBehaviorLambda")
|
behaviorContext->Class<AWSScriptBehaviorLambda>("AWSScriptBehaviorLambda")
|
||||||
->Attribute(AZ::Script::Attributes::Category, "AWSCore")
|
->Attribute(AZ::Script::Attributes::Category, "AWSCore")
|
||||||
->Method("Invoke", &AWSScriptBehaviorLambda::Invoke,
|
->Method("Invoke", &AWSScriptBehaviorLambda::Invoke,
|
||||||
{{{"Function Resource KeyName", "The resource key name of the lambda function in resource mapping config file."},
|
{{{"Function Resource KeyName", "The resource key name of the lambda function in resource mapping config file."},
|
||||||
{"Payload", "The JSON that you want to provide to your Lambda function as input."}}})
|
{"Payload", "The JSON that you want to provide to your Lambda function as input."}}})
|
||||||
->Method("InvokeRaw", &AWSScriptBehaviorLambda::InvokeRaw,
|
->Method("InvokeRaw", &AWSScriptBehaviorLambda::InvokeRaw,
|
||||||
{{{"Function Name", "The name of the Lambda function, version, or alias."},
|
{{{"Function Name", "The name of the Lambda function, version, or alias."},
|
||||||
{"Payload", "The JSON that you want to provide to your Lambda function as input."},
|
{"Payload", "The JSON that you want to provide to your Lambda function as input."},
|
||||||
{"Region Name", "The region of the lambda function located in."}}});
|
{"Region Name", "The region of the lambda function located in."}}});
|
||||||
|
|
||||||
behaviorContext->EBus<AWSScriptBehaviorLambdaNotificationBus>("AWSLambdaBehaviorNotificationBus")
|
behaviorContext->EBus<AWSScriptBehaviorLambdaNotificationBus>("AWSLambdaBehaviorNotificationBus")
|
||||||
->Attribute(AZ::Script::Attributes::Category, "AWSCore")
|
->Attribute(AZ::Script::Attributes::Category, "AWSCore")
|
||||||
->Handler<AWSScriptBehaviorLambdaNotificationBusHandler>();
|
->Handler<AWSScriptBehaviorLambdaNotificationBusHandler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AWSScriptBehaviorLambda::ReflectEditParameters(AZ::EditContext* editContext)
|
|
||||||
{
|
|
||||||
AZ_UNUSED(editContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AWSScriptBehaviorLambda::Invoke(const AZStd::string& functionResourceKey, const AZStd::string& payload)
|
void AWSScriptBehaviorLambda::Invoke(const AZStd::string& functionResourceKey, const AZStd::string& payload)
|
||||||
|
|||||||
@@ -24,49 +24,39 @@
|
|||||||
|
|
||||||
namespace AWSCore
|
namespace AWSCore
|
||||||
{
|
{
|
||||||
AWSScriptBehaviorS3::AWSScriptBehaviorS3()
|
void AWSScriptBehaviorS3::Reflect(AZ::ReflectContext* context)
|
||||||
{
|
{
|
||||||
}
|
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||||
|
|
||||||
void AWSScriptBehaviorS3::ReflectSerialization(AZ::SerializeContext* serializeContext)
|
|
||||||
{
|
|
||||||
if (serializeContext)
|
|
||||||
{
|
{
|
||||||
serializeContext->Class<AWSScriptBehaviorS3>()
|
serializeContext->Class<AWSScriptBehaviorS3>()
|
||||||
->Version(0);
|
->Version(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void AWSScriptBehaviorS3::ReflectBehaviors(AZ::BehaviorContext* behaviorContext)
|
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||||
{
|
{
|
||||||
behaviorContext->Class<AWSScriptBehaviorS3>(AWSScriptBehaviorS3Name)
|
behaviorContext->Class<AWSScriptBehaviorS3>(AWSScriptBehaviorS3Name)
|
||||||
->Attribute(AZ::Script::Attributes::Category, "AWSCore")
|
->Attribute(AZ::Script::Attributes::Category, "AWSCore")
|
||||||
->Method("GetObject", &AWSScriptBehaviorS3::GetObject,
|
->Method("GetObject", &AWSScriptBehaviorS3::GetObject,
|
||||||
{{{"Bucket Resource KeyName", "The resource key name of the bucket in resource mapping config file."},
|
{{{"Bucket Resource KeyName", "The resource key name of the bucket in resource mapping config file."},
|
||||||
{"Object KeyName", "The object key."},
|
{"Object KeyName", "The object key."},
|
||||||
{"Outfile Name", "Filename where the content will be saved."}}})
|
{"Outfile Name", "Filename where the content will be saved."}}})
|
||||||
->Method("GetObjectRaw", &AWSScriptBehaviorS3::GetObjectRaw,
|
->Method("GetObjectRaw", &AWSScriptBehaviorS3::GetObjectRaw,
|
||||||
{{{"Bucket Name", "The name of the bucket containing the object."},
|
{{{"Bucket Name", "The name of the bucket containing the object."},
|
||||||
{"Object KeyName", "The object key."},
|
{"Object KeyName", "The object key."},
|
||||||
{"Region Name", "The region of the bucket located in."},
|
{"Region Name", "The region of the bucket located in."},
|
||||||
{"Outfile Name", "Filename where the content will be saved."}}})
|
{"Outfile Name", "Filename where the content will be saved."}}})
|
||||||
->Method("HeadObject", &AWSScriptBehaviorS3::HeadObject,
|
->Method("HeadObject", &AWSScriptBehaviorS3::HeadObject,
|
||||||
{{{"Bucket Resource KeyName", "The resource key name of the bucket in resource mapping config file."},
|
{{{"Bucket Resource KeyName", "The resource key name of the bucket in resource mapping config file."},
|
||||||
{"Object KeyName", "The object key."}}})
|
{"Object KeyName", "The object key."}}})
|
||||||
->Method("HeadObjectRaw", &AWSScriptBehaviorS3::HeadObjectRaw,
|
->Method("HeadObjectRaw", &AWSScriptBehaviorS3::HeadObjectRaw,
|
||||||
{{{"Bucket Name", "The name of the bucket containing the object."},
|
{{{"Bucket Name", "The name of the bucket containing the object."},
|
||||||
{"Object KeyName", "The object key."},
|
{"Object KeyName", "The object key."},
|
||||||
{"Region Name", "The region of the bucket located in."}}})
|
{"Region Name", "The region of the bucket located in."}}});
|
||||||
;
|
|
||||||
|
|
||||||
behaviorContext->EBus<AWSScriptBehaviorS3NotificationBus>("AWSS3BehaviorNotificationBus")
|
behaviorContext->EBus<AWSScriptBehaviorS3NotificationBus>("AWSS3BehaviorNotificationBus")
|
||||||
->Attribute(AZ::Script::Attributes::Category, "AWSCore")
|
->Attribute(AZ::Script::Attributes::Category, "AWSCore")
|
||||||
->Handler<AWSScriptBehaviorS3NotificationBusHandler>();
|
->Handler<AWSScriptBehaviorS3NotificationBusHandler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AWSScriptBehaviorS3::ReflectEditParameters(AZ::EditContext* editContext)
|
|
||||||
{
|
|
||||||
AZ_UNUSED(editContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AWSScriptBehaviorS3::GetObject(
|
void AWSScriptBehaviorS3::GetObject(
|
||||||
|
|||||||
@@ -12,35 +12,17 @@
|
|||||||
|
|
||||||
namespace AWSCore
|
namespace AWSCore
|
||||||
{
|
{
|
||||||
AZStd::vector<AZStd::unique_ptr<AWSScriptBehaviorBase>> AWSScriptBehaviorsComponent::m_behaviors;
|
|
||||||
bool AWSScriptBehaviorsComponent::m_alreadyAddedBehaviors = false;
|
|
||||||
|
|
||||||
void AWSScriptBehaviorsComponent::AddBehaviors()
|
|
||||||
{
|
|
||||||
if (!m_alreadyAddedBehaviors)
|
|
||||||
{
|
|
||||||
// Add new script behaviors here
|
|
||||||
m_behaviors.push_back(AZStd::make_unique<AWSScriptBehaviorDynamoDB>());
|
|
||||||
m_behaviors.push_back(AZStd::make_unique<AWSScriptBehaviorLambda>());
|
|
||||||
m_behaviors.push_back(AZStd::make_unique<AWSScriptBehaviorS3>());
|
|
||||||
m_alreadyAddedBehaviors = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AWSScriptBehaviorsComponent::Reflect(AZ::ReflectContext* context)
|
void AWSScriptBehaviorsComponent::Reflect(AZ::ReflectContext* context)
|
||||||
{
|
{
|
||||||
AddBehaviors();
|
AWSScriptBehaviorDynamoDB::Reflect(context);
|
||||||
|
AWSScriptBehaviorLambda::Reflect(context);
|
||||||
|
AWSScriptBehaviorS3::Reflect(context);
|
||||||
|
|
||||||
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
|
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
|
||||||
{
|
{
|
||||||
serialize->Class<AWSScriptBehaviorsComponent, AZ::Component>()
|
serialize->Class<AWSScriptBehaviorsComponent, AZ::Component>()
|
||||||
->Version(0);
|
->Version(0);
|
||||||
|
|
||||||
for (auto&& behavior : m_behaviors)
|
|
||||||
{
|
|
||||||
behavior->ReflectSerialization(serialize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AZ::EditContext* editContext = serialize->GetEditContext())
|
if (AZ::EditContext* editContext = serialize->GetEditContext())
|
||||||
{
|
{
|
||||||
editContext->Class<AWSScriptBehaviorsComponent>("AWSScriptBehaviors", "Provides ScriptCanvas functions for calling AWS")
|
editContext->Class<AWSScriptBehaviorsComponent>("AWSScriptBehaviors", "Provides ScriptCanvas functions for calling AWS")
|
||||||
@@ -49,19 +31,6 @@ namespace AWSCore
|
|||||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("AWS"))
|
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("AWS"))
|
||||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||||
;
|
;
|
||||||
|
|
||||||
for (auto&& behavior : m_behaviors)
|
|
||||||
{
|
|
||||||
behavior->ReflectEditParameters(editContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
|
||||||
{
|
|
||||||
for (auto&& behavior : m_behaviors)
|
|
||||||
{
|
|
||||||
behavior->ReflectBehaviors(behaviorContext);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,31 +55,12 @@ namespace AWSCore
|
|||||||
AZ_UNUSED(dependent);
|
AZ_UNUSED(dependent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AWSScriptBehaviorsComponent::Init()
|
|
||||||
{
|
|
||||||
for (auto&& behavior : m_behaviors)
|
|
||||||
{
|
|
||||||
behavior->Init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AWSScriptBehaviorsComponent::Activate()
|
void AWSScriptBehaviorsComponent::Activate()
|
||||||
{
|
{
|
||||||
for (auto&& behavior : m_behaviors)
|
|
||||||
{
|
|
||||||
behavior->Activate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AWSScriptBehaviorsComponent::Deactivate()
|
void AWSScriptBehaviorsComponent::Deactivate()
|
||||||
{
|
{
|
||||||
for (auto&& behavior : m_behaviors)
|
|
||||||
{
|
|
||||||
behavior->Deactivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
// this forces the vector to release its capacity, clear/shrink_to_fit is not
|
|
||||||
m_behaviors.swap(AZStd::vector<AZStd::unique_ptr<AWSScriptBehaviorBase>>());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,18 +15,6 @@
|
|||||||
|
|
||||||
using namespace AWSCore;
|
using namespace AWSCore;
|
||||||
|
|
||||||
class AWSScriptBehaviorsComponentMock
|
|
||||||
: public AWSScriptBehaviorsComponent
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AZ_COMPONENT(AWSScriptBehaviorsComponentMock, "{78579706-E1B2-4788-A34D-A58D3F273FF9}");
|
|
||||||
|
|
||||||
int GetBehaviorsNum()
|
|
||||||
{
|
|
||||||
return m_behaviors.size();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class AWSScriptBehaviorsComponentTest
|
class AWSScriptBehaviorsComponentTest
|
||||||
: public UnitTest::ScopedAllocatorSetupFixture
|
: public UnitTest::ScopedAllocatorSetupFixture
|
||||||
{
|
{
|
||||||
@@ -38,7 +26,7 @@ public:
|
|||||||
m_behaviorContext = AZStd::make_unique<AZ::BehaviorContext>();
|
m_behaviorContext = AZStd::make_unique<AZ::BehaviorContext>();
|
||||||
|
|
||||||
m_entity = AZStd::make_unique<AZ::Entity>();
|
m_entity = AZStd::make_unique<AZ::Entity>();
|
||||||
m_scriptBehaviorsComponent.reset(m_entity->CreateComponent<AWSScriptBehaviorsComponentMock>());
|
m_scriptBehaviorsComponent.reset(m_entity->CreateComponent<AWSScriptBehaviorsComponent>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TearDown() override
|
void TearDown() override
|
||||||
@@ -56,20 +44,16 @@ protected:
|
|||||||
AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
|
AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
|
||||||
AZStd::unique_ptr<AZ::BehaviorContext> m_behaviorContext;
|
AZStd::unique_ptr<AZ::BehaviorContext> m_behaviorContext;
|
||||||
AZStd::unique_ptr<AZ::ComponentDescriptor> m_componentDescriptor;
|
AZStd::unique_ptr<AZ::ComponentDescriptor> m_componentDescriptor;
|
||||||
AZStd::unique_ptr<AWSScriptBehaviorsComponentMock> m_scriptBehaviorsComponent;
|
AZStd::unique_ptr<AWSScriptBehaviorsComponent> m_scriptBehaviorsComponent;
|
||||||
AZStd::unique_ptr<AZ::Entity> m_entity;
|
AZStd::unique_ptr<AZ::Entity> m_entity;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(AWSScriptBehaviorsComponentTest, InitActivateDeactivate_Call_GetExpectedNumOfAddedBehaviors)
|
TEST_F(AWSScriptBehaviorsComponentTest, Reflect)
|
||||||
{
|
{
|
||||||
m_componentDescriptor.reset(AWSScriptBehaviorsComponentMock::CreateDescriptor());
|
int oldEBusNum = m_behaviorContext->m_ebuses.size();
|
||||||
|
m_componentDescriptor.reset(AWSScriptBehaviorsComponent::CreateDescriptor());
|
||||||
m_componentDescriptor->Reflect(m_serializeContext.get());
|
m_componentDescriptor->Reflect(m_serializeContext.get());
|
||||||
m_componentDescriptor->Reflect(m_behaviorContext.get());
|
m_componentDescriptor->Reflect(m_behaviorContext.get());
|
||||||
EXPECT_TRUE(AWSScriptBehaviorsComponentMock::AddedBehaviours());
|
|
||||||
EXPECT_TRUE(m_scriptBehaviorsComponent->GetBehaviorsNum() == 3);
|
|
||||||
|
|
||||||
m_entity->Init();
|
EXPECT_TRUE(m_behaviorContext->m_ebuses.size() - oldEBusNum == 3);
|
||||||
m_entity->Activate();
|
|
||||||
m_entity->Deactivate();
|
|
||||||
EXPECT_TRUE(m_scriptBehaviorsComponent->GetBehaviorsNum() == 0);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ set(FILES
|
|||||||
Include/Public/Framework/ServiceRequestJobConfig.h
|
Include/Public/Framework/ServiceRequestJobConfig.h
|
||||||
Include/Public/Framework/Util.h
|
Include/Public/Framework/Util.h
|
||||||
Include/Public/ResourceMapping/AWSResourceMappingBus.h
|
Include/Public/ResourceMapping/AWSResourceMappingBus.h
|
||||||
Include/Public/ScriptCanvas/AWSScriptBehaviorBase.h
|
|
||||||
Include/Public/ScriptCanvas/AWSScriptBehaviorDynamoDB.h
|
Include/Public/ScriptCanvas/AWSScriptBehaviorDynamoDB.h
|
||||||
Include/Public/ScriptCanvas/AWSScriptBehaviorLambda.h
|
Include/Public/ScriptCanvas/AWSScriptBehaviorLambda.h
|
||||||
Include/Public/ScriptCanvas/AWSScriptBehaviorS3.h
|
Include/Public/ScriptCanvas/AWSScriptBehaviorS3.h
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ namespace AZ
|
|||||||
shaderVariantAssetBuilderDescriptor.m_name = "Shader Variant Asset Builder";
|
shaderVariantAssetBuilderDescriptor.m_name = "Shader Variant Asset Builder";
|
||||||
// Both "Shader Variant Asset Builder" and "Shader Asset Builder" produce ShaderVariantAsset products. If you update
|
// Both "Shader Variant Asset Builder" and "Shader Asset Builder" produce ShaderVariantAsset products. If you update
|
||||||
// ShaderVariantAsset you will need to update BOTH version numbers, not just "Shader Variant Asset Builder".
|
// ShaderVariantAsset you will need to update BOTH version numbers, not just "Shader Variant Asset Builder".
|
||||||
shaderVariantAssetBuilderDescriptor.m_version = 23; // ATOM-15472
|
shaderVariantAssetBuilderDescriptor.m_version = 24; // ATOM-15978
|
||||||
shaderVariantAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string::format("*.%s", RPI::ShaderVariantListSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
|
shaderVariantAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string::format("*.%s", RPI::ShaderVariantListSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
|
||||||
shaderVariantAssetBuilderDescriptor.m_busId = azrtti_typeid<ShaderVariantAssetBuilder>();
|
shaderVariantAssetBuilderDescriptor.m_busId = azrtti_typeid<ShaderVariantAssetBuilder>();
|
||||||
shaderVariantAssetBuilderDescriptor.m_createJobFunction = AZStd::bind(&ShaderVariantAssetBuilder::CreateJobs, &m_shaderVariantAssetBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
|
shaderVariantAssetBuilderDescriptor.m_createJobFunction = AZStd::bind(&ShaderVariantAssetBuilder::CreateJobs, &m_shaderVariantAssetBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
#include "ShaderAssetBuilder.h"
|
#include "ShaderAssetBuilder.h"
|
||||||
#include "ShaderBuilderUtility.h"
|
#include "ShaderBuilderUtility.h"
|
||||||
|
#include "SrgLayoutUtility.h"
|
||||||
#include "AzslData.h"
|
#include "AzslData.h"
|
||||||
#include "AzslCompiler.h"
|
#include "AzslCompiler.h"
|
||||||
#include <CommonFiles/Preprocessor.h>
|
#include <CommonFiles/Preprocessor.h>
|
||||||
@@ -520,6 +521,96 @@ namespace AZ
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool LoadSrgLayoutListFromShaderAssetBuilder(
|
||||||
|
const RHI::ShaderPlatformInterface* shaderPlatformInterface,
|
||||||
|
const AssetBuilderSDK::PlatformInfo& platformInfo,
|
||||||
|
const AzslCompiler& azslCompiler, const AZStd::string& shaderSourceFileFullPath,
|
||||||
|
const RPI::SupervariantIndex supervariantIndex,
|
||||||
|
const bool platformUsesRegisterSpaces,
|
||||||
|
RPI::ShaderResourceGroupLayoutList& srgLayoutList,
|
||||||
|
RootConstantData& rootConstantData)
|
||||||
|
{
|
||||||
|
auto srgJsonPathOutcome = ShaderBuilderUtility::ObtainBuildArtifactPathFromShaderAssetBuilder(
|
||||||
|
shaderPlatformInterface->GetAPIUniqueIndex(), platformInfo.m_identifier, shaderSourceFileFullPath, supervariantIndex.GetIndex(), AZ::RPI::ShaderAssetSubId::SrgJson);
|
||||||
|
if (!srgJsonPathOutcome.IsSuccess())
|
||||||
|
{
|
||||||
|
AZ_Error(ShaderVariantAssetBuilderName, false, "%s", srgJsonPathOutcome.GetError().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto srgJsonPath = srgJsonPathOutcome.TakeValue();
|
||||||
|
auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(srgJsonPath);
|
||||||
|
if (!jsonOutcome.IsSuccess())
|
||||||
|
{
|
||||||
|
AZ_Error(ShaderVariantAssetBuilderName, false, "%s", jsonOutcome.GetError().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SrgDataContainer srgData;
|
||||||
|
if (!azslCompiler.ParseSrgPopulateSrgData(jsonOutcome.GetValue(), srgData))
|
||||||
|
{
|
||||||
|
AZ_Error(ShaderVariantAssetBuilderName, false, "Failed to parse srg data");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Add all Shader Resource Group Assets that were defined in the shader code to the shader asset
|
||||||
|
if (!SrgLayoutUtility::LoadShaderResourceGroupLayouts(ShaderVariantAssetBuilderName, srgData, platformUsesRegisterSpaces, srgLayoutList))
|
||||||
|
{
|
||||||
|
AZ_Error(ShaderVariantAssetBuilderName, false, "Failed to load ShaderResourceGroupLayouts");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto srgLayout : srgLayoutList)
|
||||||
|
{
|
||||||
|
if (!srgLayout->Finalize())
|
||||||
|
{
|
||||||
|
AZ_Error(ShaderVariantAssetBuilderName, false,
|
||||||
|
"Failed to finalize SrgLayout %s", srgLayout->GetName().GetCStr());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Access the root constants reflection
|
||||||
|
if (!azslCompiler.ParseSrgPopulateRootConstantData(
|
||||||
|
jsonOutcome.GetValue(),
|
||||||
|
rootConstantData)) // consuming data from --srg ("InlineConstantBuffer" subjson section)
|
||||||
|
{
|
||||||
|
AZ_Error(ShaderVariantAssetBuilderName, false, "Failed to obtain root constant data reflection");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool LoadBindingDependenciesFromShaderAssetBuilder(
|
||||||
|
const RHI::ShaderPlatformInterface* shaderPlatformInterface,
|
||||||
|
const AssetBuilderSDK::PlatformInfo& platformInfo,
|
||||||
|
const AzslCompiler& azslCompiler, const AZStd::string& shaderSourceFileFullPath,
|
||||||
|
const RPI::SupervariantIndex supervariantIndex,
|
||||||
|
BindingDependencies& bindingDependencies)
|
||||||
|
{
|
||||||
|
auto bindingsJsonPathOutcome = ShaderBuilderUtility::ObtainBuildArtifactPathFromShaderAssetBuilder(
|
||||||
|
shaderPlatformInterface->GetAPIUniqueIndex(), platformInfo.m_identifier, shaderSourceFileFullPath, supervariantIndex.GetIndex(), AZ::RPI::ShaderAssetSubId::BindingdepJson);
|
||||||
|
if (!bindingsJsonPathOutcome.IsSuccess())
|
||||||
|
{
|
||||||
|
AZ_Error(ShaderVariantAssetBuilderName, false, "%s", bindingsJsonPathOutcome.GetError().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bindingsJsonPath = bindingsJsonPathOutcome.TakeValue();
|
||||||
|
auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(bindingsJsonPath);
|
||||||
|
if (!jsonOutcome.IsSuccess())
|
||||||
|
{
|
||||||
|
AZ_Error(ShaderVariantAssetBuilderName, false, "%s", jsonOutcome.GetError().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!azslCompiler.ParseBindingdepPopulateBindingDependencies(jsonOutcome.GetValue(), bindingDependencies))
|
||||||
|
{
|
||||||
|
AZ_Error(ShaderVariantAssetBuilderName, false, "Failed to parse binding dependencies data");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns the content of the hlsl file for the given supervariant as produced by ShaderAsssetBuilder.
|
// Returns the content of the hlsl file for the given supervariant as produced by ShaderAsssetBuilder.
|
||||||
@@ -773,6 +864,50 @@ namespace AZ
|
|||||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
|
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! It is important to keep this refcounted pointer outside of the if block to prevent it from being destroyed.
|
||||||
|
RHI::Ptr<RHI::PipelineLayoutDescriptor> pipelineLayoutDescriptor;
|
||||||
|
if (shaderPlatformInterface->VariantCompilationRequiresSrgLayoutData())
|
||||||
|
{
|
||||||
|
AZStd::string azslcCompilerParameters =
|
||||||
|
shaderPlatformInterface->GetAzslCompilerParameters(buildOptions.m_compilerArguments);
|
||||||
|
const bool platformUsesRegisterSpaces =
|
||||||
|
(AzFramework::StringFunc::Find(azslcCompilerParameters, "--use-spaces") != AZStd::string::npos);
|
||||||
|
|
||||||
|
RPI::ShaderResourceGroupLayoutList srgLayoutList;
|
||||||
|
RootConstantData rootConstantData;
|
||||||
|
if (!LoadSrgLayoutListFromShaderAssetBuilder(
|
||||||
|
shaderPlatformInterface, request.m_platformInfo, azslc, shaderSourceFileFullPath, supervariantIndex,
|
||||||
|
platformUsesRegisterSpaces,
|
||||||
|
srgLayoutList,
|
||||||
|
rootConstantData))
|
||||||
|
{
|
||||||
|
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BindingDependencies bindingDependencies;
|
||||||
|
if (!LoadBindingDependenciesFromShaderAssetBuilder(
|
||||||
|
shaderPlatformInterface, request.m_platformInfo, azslc, shaderSourceFileFullPath, supervariantIndex,
|
||||||
|
bindingDependencies))
|
||||||
|
{
|
||||||
|
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipelineLayoutDescriptor =
|
||||||
|
ShaderBuilderUtility::BuildPipelineLayoutDescriptorForApi(
|
||||||
|
ShaderVariantAssetBuilderName, srgLayoutList, shaderEntryPoints, buildOptions.m_compilerArguments, rootConstantData,
|
||||||
|
shaderPlatformInterface, bindingDependencies);
|
||||||
|
if (!pipelineLayoutDescriptor)
|
||||||
|
{
|
||||||
|
AZ_Error(
|
||||||
|
ShaderVariantAssetBuilderName, false, "Failed to build pipeline layout descriptor for api=[%s]",
|
||||||
|
shaderPlatformInterface->GetAPIName().GetCStr());
|
||||||
|
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Setup the shader variant creation context:
|
// Setup the shader variant creation context:
|
||||||
ShaderVariantCreationContext shaderVariantCreationContext =
|
ShaderVariantCreationContext shaderVariantCreationContext =
|
||||||
|
|||||||
@@ -144,6 +144,12 @@ namespace AZ
|
|||||||
const ShaderResourceGroupInfoList& srgInfoList,
|
const ShaderResourceGroupInfoList& srgInfoList,
|
||||||
const RootConstantsInfo& rootConstantsInfo,
|
const RootConstantsInfo& rootConstantsInfo,
|
||||||
const ShaderCompilerArguments& shaderCompilerArguments) = 0;
|
const ShaderCompilerArguments& shaderCompilerArguments) = 0;
|
||||||
|
|
||||||
|
//! In general, shader compilation doesn't require SRG Layout data, but RHIs like
|
||||||
|
//! Metal don't do well if unused resources (descriptors) are not bound. If this function returns TRUE
|
||||||
|
//! the ShaderVariantAssetBuilder will invoke BuildPipelineLayoutDescriptor() so the RHI gets the chance to
|
||||||
|
//! build SRG Layout data which will be useful when compiling MetalISL to Metal byte code.
|
||||||
|
virtual bool VariantCompilationRequiresSrgLayoutData() const { return false; }
|
||||||
|
|
||||||
//! See AZ::RHI::Factory::GetAPIUniqueIndex() for details.
|
//! See AZ::RHI::Factory::GetAPIUniqueIndex() for details.
|
||||||
//! See AZ::RHI::Limits::APIType::PerPlatformApiUniqueIndexMax.
|
//! See AZ::RHI::Limits::APIType::PerPlatformApiUniqueIndexMax.
|
||||||
|
|||||||
@@ -159,7 +159,13 @@ namespace AZ
|
|||||||
arguments += " -Zi"; // Generate debug information
|
arguments += " -Zi"; // Generate debug information
|
||||||
arguments += " -Zss"; // Compute Shader Hash considering source information
|
arguments += " -Zss"; // Compute Shader Hash considering source information
|
||||||
}
|
}
|
||||||
arguments += " " + m_dxcAdditionalFreeArguments;
|
// strip spaces at both sides
|
||||||
|
AZStd::string dxcAdditionalFreeArguments = m_dxcAdditionalFreeArguments;
|
||||||
|
AzFramework::StringFunc::TrimWhiteSpace(dxcAdditionalFreeArguments, true, true);
|
||||||
|
if (!dxcAdditionalFreeArguments.empty())
|
||||||
|
{
|
||||||
|
arguments += " " + dxcAdditionalFreeArguments;
|
||||||
|
}
|
||||||
return arguments;
|
return arguments;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ namespace AZ
|
|||||||
const ShaderResourceGroupInfoList& srgInfoList,
|
const ShaderResourceGroupInfoList& srgInfoList,
|
||||||
const RootConstantsInfo& rootConstantsInfo,
|
const RootConstantsInfo& rootConstantsInfo,
|
||||||
const RHI::ShaderCompilerArguments& shaderCompilerArguments) override;
|
const RHI::ShaderCompilerArguments& shaderCompilerArguments) override;
|
||||||
|
|
||||||
|
bool VariantCompilationRequiresSrgLayoutData() const override { return true; }
|
||||||
|
|
||||||
bool CompilePlatformInternal(
|
bool CompilePlatformInternal(
|
||||||
const AssetBuilderSDK::PlatformInfo& platform,
|
const AssetBuilderSDK::PlatformInfo& platform,
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace AZ
|
|||||||
{
|
{
|
||||||
AZ_UNUSED(device);
|
AZ_UNUSED(device);
|
||||||
m_hardwareQueueClass = hardwareQueueClass;
|
m_hardwareQueueClass = hardwareQueueClass;
|
||||||
|
m_supportsInterDrawTimestamps = AZ::RHI::QueryTypeFlags::Timestamp == (device->GetFeatures().m_queryTypesMask[static_cast<uint32_t>(hardwareQueueClass)] & AZ::RHI::QueryTypeFlags::Timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandListBase::Reset()
|
void CommandListBase::Reset()
|
||||||
@@ -64,7 +65,10 @@ namespace AZ
|
|||||||
[m_encoder endEncoding];
|
[m_encoder endEncoding];
|
||||||
m_encoder = nil;
|
m_encoder = nil;
|
||||||
#if AZ_TRAIT_ATOM_METAL_COUNTER_SAMPLING
|
#if AZ_TRAIT_ATOM_METAL_COUNTER_SAMPLING
|
||||||
m_timeStampQueue.clear();
|
if (m_supportsInterDrawTimestamps)
|
||||||
|
{
|
||||||
|
m_timeStampQueue.clear();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,9 +148,12 @@ namespace AZ
|
|||||||
m_isEncoded = true;
|
m_isEncoded = true;
|
||||||
|
|
||||||
#if AZ_TRAIT_ATOM_METAL_COUNTER_SAMPLING
|
#if AZ_TRAIT_ATOM_METAL_COUNTER_SAMPLING
|
||||||
for(auto& timeStamp: m_timeStampQueue)
|
if (m_supportsInterDrawTimestamps)
|
||||||
{
|
{
|
||||||
SampleCounters(timeStamp.m_counterSampleBuffer, timeStamp.m_timeStampIndex);
|
for(auto& timeStamp: m_timeStampQueue)
|
||||||
|
{
|
||||||
|
SampleCounters(timeStamp.m_counterSampleBuffer, timeStamp.m_timeStampIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -195,6 +202,11 @@ namespace AZ
|
|||||||
#if AZ_TRAIT_ATOM_METAL_COUNTER_SAMPLING
|
#if AZ_TRAIT_ATOM_METAL_COUNTER_SAMPLING
|
||||||
void CommandListBase::SampleCounters(id<MTLCounterSampleBuffer> counterSampleBuffer, uint32_t sampleIndex)
|
void CommandListBase::SampleCounters(id<MTLCounterSampleBuffer> counterSampleBuffer, uint32_t sampleIndex)
|
||||||
{
|
{
|
||||||
|
if (!m_supportsInterDrawTimestamps)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AZ_Assert(sampleIndex >= 0, "Invalid sample index");
|
AZ_Assert(sampleIndex >= 0, "Invalid sample index");
|
||||||
//useBarrier - Inserting a barrier ensures that encoded work is complete before the GPU samples the hardware counters.
|
//useBarrier - Inserting a barrier ensures that encoded work is complete before the GPU samples the hardware counters.
|
||||||
//If it is true there is a performance penalty but you will get consistent results
|
//If it is true there is a performance penalty but you will get consistent results
|
||||||
@@ -231,6 +243,11 @@ namespace AZ
|
|||||||
|
|
||||||
void CommandListBase::SamplePassCounters(id<MTLCounterSampleBuffer> counterSampleBuffer, uint32_t sampleIndex)
|
void CommandListBase::SamplePassCounters(id<MTLCounterSampleBuffer> counterSampleBuffer, uint32_t sampleIndex)
|
||||||
{
|
{
|
||||||
|
if (!m_supportsInterDrawTimestamps)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(m_encoder == nil)
|
if(m_encoder == nil)
|
||||||
{
|
{
|
||||||
//Queue the query to be activated upon encoder creation. Applies to timestamp queries
|
//Queue the query to be activated upon encoder creation. Applies to timestamp queries
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ namespace AZ
|
|||||||
|
|
||||||
const AZStd::set<id<MTLHeap>>* m_residentHeaps = nullptr;
|
const AZStd::set<id<MTLHeap>>* m_residentHeaps = nullptr;
|
||||||
|
|
||||||
|
bool m_supportsInterDrawTimestamps = AZ_TRAIT_ATOM_METAL_COUNTER_SAMPLING; // iOS/TVOS = false, MacOS = defaults to true
|
||||||
|
|
||||||
#if AZ_TRAIT_ATOM_METAL_COUNTER_SAMPLING
|
#if AZ_TRAIT_ATOM_METAL_COUNTER_SAMPLING
|
||||||
struct TimeStampData
|
struct TimeStampData
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -328,14 +328,28 @@ namespace AZ
|
|||||||
m_features.m_indirectDrawSupport = false;
|
m_features.m_indirectDrawSupport = false;
|
||||||
|
|
||||||
RHI::QueryTypeFlags counterSamplingFlags = RHI::QueryTypeFlags::None;
|
RHI::QueryTypeFlags counterSamplingFlags = RHI::QueryTypeFlags::None;
|
||||||
|
|
||||||
#if AZ_TRAIT_ATOM_METAL_COUNTER_SAMPLING
|
bool supportsInterDrawTimestamps = true;
|
||||||
counterSamplingFlags |= (RHI::QueryTypeFlags::Timestamp | RHI::QueryTypeFlags::PipelineStatistics);
|
#if defined(__IPHONE_14_0) || defined(__MAC_11_0) || defined(__TVOS_14_0)
|
||||||
m_features.m_queryTypesMask[static_cast<uint32_t>(RHI::HardwareQueueClass::Copy)] = RHI::QueryTypeFlags::Timestamp;
|
if (@available(macOS 11.0, iOS 14, tvOS 14, *))
|
||||||
|
{
|
||||||
|
supportsInterDrawTimestamps = [m_metalDevice supportsCounterSampling:MTLCounterSamplingPointAtDrawBoundary];
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
supportsInterDrawTimestamps = ![m_metalDevice.name containsString:@"Apple"]; // Apple GPU's don't support inter draw timestamps at the M1/A14 generation
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportsInterDrawTimestamps)
|
||||||
|
{
|
||||||
|
counterSamplingFlags |= (RHI::QueryTypeFlags::Timestamp | RHI::QueryTypeFlags::PipelineStatistics);
|
||||||
|
m_features.m_queryTypesMask[static_cast<uint32_t>(RHI::HardwareQueueClass::Copy)] = RHI::QueryTypeFlags::Timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
m_features.m_queryTypesMask[static_cast<uint32_t>(RHI::HardwareQueueClass::Graphics)] = RHI::QueryTypeFlags::Occlusion | counterSamplingFlags;
|
m_features.m_queryTypesMask[static_cast<uint32_t>(RHI::HardwareQueueClass::Graphics)] = RHI::QueryTypeFlags::Occlusion | counterSamplingFlags;
|
||||||
//Compute queue can do gfx work
|
//Compute queue can do gfx work
|
||||||
m_features.m_queryTypesMask[static_cast<uint32_t>(RHI::HardwareQueueClass::Compute)] = RHI::QueryTypeFlags::Occlusion |counterSamplingFlags;
|
m_features.m_queryTypesMask[static_cast<uint32_t>(RHI::HardwareQueueClass::Compute)] = RHI::QueryTypeFlags::Occlusion | counterSamplingFlags;
|
||||||
m_features.m_occlusionQueryPrecise = true;
|
m_features.m_occlusionQueryPrecise = true;
|
||||||
|
|
||||||
//Values taken from https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
|
//Values taken from https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
|
||||||
|
|||||||
@@ -218,7 +218,8 @@ namespace AZ
|
|||||||
createInfo.extent = extent;
|
createInfo.extent = extent;
|
||||||
createInfo.mipLevels = AZStd::min<uint32_t>(descriptor.m_mipLevels, formatProps.maxMipLevels);
|
createInfo.mipLevels = AZStd::min<uint32_t>(descriptor.m_mipLevels, formatProps.maxMipLevels);
|
||||||
createInfo.arrayLayers = AZStd::min<uint32_t>(descriptor.m_arraySize, formatProps.maxArrayLayers);
|
createInfo.arrayLayers = AZStd::min<uint32_t>(descriptor.m_arraySize, formatProps.maxArrayLayers);
|
||||||
createInfo.samples = static_cast<VkSampleCountFlagBits>(RHI::FilterBits(static_cast<VkSampleCountFlags>(ConvertSampleCount(descriptor.m_multisampleState.m_samples)), formatProps.sampleCounts));
|
VkSampleCountFlagBits sampleCountFlagBits = static_cast<VkSampleCountFlagBits>(RHI::FilterBits(static_cast<VkSampleCountFlags>(ConvertSampleCount(descriptor.m_multisampleState.m_samples)), formatProps.sampleCounts));
|
||||||
|
createInfo.samples = (static_cast<uint32_t>(sampleCountFlagBits) > 0) ? sampleCountFlagBits : VK_SAMPLE_COUNT_1_BIT;
|
||||||
createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
createInfo.usage = GetImageUsageFlags();
|
createInfo.usage = GetImageUsageFlags();
|
||||||
createInfo.sharingMode = exclusiveOwnership ? VK_SHARING_MODE_EXCLUSIVE : VK_SHARING_MODE_CONCURRENT;
|
createInfo.sharingMode = exclusiveOwnership ? VK_SHARING_MODE_EXCLUSIVE : VK_SHARING_MODE_CONCURRENT;
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ namespace AZ
|
|||||||
{
|
{
|
||||||
AZ_Assert(IsQueryTypeValid(queryType), "Provided QueryType is invalid");
|
AZ_Assert(IsQueryTypeValid(queryType), "Provided QueryType is invalid");
|
||||||
|
|
||||||
return static_cast<uint32_t>(m_queryTypeSupport) & static_cast<uint32_t>(queryType);
|
return static_cast<uint32_t>(m_queryTypeSupport) & AZ_BIT(static_cast<uint32_t>(queryType));
|
||||||
}
|
}
|
||||||
|
|
||||||
RPI::QueryPool* GpuQuerySystem::GetQueryPoolByType(RHI::QueryType queryType)
|
RPI::QueryPool* GpuQuerySystem::GetQueryPoolByType(RHI::QueryType queryType)
|
||||||
|
|||||||
@@ -237,8 +237,8 @@ namespace EditorPythonBindings
|
|||||||
{
|
{
|
||||||
ec->Class<PythonSystemComponent>("PythonSystemComponent", "The Python interpreter")
|
ec->Class<PythonSystemComponent>("PythonSystemComponent", "The Python interpreter")
|
||||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System"))
|
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System"))
|
||||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,10 +284,10 @@ namespace EditorPythonBindings
|
|||||||
ReleaseFunction m_releaseFunction;
|
ReleaseFunction m_releaseFunction;
|
||||||
};
|
};
|
||||||
ReleaseInitalizeWaiterScope scope([this]()
|
ReleaseInitalizeWaiterScope scope([this]()
|
||||||
{
|
{
|
||||||
m_initalizeWaiter.release(m_initalizeWaiterCount);
|
m_initalizeWaiter.release(m_initalizeWaiterCount);
|
||||||
m_initalizeWaiterCount = 0;
|
m_initalizeWaiterCount = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Py_IsInitialized())
|
if (Py_IsInitialized())
|
||||||
{
|
{
|
||||||
@@ -327,6 +327,11 @@ namespace EditorPythonBindings
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PythonSystemComponent::IsPythonActive()
|
||||||
|
{
|
||||||
|
return Py_IsInitialized() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
void PythonSystemComponent::WaitForInitialization()
|
void PythonSystemComponent::WaitForInitialization()
|
||||||
{
|
{
|
||||||
m_initalizeWaiterCount++;
|
m_initalizeWaiterCount++;
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ namespace EditorPythonBindings
|
|||||||
// AzToolsFramework::EditorPythonEventsInterface
|
// AzToolsFramework::EditorPythonEventsInterface
|
||||||
bool StartPython(bool silenceWarnings = false) override;
|
bool StartPython(bool silenceWarnings = false) override;
|
||||||
bool StopPython(bool silenceWarnings = false) override;
|
bool StopPython(bool silenceWarnings = false) override;
|
||||||
|
bool IsPythonActive() override;
|
||||||
void WaitForInitialization() override;
|
void WaitForInitialization() override;
|
||||||
void ExecuteWithLock(AZStd::function<void()> executionCallback) override;
|
void ExecuteWithLock(AZStd::function<void()> executionCallback) override;
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -209,12 +209,17 @@ namespace Gestures
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
inline uint32_t IRecognizer::GetGesturePointerIndex(const AzFramework::InputChannel& inputChannel)
|
inline uint32_t IRecognizer::GetGesturePointerIndex(const AzFramework::InputChannel& inputChannel)
|
||||||
{
|
{
|
||||||
const auto& mouseButtonIt = AZStd::find(AzFramework::InputDeviceMouse::Button::All.cbegin(),
|
// Only recognize gestures for the default mouse input device. The Editor may register synthetic
|
||||||
AzFramework::InputDeviceMouse::Button::All.cend(),
|
// mouse input devices with the same mouse input channels, which can confuse gesture recognition.
|
||||||
inputChannel.GetInputChannelId());
|
if (inputChannel.GetInputDevice().GetInputDeviceId() == AzFramework::InputDeviceMouse::Id)
|
||||||
if (mouseButtonIt != AzFramework::InputDeviceMouse::Button::All.cend())
|
|
||||||
{
|
{
|
||||||
return static_cast<uint32_t>(mouseButtonIt - AzFramework::InputDeviceMouse::Button::All.cbegin());
|
const auto& mouseButtonIt = AZStd::find(AzFramework::InputDeviceMouse::Button::All.cbegin(),
|
||||||
|
AzFramework::InputDeviceMouse::Button::All.cend(),
|
||||||
|
inputChannel.GetInputChannelId());
|
||||||
|
if (mouseButtonIt != AzFramework::InputDeviceMouse::Button::All.cend())
|
||||||
|
{
|
||||||
|
return static_cast<uint32_t>(mouseButtonIt - AzFramework::InputDeviceMouse::Button::All.cbegin());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& touchIndexIt = AZStd::find(AzFramework::InputDeviceTouch::Touch::All.cbegin(),
|
const auto& touchIndexIt = AZStd::find(AzFramework::InputDeviceTouch::Touch::All.cbegin(),
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
|||||||
AUTORCC
|
AUTORCC
|
||||||
FILES_CMAKE
|
FILES_CMAKE
|
||||||
lyshine_uicanvaseditor_files.cmake
|
lyshine_uicanvaseditor_files.cmake
|
||||||
lyshine_editor_builder_files.cmake
|
|
||||||
INCLUDE_DIRECTORIES
|
INCLUDE_DIRECTORIES
|
||||||
PRIVATE
|
PRIVATE
|
||||||
.
|
.
|
||||||
@@ -78,7 +77,6 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
|||||||
3rdParty::Qt::Widgets
|
3rdParty::Qt::Widgets
|
||||||
AZ::AzCore
|
AZ::AzCore
|
||||||
AZ::AzToolsFramework
|
AZ::AzToolsFramework
|
||||||
AZ::AssetBuilderSDK
|
|
||||||
Legacy::EditorCommon
|
Legacy::EditorCommon
|
||||||
Legacy::EditorCore
|
Legacy::EditorCore
|
||||||
Gem::LyShine.Static
|
Gem::LyShine.Static
|
||||||
@@ -98,7 +96,6 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
|||||||
|
|
||||||
ly_add_target(
|
ly_add_target(
|
||||||
NAME LyShine.Editor GEM_MODULE
|
NAME LyShine.Editor GEM_MODULE
|
||||||
|
|
||||||
NAMESPACE Gem
|
NAMESPACE Gem
|
||||||
FILES_CMAKE
|
FILES_CMAKE
|
||||||
lyshine_common_module_files.cmake
|
lyshine_common_module_files.cmake
|
||||||
@@ -115,17 +112,72 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
|||||||
BUILD_DEPENDENCIES
|
BUILD_DEPENDENCIES
|
||||||
PRIVATE
|
PRIVATE
|
||||||
Legacy::CryCommon
|
Legacy::CryCommon
|
||||||
AZ::AssetBuilderSDK
|
AZ::AzToolsFramework
|
||||||
Gem::LyShine.Editor.Static
|
Gem::LyShine.Editor.Static
|
||||||
Gem::LmbrCentral.Editor
|
Gem::LmbrCentral.Editor
|
||||||
Gem::TextureAtlas.Editor
|
Gem::TextureAtlas.Editor
|
||||||
RUNTIME_DEPENDENCIES
|
RUNTIME_DEPENDENCIES
|
||||||
Gem::LmbrCentral.Editor
|
Gem::LmbrCentral.Editor
|
||||||
Gem::TextureAtlas.Editor
|
Gem::TextureAtlas.Editor
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# by naming this target LyShine.Builders it ensures that it is loaded
|
||||||
|
# in any pipeline tools (Like Asset Processor, AssetBuilder, etc)
|
||||||
|
ly_add_target(
|
||||||
|
NAME LyShine.Builders.Static STATIC
|
||||||
|
NAMESPACE Gem
|
||||||
|
FILES_CMAKE
|
||||||
|
lyshine_editor_builder_files.cmake
|
||||||
|
INCLUDE_DIRECTORIES
|
||||||
|
PRIVATE
|
||||||
|
.
|
||||||
|
Source
|
||||||
|
PUBLIC
|
||||||
|
Include
|
||||||
|
BUILD_DEPENDENCIES
|
||||||
|
PRIVATE
|
||||||
|
AZ::AzCore
|
||||||
|
AZ::AzToolsFramework
|
||||||
|
AZ::AssetBuilderSDK
|
||||||
|
Gem::LyShine.Static
|
||||||
|
Legacy::CryCommon
|
||||||
|
Gem::LmbrCentral.Editor
|
||||||
|
Gem::TextureAtlas.Editor
|
||||||
|
Gem::AtomToolsFramework.Static
|
||||||
|
Gem::AtomToolsFramework.Editor
|
||||||
|
${additional_dependencies}
|
||||||
|
PUBLIC
|
||||||
|
Gem::Atom_RPI.Public
|
||||||
|
Gem::Atom_Utils.Static
|
||||||
|
Gem::Atom_Bootstrap.Headers
|
||||||
|
)
|
||||||
|
|
||||||
|
ly_add_target(
|
||||||
|
NAME LyShine.Builders GEM_MODULE
|
||||||
|
NAMESPACE Gem
|
||||||
|
OUTPUT_NAME Gem.LyShine.Builders
|
||||||
|
FILES_CMAKE
|
||||||
|
lyshine_common_module_files.cmake
|
||||||
|
COMPILE_DEFINITIONS
|
||||||
|
PRIVATE
|
||||||
|
LYSHINE_BUILDER
|
||||||
|
INCLUDE_DIRECTORIES
|
||||||
|
PRIVATE
|
||||||
|
.
|
||||||
|
Source
|
||||||
|
Editor
|
||||||
|
PUBLIC
|
||||||
|
Include
|
||||||
|
BUILD_DEPENDENCIES
|
||||||
|
PRIVATE
|
||||||
|
Legacy::CryCommon
|
||||||
|
AZ::AssetBuilderSDK
|
||||||
|
Gem::LyShine.Builders.Static
|
||||||
|
Gem::LmbrCentral.Editor
|
||||||
|
Gem::TextureAtlas.Editor
|
||||||
|
)
|
||||||
|
|
||||||
# by default, load the above "Gem::LyShine.Editor" module in dev tools:
|
# by default, load the above "Gem::LyShine.Editor" module in dev tools:
|
||||||
ly_create_alias(NAME LyShine.Builders NAMESPACE Gem TARGETS Gem::LyShine.Editor)
|
|
||||||
ly_create_alias(NAME LyShine.Tools NAMESPACE Gem TARGETS Gem::LyShine.Editor)
|
ly_create_alias(NAME LyShine.Tools NAMESPACE Gem TARGETS Gem::LyShine.Editor)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -169,6 +221,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
|||||||
COMPILE_DEFINITIONS
|
COMPILE_DEFINITIONS
|
||||||
PRIVATE
|
PRIVATE
|
||||||
LYSHINE_EDITOR
|
LYSHINE_EDITOR
|
||||||
|
LYSHINE_BUILDER
|
||||||
INCLUDE_DIRECTORIES
|
INCLUDE_DIRECTORIES
|
||||||
PRIVATE
|
PRIVATE
|
||||||
Tests
|
Tests
|
||||||
@@ -182,6 +235,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
|||||||
Legacy::CryCommon
|
Legacy::CryCommon
|
||||||
AZ::AssetBuilderSDK
|
AZ::AssetBuilderSDK
|
||||||
Gem::LyShine.Editor.Static
|
Gem::LyShine.Editor.Static
|
||||||
|
Gem::LyShine.Builders.Static
|
||||||
Gem::LmbrCentral.Editor
|
Gem::LmbrCentral.Editor
|
||||||
Gem::TextureAtlas
|
Gem::TextureAtlas
|
||||||
RUNTIME_DEPENDENCIES
|
RUNTIME_DEPENDENCIES
|
||||||
|
|||||||
@@ -52,9 +52,9 @@
|
|||||||
#include "World/UiCanvasProxyRefComponent.h"
|
#include "World/UiCanvasProxyRefComponent.h"
|
||||||
#include "World/UiCanvasOnMeshComponent.h"
|
#include "World/UiCanvasOnMeshComponent.h"
|
||||||
|
|
||||||
#if defined (LYSHINE_EDITOR)
|
#if defined(LYSHINE_BUILDER)
|
||||||
# include "Pipeline/LyShineBuilder/LyShineBuilderComponent.h"
|
#include "Pipeline/LyShineBuilder/LyShineBuilderComponent.h"
|
||||||
#endif // LYSHINE_EDITOR
|
#endif // LYSHINE_BUILDER
|
||||||
|
|
||||||
namespace LyShine
|
namespace LyShine
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ namespace LyShine
|
|||||||
// Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
|
// Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
|
||||||
m_descriptors.insert(m_descriptors.end(), {
|
m_descriptors.insert(m_descriptors.end(), {
|
||||||
LyShineSystemComponent::CreateDescriptor(),
|
LyShineSystemComponent::CreateDescriptor(),
|
||||||
#if defined (LYSHINE_EDITOR)
|
#if defined(LYSHINE_EDITOR)
|
||||||
LyShineEditor::LyShineEditorSystemComponent::CreateDescriptor(),
|
LyShineEditor::LyShineEditorSystemComponent::CreateDescriptor(),
|
||||||
#endif
|
#endif
|
||||||
UiCanvasAssetRefComponent::CreateDescriptor(),
|
UiCanvasAssetRefComponent::CreateDescriptor(),
|
||||||
@@ -103,7 +103,7 @@ namespace LyShine
|
|||||||
UiRadioButtonComponent::CreateDescriptor(),
|
UiRadioButtonComponent::CreateDescriptor(),
|
||||||
UiRadioButtonGroupComponent::CreateDescriptor(),
|
UiRadioButtonGroupComponent::CreateDescriptor(),
|
||||||
UiParticleEmitterComponent::CreateDescriptor(),
|
UiParticleEmitterComponent::CreateDescriptor(),
|
||||||
#if defined(LYSHINE_EDITOR)
|
#if defined(LYSHINE_BUILDER)
|
||||||
// Builder
|
// Builder
|
||||||
LyShineBuilder::LyShineBuilderComponent::CreateDescriptor(),
|
LyShineBuilder::LyShineBuilderComponent::CreateDescriptor(),
|
||||||
#endif
|
#endif
|
||||||
@@ -123,7 +123,7 @@ namespace LyShine
|
|||||||
{
|
{
|
||||||
return AZ::ComponentTypeList{
|
return AZ::ComponentTypeList{
|
||||||
azrtti_typeid<LyShineSystemComponent>(),
|
azrtti_typeid<LyShineSystemComponent>(),
|
||||||
#if defined (LYSHINE_EDITOR)
|
#if defined(LYSHINE_EDITOR)
|
||||||
azrtti_typeid<LyShineEditor::LyShineEditorSystemComponent>(),
|
azrtti_typeid<LyShineEditor::LyShineEditorSystemComponent>(),
|
||||||
#endif
|
#endif
|
||||||
#if AZ_LOADSCREENCOMPONENT_ENABLED
|
#if AZ_LOADSCREENCOMPONENT_ENABLED
|
||||||
|
|||||||
@@ -148,7 +148,6 @@ namespace LyShine
|
|||||||
{
|
{
|
||||||
LyShineAllocatorScope::ActivateAllocators();
|
LyShineAllocatorScope::ActivateAllocators();
|
||||||
|
|
||||||
LyShineRequestBus::Handler::BusConnect();
|
|
||||||
UiSystemBus::Handler::BusConnect();
|
UiSystemBus::Handler::BusConnect();
|
||||||
UiSystemToolsBus::Handler::BusConnect();
|
UiSystemToolsBus::Handler::BusConnect();
|
||||||
UiFrameworkBus::Handler::BusConnect();
|
UiFrameworkBus::Handler::BusConnect();
|
||||||
@@ -196,7 +195,6 @@ namespace LyShine
|
|||||||
UiSystemBus::Handler::BusDisconnect();
|
UiSystemBus::Handler::BusDisconnect();
|
||||||
UiSystemToolsBus::Handler::BusDisconnect();
|
UiSystemToolsBus::Handler::BusDisconnect();
|
||||||
UiFrameworkBus::Handler::BusDisconnect();
|
UiFrameworkBus::Handler::BusDisconnect();
|
||||||
LyShineRequestBus::Handler::BusDisconnect();
|
|
||||||
CrySystemEventBus::Handler::BusDisconnect();
|
CrySystemEventBus::Handler::BusDisconnect();
|
||||||
|
|
||||||
LyShineAllocatorScope::DeactivateAllocators();
|
LyShineAllocatorScope::DeactivateAllocators();
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include <LmbrCentral/Rendering/MaterialAsset.h>
|
#include <LmbrCentral/Rendering/MaterialAsset.h>
|
||||||
|
|
||||||
#include <LyShine/LyShineBus.h>
|
|
||||||
#include <LyShine/Bus/UiSystemBus.h>
|
#include <LyShine/Bus/UiSystemBus.h>
|
||||||
#include <LyShine/Bus/UiCanvasManagerBus.h>
|
#include <LyShine/Bus/UiCanvasManagerBus.h>
|
||||||
#include <LyShine/Bus/Tools/UiSystemToolsBus.h>
|
#include <LyShine/Bus/Tools/UiSystemToolsBus.h>
|
||||||
@@ -28,7 +27,6 @@ namespace LyShine
|
|||||||
|
|
||||||
class LyShineSystemComponent
|
class LyShineSystemComponent
|
||||||
: public AZ::Component
|
: public AZ::Component
|
||||||
, protected LyShineRequestBus::Handler
|
|
||||||
, protected UiSystemBus::Handler
|
, protected UiSystemBus::Handler
|
||||||
, protected UiSystemToolsBus::Handler
|
, protected UiSystemToolsBus::Handler
|
||||||
, protected LyShineAllocatorScope
|
, protected LyShineAllocatorScope
|
||||||
|
|||||||
@@ -8,4 +8,6 @@
|
|||||||
set(FILES
|
set(FILES
|
||||||
Source/LyShineModule.cpp
|
Source/LyShineModule.cpp
|
||||||
Source/LyShineModule.h
|
Source/LyShineModule.h
|
||||||
|
Source/LyShineSystemComponent.cpp
|
||||||
|
Source/LyShineSystemComponent.h
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ set(FILES
|
|||||||
Source/EditorPropertyTypes.h
|
Source/EditorPropertyTypes.h
|
||||||
Source/LyShineLoadScreen.cpp
|
Source/LyShineLoadScreen.cpp
|
||||||
Source/LyShineLoadScreen.h
|
Source/LyShineLoadScreen.h
|
||||||
Source/LyShineSystemComponent.cpp
|
|
||||||
Source/LyShineSystemComponent.h
|
|
||||||
Source/RenderGraph.cpp
|
Source/RenderGraph.cpp
|
||||||
Source/RenderGraph.h
|
Source/RenderGraph.h
|
||||||
Source/TextMarkup.cpp
|
Source/TextMarkup.cpp
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
|||||||
RUNTIME_DEPENDENCIES
|
RUNTIME_DEPENDENCIES
|
||||||
AZ::SceneCore
|
AZ::SceneCore
|
||||||
AZ::SceneData
|
AZ::SceneData
|
||||||
|
AZ::SceneUI
|
||||||
)
|
)
|
||||||
# the SceneProcessing.Editor module above is only used in Builders and Tools.
|
# the SceneProcessing.Editor module above is only used in Builders and Tools.
|
||||||
ly_create_alias(NAME SceneProcessing.Builders NAMESPACE Gem TARGETS Gem::SceneProcessing.Editor)
|
ly_create_alias(NAME SceneProcessing.Builders NAMESPACE Gem TARGETS Gem::SceneProcessing.Editor)
|
||||||
|
|||||||
@@ -52,18 +52,4 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT
|
|||||||
AutomatedTesting.Assets
|
AutomatedTesting.Assets
|
||||||
COMPONENT TestTools
|
COMPONENT TestTools
|
||||||
)
|
)
|
||||||
|
|
||||||
# Example tests.
|
|
||||||
ly_add_pytest(
|
|
||||||
NAME LyTestTools_ExampleTests_periodic_no_gpu
|
|
||||||
PATH ${CMAKE_CURRENT_LIST_DIR}/example/test_system_example.py
|
|
||||||
TEST_SERIAL
|
|
||||||
TEST_SUITE periodic
|
|
||||||
RUNTIME_DEPENDENCIES
|
|
||||||
Legacy::Editor
|
|
||||||
AssetProcessor
|
|
||||||
AutomatedTesting.GameLauncher
|
|
||||||
AutomatedTesting.Assets
|
|
||||||
COMPONENT TestTools
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,5 +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
|
|
||||||
"""
|
|
||||||
@@ -1,129 +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
|
|
||||||
|
|
||||||
Example test using LyTestTools to test Lumberyard.
|
|
||||||
"""
|
|
||||||
# Python built-in dependencies.
|
|
||||||
import logging
|
|
||||||
|
|
||||||
# Third party dependencies.
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
# ly_test_tools dependencies.
|
|
||||||
import ly_test_tools.log.log_monitor
|
|
||||||
import ly_remote_console.remote_console_commands as remote_console_commands
|
|
||||||
|
|
||||||
# Configuring the logging is done in ly_test_tools at the following location:
|
|
||||||
# ~/dev/Tools/LyTestTools/ly_test_tools/_internal/log/py_logging_util.py
|
|
||||||
|
|
||||||
# Use the following logging pattern to hook all test logging together:
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def remote_console(request):
|
|
||||||
"""
|
|
||||||
Creates a RemoteConsole() class instance to send console commands to the
|
|
||||||
Lumberyard client console.
|
|
||||||
:param request: _pytest.fixtures.SubRequest class that handles getting
|
|
||||||
a pytest fixture from a pytest function/fixture.
|
|
||||||
:return: ly_remote_console.remote_console_commands.RemoteConsole class instance
|
|
||||||
representing the Lumberyard remote console executable.
|
|
||||||
"""
|
|
||||||
# Initialize the RemoteConsole object to send commands to the Lumberyard client console.
|
|
||||||
console = remote_console_commands.RemoteConsole()
|
|
||||||
|
|
||||||
# Custom teardown method for this remote_console fixture.
|
|
||||||
def teardown():
|
|
||||||
console.stop()
|
|
||||||
|
|
||||||
# Utilize request.addfinalizer() to add custom teardown() methods.
|
|
||||||
request.addfinalizer(teardown) # This pattern must be used in pytest version
|
|
||||||
|
|
||||||
return console
|
|
||||||
|
|
||||||
# Shared parameters & fixtures for all test methods inside the TestSystemExample class.
|
|
||||||
@pytest.mark.usefixtures("automatic_process_killer")
|
|
||||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
|
||||||
class TestSystemExample(object):
|
|
||||||
"""
|
|
||||||
Example test case class to hold a set of test case methods.
|
|
||||||
|
|
||||||
The amount of tests run is based on the parametrization stacking made in each test method or class.
|
|
||||||
For this test, we placed unique test values in test methods and shared test values in the test class.
|
|
||||||
We also assume building has already been done, but the test should error if the build is mis-configured.
|
|
||||||
"""
|
|
||||||
# This test method needs specific parameters not shared by all other tests in the class.
|
|
||||||
# For targeting specific launchers, use the 'launcher_platform' pytest param like below:
|
|
||||||
# @pytest.mark.parametrize("launcher_platform", ['android'])
|
|
||||||
# If you want to target different AssetProcessor platforms, use asset_processor_platform:
|
|
||||||
# @pytest.mark.parametrize("asset_processor_platform", ['android'])
|
|
||||||
@pytest.mark.parametrize('level', ['simple_jacklocomotion'])
|
|
||||||
@pytest.mark.parametrize('load_wait', [120])
|
|
||||||
@pytest.mark.test_case_id('C16806863')
|
|
||||||
def test_SystemTestExample_AllSupportedPlatforms_LaunchAutomatedTesting(
|
|
||||||
# launcher_platform, asset_processor_platform, # Re-add these here if you plan to use them.
|
|
||||||
self, launcher, remote_console, level, load_wait):
|
|
||||||
"""
|
|
||||||
Tests launching the AutomatedTesting then launches the Lumberyard client &
|
|
||||||
loads the "simple_jacklocomotion" level using the remote console.
|
|
||||||
Assumes the user already setup & built their machine for the test.
|
|
||||||
"""
|
|
||||||
# Launch the Lumberyard client & remote console test case:
|
|
||||||
with launcher.start():
|
|
||||||
remote_console.start()
|
|
||||||
launcher_load = remote_console.expect_log_line(
|
|
||||||
match_string='Level system is loading "simple_jacklocomotion"',
|
|
||||||
timeout=load_wait)
|
|
||||||
|
|
||||||
# Assert loading was successful using remote console logs:
|
|
||||||
assert launcher_load, (
|
|
||||||
'Launcher failed to load Lumberyard client with the '
|
|
||||||
f'"{level}" level - waited "{load_wait}" seconds.')
|
|
||||||
|
|
||||||
# This test method only needs pytest.mark report values and shared test class parameters.
|
|
||||||
@pytest.mark.parametrize('processes_to_kill', ['Editor.exe'])
|
|
||||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
|
||||||
@pytest.mark.test_case_id('C16806864')
|
|
||||||
def test_SystemTestExample_AllSupportedPlatforms_LaunchEditor(self, editor, processes_to_kill, launcher_platform):
|
|
||||||
"""
|
|
||||||
Tests launching the Lumberyard Editor is successful with the current build.
|
|
||||||
"""
|
|
||||||
# Launch the Lumberyard editor & verify load is successful:
|
|
||||||
with editor.start():
|
|
||||||
assert editor.is_alive(), (
|
|
||||||
'Editor failed to launch for the current Lumberyard build.')
|
|
||||||
|
|
||||||
# Log monitoring example test.
|
|
||||||
@pytest.mark.parametrize('level', ['simple_jacklocomotion'])
|
|
||||||
@pytest.mark.parametrize('expected_lines', [['Log Monitoring test 1', 'Log Monitoring test 2']])
|
|
||||||
@pytest.mark.parametrize('unexpected_lines', [['Unexpected test 1', 'Unexpected test 2']])
|
|
||||||
@pytest.mark.test_case_id('C21202585')
|
|
||||||
def test_SystemTestExample_AllSupportedPlatforms_LogMonitoring(self, level, launcher, expected_lines,
|
|
||||||
unexpected_lines):
|
|
||||||
"""
|
|
||||||
Tests that the logging paths created by LyTestTools can be monitored for results using the log monitor.
|
|
||||||
"""
|
|
||||||
# Launch the Lumberyard client & initialize the log monitor.
|
|
||||||
file_to_monitor = launcher.workspace.info_log_path
|
|
||||||
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=launcher,
|
|
||||||
log_file_path=file_to_monitor)
|
|
||||||
|
|
||||||
# Generate log lines to the info log using logger.
|
|
||||||
for expected_line in expected_lines:
|
|
||||||
logger.info(expected_line)
|
|
||||||
|
|
||||||
# Start the Lumberyard client & test that the lines we logged can be viewed by the log monitor.
|
|
||||||
with launcher.start():
|
|
||||||
log_test = log_monitor.monitor_log_for_lines(
|
|
||||||
expected_lines=expected_lines, # Defaults to None.
|
|
||||||
unexpected_lines=unexpected_lines, # Defaults to None.
|
|
||||||
halt_on_unexpected=True, # Defaults to False.
|
|
||||||
timeout=60) # Defaults to 30
|
|
||||||
|
|
||||||
# Assert the log monitor detected expected lines and did not detect any unexpected lines.
|
|
||||||
assert log_test, (
|
|
||||||
f'Log monitoring failed. Used expected_lines values: {expected_lines} & '
|
|
||||||
f'unexpected_lines values: {unexpected_lines}')
|
|
||||||
@@ -6,49 +6,86 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
|
|||||||
A sanity test for the built-in fixtures.
|
A sanity test for the built-in fixtures.
|
||||||
Launch the windows launcher attached to the currently installed instance.
|
Launch the windows launcher attached to the currently installed instance.
|
||||||
"""
|
"""
|
||||||
|
# Import any dependencies for the test.
|
||||||
import logging
|
import logging
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
# Import any desired LTT modules from the package `ly_test_tools`. All LTT modules can be viewed at `Tools/LyTestTools/ly_test_tools`.
|
||||||
import ly_test_tools
|
import ly_test_tools
|
||||||
|
# The `launchers.launcher_helper` module helps create Launcher objects which control the Open 3D Engine (O3DE) Editor and game clients.
|
||||||
import ly_test_tools.launchers.launcher_helper as launcher_helper
|
import ly_test_tools.launchers.launcher_helper as launcher_helper
|
||||||
|
# The `builtin.helpers` module helps create the Workspace object, which controls the testing workspace in LTT.
|
||||||
import ly_test_tools.builtin.helpers as helpers
|
import ly_test_tools.builtin.helpers as helpers
|
||||||
|
# The `environment` module contains tools that involve the system's environment such as processes or timed waiters.
|
||||||
import ly_test_tools.environment.process_utils as process_utils
|
import ly_test_tools.environment.process_utils as process_utils
|
||||||
import ly_test_tools.environment.waiter as waiter
|
import ly_test_tools.environment.waiter as waiter
|
||||||
|
|
||||||
pytestmark = pytest.mark.SUITE_smoke
|
# Initialize a logger instance to hook all test logs together. The sub-logger pattern below makes it easy to track which file creates a log line.
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Note: For device testing, device ids must exist in ~/ly_test_tools/devices.ini, see README.txt for more info.
|
# Note: For device testing, device ids must exist in ~/ly_test_tools/devices.ini, see README.txt for more info.
|
||||||
|
|
||||||
|
|
||||||
|
# First define the class `TestAutomatedTestingProject` to group test functions together.
|
||||||
|
# The example test contains two test functions: `test_StartGameLauncher_Sanity` and `test_StartEditor_Sanity`.
|
||||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||||
|
# The example test utilizes Pytest parameterization. The following sets the `project` parameter to `AutomatedTesting`
|
||||||
|
# for both test functions. Notice that the Pytest mark is defined at the class level to affect both test functions.
|
||||||
class TestAutomatedTestingProject(object):
|
class TestAutomatedTestingProject(object):
|
||||||
|
|
||||||
def test_StartGameLauncher_Sanity(self, project):
|
def test_StartGameLauncher_Sanity(self, project):
|
||||||
|
"""
|
||||||
|
The `test_StartGameLauncher_Sanity` test function verifies that the O3DE game client launches successfully.
|
||||||
|
Start the test by utilizing the `kill_processes_named` function to close any open O3DE processes that may
|
||||||
|
interfere with the test. The Workspace object emulates the O3DE package by locating the engine and project
|
||||||
|
directories. The Launcher object controls the O3DE game client and requires a Workspace object for
|
||||||
|
initialization. Add the `-rhi=Null` arg to the executable call to disable GPU rendering. This allows the
|
||||||
|
test to run on instances without a GPU. We launch the game client executable and wait for the process to exist.
|
||||||
|
A try/finally block ensures proper test cleanup if issues occur during the test.
|
||||||
|
"""
|
||||||
|
# Kill processes that may interfere with the test
|
||||||
process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True)
|
process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Create the Workspace object
|
||||||
workspace = helpers.create_builtin_workspace(project=project)
|
workspace = helpers.create_builtin_workspace(project=project)
|
||||||
|
|
||||||
|
# Create the Launcher object and add args
|
||||||
launcher = launcher_helper.create_launcher(workspace)
|
launcher = launcher_helper.create_launcher(workspace)
|
||||||
launcher.args.extend(['-NullRenderer', '-BatchMode'])
|
launcher.args.extend(['-rhi=Null'])
|
||||||
|
|
||||||
|
# Call the game client executable
|
||||||
with launcher.start():
|
with launcher.start():
|
||||||
|
# Wait for the process to exist
|
||||||
waiter.wait_for(lambda: process_utils.process_exists(f"{project}.GameLauncher.exe", ignore_extensions=True))
|
waiter.wait_for(lambda: process_utils.process_exists(f"{project}.GameLauncher.exe", ignore_extensions=True))
|
||||||
finally:
|
finally:
|
||||||
|
# Clean up processes after the test is finished
|
||||||
process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True)
|
process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True)
|
||||||
|
|
||||||
@pytest.mark.skipif(not ly_test_tools.WINDOWS, reason="Editor currently only functions on Windows")
|
@pytest.mark.skipif(not ly_test_tools.WINDOWS, reason="Editor currently only functions on Windows")
|
||||||
def test_StartEditor_Sanity(self, project):
|
def test_StartEditor_Sanity(self, project):
|
||||||
|
"""
|
||||||
|
The `test_StartEditor_Sanity` test function is similar to the previous example with minor adjustments. A
|
||||||
|
PyTest mark skips the test if the operating system is not Windows. We use the `create_editor` function instead
|
||||||
|
of `create_launcher` to create an Editor type launcher instead of a game client type launcher. The additional
|
||||||
|
`-autotest_mode` arg supresses modal dialogs from interfering with our test. We launch the Editor executable and
|
||||||
|
wait for the process to exist.
|
||||||
|
"""
|
||||||
|
# Kill processes that may interfere with the test
|
||||||
process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True)
|
process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Create the Workspace object
|
||||||
workspace = helpers.create_builtin_workspace(project=project)
|
workspace = helpers.create_builtin_workspace(project=project)
|
||||||
|
|
||||||
|
# Create the Launcher object and add args
|
||||||
editor = launcher_helper.create_editor(workspace)
|
editor = launcher_helper.create_editor(workspace)
|
||||||
editor.args.extend(['-NullRenderer', '-autotest_mode'])
|
editor.args.extend(['-rhi=Null', '-autotest_mode'])
|
||||||
|
|
||||||
|
# Call the Editor executable
|
||||||
with editor.start():
|
with editor.start():
|
||||||
|
# Wait for the process to exist
|
||||||
waiter.wait_for(lambda: process_utils.process_exists("Editor", ignore_extensions=True))
|
waiter.wait_for(lambda: process_utils.process_exists("Editor", ignore_extensions=True))
|
||||||
finally:
|
finally:
|
||||||
|
# Clean up processes after the test is finished
|
||||||
process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True)
|
process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True)
|
||||||
|
|||||||
@@ -100,18 +100,29 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar
|
|||||||
cmake_path(RELATIVE_PATH target_library_output_directory BASE_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_library_output_subdirectory)
|
cmake_path(RELATIVE_PATH target_library_output_directory BASE_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_library_output_subdirectory)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(
|
if(COMMAND ly_install_target_override)
|
||||||
TARGETS ${TARGET_NAME}
|
# Mac needs special handling because of a cmake issue
|
||||||
ARCHIVE
|
ly_install_target_override(TARGET ${TARGET_NAME}
|
||||||
DESTINATION ${archive_output_directory}/${PAL_PLATFORM_NAME}/$<CONFIG>
|
ARCHIVE_DIR ${archive_output_directory}
|
||||||
COMPONENT ${install_component}
|
LIBRARY_DIR ${library_output_directory}
|
||||||
LIBRARY
|
RUNTIME_DIR ${runtime_output_directory}
|
||||||
DESTINATION ${library_output_directory}/${PAL_PLATFORM_NAME}/$<CONFIG>/${target_library_output_subdirectory}
|
LIBRARY_SUBDIR ${target_library_output_subdirectory}
|
||||||
COMPONENT ${install_component}
|
RUNTIME_SUBDIR ${target_runtime_output_subdirectory}
|
||||||
RUNTIME
|
)
|
||||||
DESTINATION ${runtime_output_directory}/${PAL_PLATFORM_NAME}/$<CONFIG>/${target_runtime_output_subdirectory}
|
else()
|
||||||
COMPONENT ${install_component}
|
install(
|
||||||
)
|
TARGETS ${TARGET_NAME}
|
||||||
|
ARCHIVE
|
||||||
|
DESTINATION ${archive_output_directory}/${PAL_PLATFORM_NAME}/$<CONFIG>
|
||||||
|
COMPONENT ${install_component}
|
||||||
|
LIBRARY
|
||||||
|
DESTINATION ${library_output_directory}/${PAL_PLATFORM_NAME}/$<CONFIG>/${target_library_output_subdirectory}
|
||||||
|
COMPONENT ${install_component}
|
||||||
|
RUNTIME
|
||||||
|
DESTINATION ${runtime_output_directory}/${PAL_PLATFORM_NAME}/$<CONFIG>/${target_runtime_output_subdirectory}
|
||||||
|
COMPONENT ${install_component}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# CMakeLists.txt file
|
# CMakeLists.txt file
|
||||||
string(REGEX MATCH "(.*)::(.*)$" match ${ALIAS_TARGET_NAME})
|
string(REGEX MATCH "(.*)::(.*)$" match ${ALIAS_TARGET_NAME})
|
||||||
@@ -487,7 +498,7 @@ function(ly_setup_others)
|
|||||||
|
|
||||||
# Scripts
|
# Scripts
|
||||||
file(GLOB o3de_scripts "${LY_ROOT_FOLDER}/scripts/o3de.*")
|
file(GLOB o3de_scripts "${LY_ROOT_FOLDER}/scripts/o3de.*")
|
||||||
install(FILES
|
install(PROGRAMS
|
||||||
${o3de_scripts}
|
${o3de_scripts}
|
||||||
DESTINATION ./scripts
|
DESTINATION ./scripts
|
||||||
)
|
)
|
||||||
@@ -505,6 +516,14 @@ function(ly_setup_others)
|
|||||||
DESTINATION .
|
DESTINATION .
|
||||||
REGEX "downloaded_packages" EXCLUDE
|
REGEX "downloaded_packages" EXCLUDE
|
||||||
REGEX "runtime" EXCLUDE
|
REGEX "runtime" EXCLUDE
|
||||||
|
REGEX ".*$\.sh" EXCLUDE
|
||||||
|
)
|
||||||
|
|
||||||
|
# For Mac/Linux shell scripts need to be installed as PROGRAMS to have execute permission
|
||||||
|
file(GLOB python_scripts "${LY_ROOT_FOLDER}/python/*.sh")
|
||||||
|
install(PROGRAMS
|
||||||
|
${python_scripts}
|
||||||
|
DESTINATION ./python
|
||||||
)
|
)
|
||||||
|
|
||||||
# Registry
|
# Registry
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Signing
|
# Signing
|
||||||
ly_set(CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS --deep)
|
# The "-o linker-signed" flag is required as a work-around for the following CMake issue:
|
||||||
|
# https://gitlab.kitware.com/cmake/cmake/-/issues/21854
|
||||||
|
ly_set(CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--deep -o linker-signed")
|
||||||
|
|
||||||
# Generate scheme files for Xcode
|
# Generate scheme files for Xcode
|
||||||
ly_set(CMAKE_XCODE_GENERATE_SCHEME TRUE)
|
ly_set(CMAKE_XCODE_GENERATE_SCHEME TRUE)
|
||||||
|
|||||||
@@ -5,7 +5,47 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
# Empty implementations for untested platforms to fix build errors.
|
#! ly_install_target_override: Mac specific target installation
|
||||||
|
function(ly_install_target_override)
|
||||||
|
|
||||||
function(ly_setup_o3de_install)
|
set(options)
|
||||||
endfunction()
|
set(oneValueArgs TARGET ARCHIVE_DIR LIBRARY_DIR RUNTIME_DIR LIBRARY_SUBDIR RUNTIME_SUBDIR)
|
||||||
|
set(multiValueArgs)
|
||||||
|
cmake_parse_arguments(ly_platform_install_target "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
get_property(install_component TARGET ${ly_platform_install_target_TARGET} PROPERTY INSTALL_COMPONENT)
|
||||||
|
|
||||||
|
# For bundles on Mac, we set the icons by passing in a path to the Images.xcassets directory.
|
||||||
|
# However, the CMake install command expects paths to files for the the RESOURCE property.
|
||||||
|
# More details can be found in the CMake issue: https://gitlab.kitware.com/cmake/cmake/-/issues/22409
|
||||||
|
get_target_property(is_bundle ${ly_platform_install_target_TARGET} MACOSX_BUNDLE)
|
||||||
|
if (${is_bundle})
|
||||||
|
get_target_property(cached_resources_dir ${ly_platform_install_target_TARGET} RESOURCE)
|
||||||
|
set_property(TARGET ${ly_platform_install_target_TARGET} PROPERTY RESOURCE "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(
|
||||||
|
TARGETS ${ly_platform_install_target_TARGET}
|
||||||
|
ARCHIVE
|
||||||
|
DESTINATION ${ly_platform_install_target_ARCHIVE_DIR}/${PAL_PLATFORM_NAME}/$<CONFIG>
|
||||||
|
COMPONENT ${install_component}
|
||||||
|
LIBRARY
|
||||||
|
DESTINATION ${ly_platform_install_target_LIBRARY_DIR}/${PAL_PLATFORM_NAME}/$<CONFIG>/${ly_platform_install_target_LIBRARY_SUBDIR}
|
||||||
|
COMPONENT ${install_component}
|
||||||
|
RUNTIME
|
||||||
|
DESTINATION ${ly_platform_install_target_RUNTIME_DIR}/${PAL_PLATFORM_NAME}/$<CONFIG>/${ly_platform_install_target_RUNTIME_SUBDIR}
|
||||||
|
COMPONENT ${install_component}
|
||||||
|
BUNDLE
|
||||||
|
DESTINATION ${ly_platform_install_target_RUNTIME_DIR}/${PAL_PLATFORM_NAME}/$<CONFIG>/${ly_platform_install_target_RUNTIME_SUBDIR}
|
||||||
|
COMPONENT ${install_component}
|
||||||
|
RESOURCE
|
||||||
|
DESTINATION ${ly_platform_install_target_RUNTIME_DIR}/${PAL_PLATFORM_NAME}/$<CONFIG>/${ly_platform_install_target_RUNTIME_SUBDIR}/
|
||||||
|
COMPONENT ${install_component}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (${is_bundle})
|
||||||
|
set_property(TARGET ${ly_platform_install_target_TARGET} PROPERTY RESOURCE ${cached_resources_dir})
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
include(cmake/Platform/Common/Install_common.cmake)
|
||||||
|
|||||||
Reference in New Issue
Block a user