Merge branch 'development' into redcode/driller_removal
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> # Conflicts: # Code/Framework/AzCore/AzCore/azcore_files.cmake # Gems/Atom/Feature/Common/Assets/Materials/Presets/MacBeth/15_red_sRGB.tif
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:011454252e40c927343cce16296412f02f45d1f345c75c036651bdcca473bda5
|
||||
size 2672
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7bafcc4aefab827e1414e64bcdde235500b51392e52c9ccd588b2d7a24b865a0
|
||||
size 20214
|
||||
@@ -1,46 +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
|
||||
"""
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
from ly_test_tools.o3de.editor_test import EditorSharedTest, EditorTestSuite
|
||||
from ly_test_tools.image.screenshot_compare_qssim import qssim as compare_screenshots
|
||||
from .atom_utils.atom_component_helper import create_screenshots_archive, golden_images_directory
|
||||
|
||||
DEFAULT_SUBFOLDER_PATH = 'user/PythonTests/Automated/Screenshots'
|
||||
|
||||
|
||||
@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.")
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
class TestAutomation(EditorTestSuite):
|
||||
# Remove -autotest_mode from global_extra_cmdline_args since we need rendering for these tests.
|
||||
global_extra_cmdline_args = ["-BatchMode"] # Default is ["-BatchMode", "-autotest_mode"]
|
||||
|
||||
enable_prefab_system = False
|
||||
|
||||
@pytest.mark.test_case_id("C34603773")
|
||||
class AtomGPU_BasicLevelSetup_SetsUpLevel(EditorSharedTest):
|
||||
use_null_renderer = False # Default is True
|
||||
screenshot_name = "AtomBasicLevelSetup.ppm"
|
||||
test_screenshots = [] # Gets set by setup()
|
||||
screenshot_directory = "" # Gets set by setup()
|
||||
|
||||
# Clear existing test screenshots before starting test.
|
||||
def setup(self, workspace):
|
||||
screenshot_directory = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH)
|
||||
test_screenshots = [os.path.join(screenshot_directory, self.screenshot_name)]
|
||||
file_system.delete(test_screenshots, True, True)
|
||||
|
||||
from Atom.tests import hydra_AtomGPU_BasicLevelSetup as test_module
|
||||
|
||||
golden_images = [os.path.join(golden_images_directory(), screenshot_name)]
|
||||
for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images):
|
||||
compare_screenshots(test_screenshot, golden_screenshot)
|
||||
create_screenshots_archive(screenshot_directory)
|
||||
@@ -1,200 +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
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import editor_python_test_tools.hydra_editor_utils as hydra
|
||||
from editor_python_test_tools.editor_test_helper import EditorTestHelper
|
||||
from Atom.atom_utils.screenshot_utils import ScreenshotHelper
|
||||
|
||||
SCREEN_WIDTH = 1280
|
||||
SCREEN_HEIGHT = 720
|
||||
DEGREE_RADIAN_FACTOR = 0.0174533
|
||||
|
||||
helper = EditorTestHelper(log_prefix="Test_Atom_BasicLevelSetup")
|
||||
|
||||
|
||||
def run():
|
||||
"""
|
||||
1. View -> Layouts -> Restore Default Layout, sets the viewport to ratio 16:9 @ 1280 x 720
|
||||
2. Runs console command r_DisplayInfo = 0
|
||||
3. Deletes all entities currently present in the level.
|
||||
4. Creates a "default_level" entity to hold all other entities, setting the translate values to x:0, y:0, z:0
|
||||
5. Adds a Grid component to the "default_level" & updates its Grid Spacing to 1.0m
|
||||
6. Adds a "global_skylight" entity to "default_level", attaching an HDRi Skybox w/ a Cubemap Texture.
|
||||
7. Adds a Global Skylight (IBL) component w/ diffuse image and specular image to "global_skylight" entity.
|
||||
8. Adds a "ground_plane" entity to "default_level", attaching a Mesh component & Material component.
|
||||
9. Adds a "directional_light" entity to "default_level" & adds a Directional Light component.
|
||||
10. Adds a "sphere" entity to "default_level" & adds a Mesh component with a Material component to it.
|
||||
11. Adds a "camera" entity to "default_level" & adds a Camera component with 80 degree FOV and Transform values:
|
||||
Translate - x:5.5m, y:-12.0m, z:9.0m
|
||||
Rotate - x:-27.0, y:-12.0, z:25.0
|
||||
12. Finally enters game mode, takes a screenshot, & exits game mode.
|
||||
:return: None
|
||||
"""
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.camera as camera
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.legacy.general as general
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.editor as editor
|
||||
|
||||
def initial_viewport_setup(screen_width, screen_height):
|
||||
general.set_viewport_size(screen_width, screen_height)
|
||||
general.update_viewport()
|
||||
helper.wait_for_condition(
|
||||
function=lambda: helper.isclose(a=general.get_viewport_size().x, b=SCREEN_WIDTH, rel_tol=0.1)
|
||||
and helper.isclose(a=general.get_viewport_size().y, b=SCREEN_HEIGHT, rel_tol=0.1),
|
||||
timeout_in_seconds=4.0
|
||||
)
|
||||
result = helper.isclose(a=general.get_viewport_size().x, b=SCREEN_WIDTH, rel_tol=0.1) and helper.isclose(
|
||||
a=general.get_viewport_size().y, b=SCREEN_HEIGHT, rel_tol=0.1)
|
||||
general.log(general.get_viewport_size().x)
|
||||
general.log(general.get_viewport_size().y)
|
||||
general.log(general.get_viewport_size().z)
|
||||
general.log(f"Viewport is set to the expected size: {result}")
|
||||
general.run_console("r_DisplayInfo = 0")
|
||||
|
||||
def after_level_load():
|
||||
"""Function to call after creating/opening a level to ensure it loads."""
|
||||
# Give everything a second to initialize.
|
||||
general.idle_enable(True)
|
||||
general.idle_wait(1.0)
|
||||
general.update_viewport()
|
||||
general.idle_wait(0.5) # half a second is more than enough for updating the viewport.
|
||||
|
||||
# Close out problematic windows, FPS meters, and anti-aliasing.
|
||||
if general.is_helpers_shown(): # Turn off the helper gizmos if visible
|
||||
general.toggle_helpers()
|
||||
general.idle_wait(1.0)
|
||||
if general.is_pane_visible("Error Report"): # Close Error Report windows that block focus.
|
||||
general.close_pane("Error Report")
|
||||
if general.is_pane_visible("Error Log"): # Close Error Log windows that block focus.
|
||||
general.close_pane("Error Log")
|
||||
general.idle_wait(1.0)
|
||||
general.run_console("r_displayInfo=0")
|
||||
general.idle_wait(1.0)
|
||||
|
||||
# Wait for Editor idle loop before executing Python hydra scripts.
|
||||
general.idle_enable(True)
|
||||
|
||||
# Basic setup for opened level.
|
||||
helper.open_level(level_name="Base")
|
||||
after_level_load()
|
||||
initial_viewport_setup(SCREEN_WIDTH, SCREEN_HEIGHT)
|
||||
|
||||
# Create default_level entity
|
||||
search_filter = azlmbr.entity.SearchFilter()
|
||||
all_entities = entity.SearchBus(azlmbr.bus.Broadcast, "SearchEntities", search_filter)
|
||||
editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntities", all_entities)
|
||||
|
||||
default_level = hydra.Entity("default_level")
|
||||
position = math.Vector3(0.0, 0.0, 0.0)
|
||||
default_level.create_entity(position, ["Grid"])
|
||||
default_level.get_set_test(0, "Controller|Configuration|Secondary Grid Spacing", 1.0)
|
||||
|
||||
# Create global_skylight entity and set the properties
|
||||
global_skylight = hydra.Entity("global_skylight")
|
||||
global_skylight.create_entity(
|
||||
entity_position=math.Vector3(0.0, 0.0, 0.0),
|
||||
components=["HDRi Skybox", "Global Skylight (IBL)"],
|
||||
parent_id=default_level.id
|
||||
)
|
||||
global_skylight_image_asset_path = os.path.join("LightingPresets", "default_iblskyboxcm.exr.streamingimage")
|
||||
global_skylight_image_asset = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", global_skylight_image_asset_path, math.Uuid(), False)
|
||||
global_skylight.get_set_test(0, "Controller|Configuration|Cubemap Texture", global_skylight_image_asset)
|
||||
hydra.get_set_test(global_skylight, 1, "Controller|Configuration|Diffuse Image", global_skylight_image_asset)
|
||||
hydra.get_set_test(global_skylight, 1, "Controller|Configuration|Specular Image", global_skylight_image_asset)
|
||||
|
||||
# Create ground_plane entity and set the properties
|
||||
ground_plane = hydra.Entity("ground_plane")
|
||||
ground_plane.create_entity(
|
||||
entity_position=math.Vector3(0.0, 0.0, 0.0),
|
||||
components=["Material"],
|
||||
parent_id=default_level.id
|
||||
)
|
||||
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalUniformScale", ground_plane.id, 32.0)
|
||||
|
||||
# Work around to add the correct Atom Mesh component and asset.
|
||||
mesh_type_id = azlmbr.globals.property.EditorMeshComponentTypeId
|
||||
ground_plane.components.append(
|
||||
editor.EditorComponentAPIBus(
|
||||
bus.Broadcast, "AddComponentsOfType", ground_plane.id, [mesh_type_id]
|
||||
).GetValue()[0]
|
||||
)
|
||||
ground_plane_mesh_asset_path = os.path.join("TestData", "Objects", "plane.azmodel")
|
||||
ground_plane_mesh_asset = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", ground_plane_mesh_asset_path, math.Uuid(), False)
|
||||
hydra.get_set_test(ground_plane, 1, "Controller|Configuration|Mesh Asset", ground_plane_mesh_asset)
|
||||
|
||||
# Add Atom Material component and asset.
|
||||
ground_plane_material_asset_path = os.path.join("Materials", "Presets", "PBR", "metal_chrome.azmaterial")
|
||||
ground_plane_material_asset = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", ground_plane_material_asset_path, math.Uuid(), False)
|
||||
ground_plane.get_set_test(0, "Default Material|Material Asset", ground_plane_material_asset)
|
||||
|
||||
# Create directional_light entity and set the properties
|
||||
directional_light = hydra.Entity("directional_light")
|
||||
directional_light.create_entity(
|
||||
entity_position=math.Vector3(0.0, 0.0, 10.0),
|
||||
components=["Directional Light"],
|
||||
parent_id=default_level.id
|
||||
)
|
||||
rotation = math.Vector3(DEGREE_RADIAN_FACTOR * -90.0, 0.0, 0.0)
|
||||
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", directional_light.id, rotation)
|
||||
|
||||
# Create sphere entity and set the properties
|
||||
sphere = hydra.Entity("sphere")
|
||||
sphere.create_entity(
|
||||
entity_position=math.Vector3(0.0, 0.0, 1.0),
|
||||
components=["Material"],
|
||||
parent_id=default_level.id
|
||||
)
|
||||
|
||||
# Work around to add the correct Atom Mesh component and asset.
|
||||
sphere.components.append(
|
||||
editor.EditorComponentAPIBus(
|
||||
bus.Broadcast, "AddComponentsOfType", sphere.id, [mesh_type_id]
|
||||
).GetValue()[0]
|
||||
)
|
||||
sphere_mesh_asset_path = os.path.join("Models", "sphere.azmodel")
|
||||
sphere_mesh_asset = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", sphere_mesh_asset_path, math.Uuid(), False)
|
||||
hydra.get_set_test(sphere, 1, "Controller|Configuration|Mesh Asset", sphere_mesh_asset)
|
||||
|
||||
# Add Atom Material component and asset.
|
||||
sphere_material_asset_path = os.path.join("Materials", "Presets", "PBR", "metal_brass_polished.azmaterial")
|
||||
sphere_material_asset = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", sphere_material_asset_path, math.Uuid(), False)
|
||||
sphere.get_set_test(0, "Default Material|Material Asset", sphere_material_asset)
|
||||
|
||||
# Create camera component and set the properties
|
||||
camera_entity = hydra.Entity("camera")
|
||||
position = math.Vector3(5.5, -12.0, 9.0)
|
||||
camera_entity.create_entity(components=["Camera"], entity_position=position, parent_id=default_level.id)
|
||||
rotation = math.Vector3(
|
||||
DEGREE_RADIAN_FACTOR * -27.0, DEGREE_RADIAN_FACTOR * -12.0, DEGREE_RADIAN_FACTOR * 25.0
|
||||
)
|
||||
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", camera_entity.id, rotation)
|
||||
camera_entity.get_set_test(0, "Controller|Configuration|Field of view", 60.0)
|
||||
camera.EditorCameraViewRequestBus(azlmbr.bus.Event, "ToggleCameraAsActiveView", camera_entity.id)
|
||||
|
||||
# Enter game mode, take screenshot, & exit game mode.
|
||||
general.idle_wait(0.5)
|
||||
general.enter_game_mode()
|
||||
general.idle_wait(1.0)
|
||||
helper.wait_for_condition(function=lambda: general.is_in_game_mode(), timeout_in_seconds=2.0)
|
||||
ScreenshotHelper(general.idle_wait_frames).capture_screenshot_blocking(f"{'AtomBasicLevelSetup'}.ppm")
|
||||
general.exit_game_mode()
|
||||
helper.wait_for_condition(function=lambda: not general.is_in_game_mode(), timeout_in_seconds=2.0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
@@ -1,261 +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
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
import azlmbr.asset as asset
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
|
||||
|
||||
import editor_python_test_tools.hydra_editor_utils as hydra
|
||||
from Atom.atom_utils import atom_component_helper, atom_constants, screenshot_utils
|
||||
from editor_python_test_tools.editor_test_helper import EditorTestHelper
|
||||
|
||||
helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper")
|
||||
|
||||
LEVEL_NAME = "Base"
|
||||
LIGHT_COMPONENT = "Light"
|
||||
LIGHT_TYPE_PROPERTY = 'Controller|Configuration|Light type'
|
||||
DEGREE_RADIAN_FACTOR = 0.0174533
|
||||
|
||||
|
||||
def run():
|
||||
"""
|
||||
Sets up the tests by making sure the required level is created & setup correctly.
|
||||
It then executes 2 test cases - see each associated test function's docstring for more info.
|
||||
|
||||
Finally prints the string "Light component tests completed" after completion
|
||||
|
||||
Tests will fail immediately if any of these log lines are found:
|
||||
1. Trace::Assert
|
||||
2. Trace::Error
|
||||
3. Traceback (most recent call last):
|
||||
|
||||
:return: None
|
||||
"""
|
||||
atom_component_helper.create_basic_atom_level(level_name=LEVEL_NAME)
|
||||
|
||||
# Run tests.
|
||||
area_light_test()
|
||||
spot_light_test()
|
||||
general.log("Light component tests completed.")
|
||||
|
||||
|
||||
def area_light_test():
|
||||
"""
|
||||
Basic test for the "Light" component attached to an "area_light" entity.
|
||||
|
||||
Test Case - Light Component: Capsule, Spot (disk), and Point (sphere):
|
||||
1. Creates "area_light" entity w/ a Light component that has a Capsule Light type w/ the color set to 255, 0, 0
|
||||
2. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
3. Sets the Light component Intensity Mode to Lumens (default).
|
||||
4. Ensures the Light component Mode is Automatic (default).
|
||||
5. Sets the Intensity value of the Light component to 0.0
|
||||
6. Enters game mode again, takes another screenshot for comparison, then exits game mode.
|
||||
7. Updates the Intensity value of the Light component to 1000.0
|
||||
8. Enters game mode again, takes another screenshot for comparison, then exits game mode.
|
||||
9. Swaps the Capsule light type option to Spot (disk) light type on the Light component
|
||||
10. Updates "area_light" entity Transform rotate value to x: 90.0, y:0.0, z:0.0
|
||||
11. Enters game mode again, takes another screenshot for comparison, then exits game mode.
|
||||
12. Swaps the Spot (disk) light type for the Point (sphere) light type in the Light component.
|
||||
13. Enters game mode again, takes another screenshot for comparison, then exits game mode.
|
||||
14. Deletes the Light component from the "area_light" entity and verifies its successful.
|
||||
"""
|
||||
# Create an "area_light" entity with "Light" component using Light type of "Capsule"
|
||||
area_light_entity_name = "area_light"
|
||||
area_light = hydra.Entity(area_light_entity_name)
|
||||
area_light.create_entity(math.Vector3(-1.0, -2.0, 3.0), [LIGHT_COMPONENT])
|
||||
general.log(
|
||||
f"{area_light_entity_name}_test: Component added to the entity: "
|
||||
f"{hydra.has_components(area_light.id, [LIGHT_COMPONENT])}")
|
||||
light_component_id_pair = hydra.attach_component_to_entity(area_light.id, LIGHT_COMPONENT)
|
||||
|
||||
# Select the "Capsule" light type option.
|
||||
azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'SetComponentProperty',
|
||||
light_component_id_pair,
|
||||
LIGHT_TYPE_PROPERTY,
|
||||
atom_constants.LIGHT_TYPES['capsule']
|
||||
)
|
||||
|
||||
# Update color and take screenshot in game mode
|
||||
color = math.Color(255.0, 0.0, 0.0, 0.0)
|
||||
area_light.get_set_test(0, "Controller|Configuration|Color", color)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("AreaLight_1", area_light_entity_name)
|
||||
|
||||
# Update intensity value to 0.0 and take screenshot in game mode
|
||||
area_light.get_set_test(0, "Controller|Configuration|Attenuation Radius|Mode", 1)
|
||||
area_light.get_set_test(0, "Controller|Configuration|Intensity", 0.0)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("AreaLight_2", area_light_entity_name)
|
||||
|
||||
# Update intensity value to 1000.0 and take screenshot in game mode
|
||||
area_light.get_set_test(0, "Controller|Configuration|Intensity", 1000.0)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("AreaLight_3", area_light_entity_name)
|
||||
|
||||
# Swap the "Capsule" light type option to "Spot (disk)" light type
|
||||
azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'SetComponentProperty',
|
||||
light_component_id_pair,
|
||||
LIGHT_TYPE_PROPERTY,
|
||||
atom_constants.LIGHT_TYPES['spot_disk']
|
||||
)
|
||||
area_light_rotation = math.Vector3(DEGREE_RADIAN_FACTOR * 90.0, 0.0, 0.0)
|
||||
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", area_light.id, area_light_rotation)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("AreaLight_4", area_light_entity_name)
|
||||
|
||||
# Swap the "Spot (disk)" light type to the "Point (sphere)" light type and take screenshot.
|
||||
azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'SetComponentProperty',
|
||||
light_component_id_pair,
|
||||
LIGHT_TYPE_PROPERTY,
|
||||
atom_constants.LIGHT_TYPES['sphere']
|
||||
)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("AreaLight_5", area_light_entity_name)
|
||||
|
||||
editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntityById", area_light.id)
|
||||
|
||||
|
||||
def spot_light_test():
|
||||
"""
|
||||
Basic test for the Light component attached to a "spot_light" entity.
|
||||
|
||||
Test Case - Light Component: Spot (disk) with shadows & colors:
|
||||
1. Creates "spot_light" entity w/ a Light component attached to it.
|
||||
2. Selects the "directional_light" entity already present in the level and disables it.
|
||||
3. Selects the "global_skylight" entity already present in the level and disables the HDRi Skybox component,
|
||||
as well as the Global Skylight (IBL) component.
|
||||
4. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
5. Selects the "ground_plane" entity and changes updates the material to a new material.
|
||||
6. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
7. Selects the "spot_light" entity and increases the Light component Intensity to 800 lm
|
||||
8. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
9. Selects the "spot_light" entity and sets the Light component Color to 47, 75, 37
|
||||
10. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
11. Selects the "spot_light" entity and modifies the Shutter controls to the following values:
|
||||
- Enable shutters: True
|
||||
- Inner Angle: 60.0
|
||||
- Outer Angle: 75.0
|
||||
12. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
13. Selects the "spot_light" entity and modifies the Shadow controls to the following values:
|
||||
- Enable Shadow: True
|
||||
- ShadowmapSize: 256
|
||||
14. Modifies the world translate position of the "spot_light" entity to 0.7, -2.0, 1.9 (for casting shadows better)
|
||||
15. Enters game mode to take a screenshot for comparison, then exits game mode.
|
||||
"""
|
||||
# Disable "Directional Light" component for the "directional_light" entity
|
||||
# "directional_light" entity is created by the create_basic_atom_level() function by default.
|
||||
directional_light_entity_id = hydra.find_entity_by_name("directional_light")
|
||||
directional_light = hydra.Entity(name='directional_light', id=directional_light_entity_id)
|
||||
directional_light_component_type = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Directional Light"], 0)[0]
|
||||
directional_light_component = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'GetComponentOfType', directional_light.id, directional_light_component_type
|
||||
).GetValue()
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [directional_light_component])
|
||||
general.idle_wait(0.5)
|
||||
|
||||
# Disable "Global Skylight (IBL)" and "HDRi Skybox" components for the "global_skylight" entity
|
||||
global_skylight_entity_id = hydra.find_entity_by_name("global_skylight")
|
||||
global_skylight = hydra.Entity(name='global_skylight', id=global_skylight_entity_id)
|
||||
global_skylight_component_type = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Global Skylight (IBL)"], 0)[0]
|
||||
global_skylight_component = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'GetComponentOfType', global_skylight.id, global_skylight_component_type
|
||||
).GetValue()
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [global_skylight_component])
|
||||
hdri_skybox_component_type = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["HDRi Skybox"], 0)[0]
|
||||
hdri_skybox_component = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'GetComponentOfType', global_skylight.id, hdri_skybox_component_type
|
||||
).GetValue()
|
||||
editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [hdri_skybox_component])
|
||||
general.idle_wait(0.5)
|
||||
|
||||
# Create a "spot_light" entity with "Light" component using Light Type of "Spot (disk)"
|
||||
spot_light_entity_name = "spot_light"
|
||||
spot_light = hydra.Entity(spot_light_entity_name)
|
||||
spot_light.create_entity(math.Vector3(0.7, -2.0, 1.0), [LIGHT_COMPONENT])
|
||||
general.log(
|
||||
f"{spot_light_entity_name}_test: Component added to the entity: "
|
||||
f"{hydra.has_components(spot_light.id, [LIGHT_COMPONENT])}")
|
||||
rotation = math.Vector3(DEGREE_RADIAN_FACTOR * 300.0, 0.0, 0.0)
|
||||
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", spot_light.id, rotation)
|
||||
light_component_type = hydra.attach_component_to_entity(spot_light.id, LIGHT_COMPONENT)
|
||||
editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'SetComponentProperty',
|
||||
light_component_type,
|
||||
LIGHT_TYPE_PROPERTY,
|
||||
atom_constants.LIGHT_TYPES['spot_disk']
|
||||
)
|
||||
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("SpotLight_1", spot_light_entity_name)
|
||||
|
||||
# Change default material of ground plane entity and take screenshot
|
||||
ground_plane_entity_id = hydra.find_entity_by_name("ground_plane")
|
||||
ground_plane = hydra.Entity(name='ground_plane', id=ground_plane_entity_id)
|
||||
ground_plane_asset_path = os.path.join("Materials", "Presets", "MacBeth", "22_neutral_5-0_0-70d.azmaterial")
|
||||
ground_plane_asset_value = asset.AssetCatalogRequestBus(
|
||||
bus.Broadcast, "GetAssetIdByPath", ground_plane_asset_path, math.Uuid(), False)
|
||||
material_property_path = "Default Material|Material Asset"
|
||||
material_component_type = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Material"], 0)[0]
|
||||
material_component = azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast, 'GetComponentOfType', ground_plane.id, material_component_type).GetValue()
|
||||
editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'SetComponentProperty',
|
||||
material_component,
|
||||
material_property_path,
|
||||
ground_plane_asset_value
|
||||
)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("SpotLight_2", spot_light_entity_name)
|
||||
|
||||
# Increase intensity value of the Spot light and take screenshot in game mode
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Intensity", 800.0)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("SpotLight_3", spot_light_entity_name)
|
||||
|
||||
# Update the Spot light color and take screenshot in game mode
|
||||
color_value = math.Color(47.0 / 255.0, 75.0 / 255.0, 37.0 / 255.0, 255.0 / 255.0)
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Color", color_value)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("SpotLight_4", spot_light_entity_name)
|
||||
|
||||
# Update the Shutter controls of the Light component and take screenshot
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Shutters|Enable shutters", True)
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Shutters|Inner angle", 60.0)
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Shutters|Outer angle", 75.0)
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("SpotLight_5", spot_light_entity_name)
|
||||
|
||||
# Update the Shadow controls, move the spot_light entity world translate position and take screenshot
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Shadows|Enable shadow", True)
|
||||
spot_light.get_set_test(0, "Controller|Configuration|Shadows|Shadowmap size", 256.0)
|
||||
azlmbr.components.TransformBus(
|
||||
azlmbr.bus.Event, "SetWorldTranslation", spot_light.id, math.Vector3(0.7, -2.0, 1.9))
|
||||
general.idle_wait(1.0)
|
||||
screenshot_utils.take_screenshot_game_mode("SpotLight_6", spot_light_entity_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
@@ -113,8 +113,15 @@ set(FILES
|
||||
Debug/TraceMessageBus.h
|
||||
Debug/TraceReflection.cpp
|
||||
Debug/TraceReflection.h
|
||||
DOM/DomBackend.cpp
|
||||
DOM/DomBackend.h
|
||||
DOM/DomUtils.cpp
|
||||
DOM/DomUtils.h
|
||||
DOM/DomVisitor.cpp
|
||||
DOM/DomVisitor.h
|
||||
DOM/Backends/JSON/JsonBackend.h
|
||||
DOM/Backends/JSON/JsonSerializationUtils.cpp
|
||||
DOM/Backends/JSON/JsonSerializationUtils.h
|
||||
EBus/BusImpl.h
|
||||
EBus/EBus.h
|
||||
EBus/EBusEnvironment.cpp
|
||||
|
||||
@@ -212,6 +212,8 @@ set(FILES
|
||||
AZStd/Variant.cpp
|
||||
AZStd/VariantSerialization.cpp
|
||||
AZStd/VectorAndArray.cpp
|
||||
DOM/DomJsonTests.cpp
|
||||
DOM/DomJsonBenchmarks.cpp
|
||||
)
|
||||
|
||||
# Prevent the following files from being grouped in UNITY builds
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
|
||||
#include <AzToolsFramework/Application/ToolsApplication.h>
|
||||
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
|
||||
#include <Prefab/PrefabTestFixture.h>
|
||||
|
||||
#include <AZTestShared/Math/MathTestHelpers.h>
|
||||
|
||||
@@ -1062,4 +1065,67 @@ R"DELIMITER(<ObjectStream version="1">
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fixture provides a root prefab with Transform component and listens for TransformNotificationBus.
|
||||
class TransformComponentActivationTest
|
||||
: public PrefabTestFixture
|
||||
, public TransformNotificationBus::Handler
|
||||
{
|
||||
protected:
|
||||
void SetUpEditorFixtureImpl() override
|
||||
{
|
||||
PrefabTestFixture::SetUpEditorFixtureImpl();
|
||||
|
||||
CreateRootPrefab();
|
||||
}
|
||||
|
||||
void TearDownEditorFixtureImpl() override
|
||||
{
|
||||
BusDisconnect();
|
||||
|
||||
PrefabTestFixture::TearDownEditorFixtureImpl();
|
||||
}
|
||||
|
||||
void OnTransformChanged(const Transform& /*local*/, const Transform& /*world*/) override
|
||||
{
|
||||
m_transformUpdated = true;
|
||||
}
|
||||
|
||||
void MoveEntity(AZ::EntityId entityId)
|
||||
{
|
||||
AzToolsFramework::ScopedUndoBatch undoBatch("Move Entity");
|
||||
TransformBus::Event(entityId, &TransformInterface::SetWorldTranslation, Vector3(1.f, 0.f, 0.f));
|
||||
}
|
||||
|
||||
bool m_transformUpdated = false;
|
||||
};
|
||||
|
||||
TEST_F(TransformComponentActivationTest, TransformChangedEventIsSentWhenEntityIsActivatedViaUndoRedo)
|
||||
{
|
||||
AZ::EntityId entityId = CreateEntityUnderRootPrefab("Entity");
|
||||
MoveEntity(entityId);
|
||||
BusConnect(entityId);
|
||||
|
||||
// verify that undoing/redoing move operations fires TransformChanged event
|
||||
Undo();
|
||||
EXPECT_TRUE(m_transformUpdated);
|
||||
m_transformUpdated = false;
|
||||
|
||||
Redo();
|
||||
EXPECT_TRUE(m_transformUpdated);
|
||||
m_transformUpdated = false;
|
||||
}
|
||||
|
||||
TEST_F(TransformComponentActivationTest, TransformChangedEventIsNotSentWhenEntityIsDeactivatedAndActivated)
|
||||
{
|
||||
AZ::EntityId entityId = CreateEntityUnderRootPrefab("Entity");
|
||||
BusConnect(entityId);
|
||||
|
||||
// verify that simply activating/deactivating an entity does not fire TransformChanged event
|
||||
Entity* entity = nullptr;
|
||||
ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, entityId);
|
||||
entity->Deactivate();
|
||||
entity->Activate();
|
||||
EXPECT_FALSE(m_transformUpdated);
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b53b8ca6b7062239398820aef6fb4145a0b6c8c7e3aae90c17b6b87f806d3579
|
||||
size 19426
|
||||
@@ -670,8 +670,6 @@ namespace AZ
|
||||
AZ::u8 width,
|
||||
int32_t viewProjOverrideIndex)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzRender, "AuxGeomDrawQueue: DrawPrimitiveWithSharedVerticesCommon");
|
||||
|
||||
// grab a mutex lock for the rest of this function so that a commit cannot happen during it and
|
||||
// other threads can't add geometry during it
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_buffersWriteLock);
|
||||
@@ -742,8 +740,6 @@ namespace AZ
|
||||
AZ::u8 width,
|
||||
int32_t viewProjOverrideIndex)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzRender, "AuxGeomDrawQueue: DrawPrimitiveWithSharedVerticesCommon");
|
||||
|
||||
AZ_Assert(indexCount >= verticesPerPrimitiveType && (indexCount % verticesPerPrimitiveType == 0),
|
||||
"Index count must be at least %d and must be a multiple of %d",
|
||||
verticesPerPrimitiveType, verticesPerPrimitiveType);
|
||||
|
||||
@@ -76,8 +76,8 @@ namespace AZ
|
||||
void MeshFeatureProcessor::Simulate(const FeatureProcessor::SimulatePacket& packet)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(RPI, "MeshFeatureProcessor: Simulate");
|
||||
AZ_UNUSED(packet);
|
||||
|
||||
AZ::Job* parentJob = packet.m_parentJob;
|
||||
AZStd::concurrency_check_scope scopeCheck(m_meshDataChecker);
|
||||
|
||||
const auto iteratorRanges = m_modelData.GetParallelRanges();
|
||||
@@ -86,6 +86,8 @@ namespace AZ
|
||||
{
|
||||
const auto jobLambda = [&]() -> void
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzRender, "MeshFeatureProcessor: Simulate: Job");
|
||||
|
||||
for (auto meshDataIter = iteratorRange.first; meshDataIter != iteratorRange.second; ++meshDataIter)
|
||||
{
|
||||
if (!meshDataIter->m_model)
|
||||
@@ -113,24 +115,22 @@ namespace AZ
|
||||
{
|
||||
meshDataIter->BuildCullable();
|
||||
}
|
||||
|
||||
if (meshDataIter->m_cullBoundsNeedsUpdate)
|
||||
{
|
||||
meshDataIter->UpdateCullBounds(m_transformService);
|
||||
}
|
||||
}
|
||||
};
|
||||
Job* executeGroupJob = aznew JobFunction<decltype(jobLambda)>(jobLambda, true, nullptr); // Auto-deletes
|
||||
executeGroupJob->SetDependent(&jobCompletion);
|
||||
executeGroupJob->Start();
|
||||
parentJob->StartAsChild(executeGroupJob);
|
||||
}
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzRender, "MeshFeatureProcessor: Simulate: WaitForChildren");
|
||||
parentJob->WaitForChildren();
|
||||
}
|
||||
jobCompletion.StartAndWaitForCompletion();
|
||||
|
||||
m_forceRebuildDrawPackets = false;
|
||||
|
||||
// CullingSystem::RegisterOrUpdateCullable() is not threadsafe, so need to do those updates in a single thread
|
||||
for (ModelDataInstance& modelDataInstance : m_modelData)
|
||||
{
|
||||
if (modelDataInstance.m_model && modelDataInstance.m_cullBoundsNeedsUpdate)
|
||||
{
|
||||
modelDataInstance.UpdateCullBounds(m_transformService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MeshFeatureProcessor::OnBeginPrepareRender()
|
||||
@@ -1037,7 +1037,6 @@ namespace AZ
|
||||
|
||||
void ModelDataInstance::UpdateDrawPackets(bool forceUpdate /*= false*/)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzRender, "ModelDataInstance:: UpdateDrawPackets");
|
||||
for (auto& drawPacketList : m_drawPacketListsByLod)
|
||||
{
|
||||
for (auto& drawPacket : drawPacketList)
|
||||
@@ -1052,7 +1051,6 @@ namespace AZ
|
||||
|
||||
void ModelDataInstance::BuildCullable()
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzRender, "ModelDataInstance: BuildCullable");
|
||||
AZ_Assert(m_cullableNeedsRebuild, "This function only needs to be called if the cullable to be rebuilt");
|
||||
AZ_Assert(m_model, "The model has not finished loading yet");
|
||||
|
||||
@@ -1129,7 +1127,6 @@ namespace AZ
|
||||
|
||||
void ModelDataInstance::UpdateCullBounds(const TransformServiceFeatureProcessor* transformService)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzRender, "ModelDataInstance: UpdateCullBounds");
|
||||
AZ_Assert(m_cullBoundsNeedsUpdate, "This function only needs to be called if the culling bounds need to be rebuilt");
|
||||
AZ_Assert(m_model, "The model has not finished loading yet");
|
||||
|
||||
|
||||
@@ -232,9 +232,10 @@ namespace AZ
|
||||
|
||||
for (ScopeProducer* scopeProducer : m_scopeProducers)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(RHI, "FrameScheduler: PrepareProducers: Scope %s", scopeProducer->GetScopeId().GetCStr());
|
||||
m_frameGraph->BeginScope(*scopeProducer->GetScope());
|
||||
scopeProducer->SetupFrameGraphDependencies(*m_frameGraph);
|
||||
|
||||
|
||||
// All scopes depend on the root scope.
|
||||
if (scopeProducer->GetScopeId() != m_rootScopeId)
|
||||
{
|
||||
@@ -526,7 +527,10 @@ namespace AZ
|
||||
parentJob->StartAsChild(AZ::CreateJobFunction(AZStd::move(jobLambda), true, nullptr));
|
||||
}
|
||||
|
||||
parentJob->WaitForChildren();
|
||||
{
|
||||
AZ_PROFILE_SCOPE(RHI, "FrameScheduler: ExecuteGroupInternal: WaitForChildren");
|
||||
parentJob->WaitForChildren();
|
||||
}
|
||||
}
|
||||
|
||||
m_frameGraphExecuter->EndGroup(groupIndex);
|
||||
|
||||
@@ -477,8 +477,7 @@ namespace AZ
|
||||
return;
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_TRANSITION_BARRIER transition;
|
||||
memset(&transition, 0, sizeof(D3D12_RESOURCE_TRANSITION_BARRIER)); // C4701 potentially unitialized local variable 'transition' used
|
||||
D3D12_RESOURCE_TRANSITION_BARRIER transition = {0};
|
||||
transition.pResource = image.GetMemoryView().GetMemory();
|
||||
|
||||
Scope& firstScope = static_cast<Scope&>(scopeAttachment->GetScope());
|
||||
|
||||
@@ -92,13 +92,13 @@ namespace AZ
|
||||
|
||||
const bool Scope::IsStateSupportedByQueue(D3D12_RESOURCE_STATES state) const
|
||||
{
|
||||
const D3D12_RESOURCE_STATES VALID_COMPUTE_QUEUE_RESOURCE_STATES =
|
||||
constexpr D3D12_RESOURCE_STATES VALID_COMPUTE_QUEUE_RESOURCE_STATES =
|
||||
(D3D12_RESOURCE_STATE_UNORDERED_ACCESS |
|
||||
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE |
|
||||
D3D12_RESOURCE_STATE_COPY_DEST |
|
||||
D3D12_RESOURCE_STATE_COPY_SOURCE);
|
||||
|
||||
const D3D12_RESOURCE_STATES VALID_GRAPHICS_QUEUE_RESOURCE_STATES =
|
||||
constexpr D3D12_RESOURCE_STATES VALID_GRAPHICS_QUEUE_RESOURCE_STATES =
|
||||
(D3D12_RESOURCE_STATES)DX12_RESOURCE_STATE_VALID_API_MASK;
|
||||
|
||||
switch (GetHardwareQueueClass())
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
//Enables more detailed profiling descriptions within the culling system, but adds some performance overhead.
|
||||
//Enable this to more easily see which jobs are associated with which view.
|
||||
//#define AZ_CULL_PROFILE_VERBOSE
|
||||
//#define AZ_CULL_PROFILE_VERBOSE
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -43,6 +43,7 @@ namespace AZ
|
||||
AZ_CVAR(bool, r_CullInParallel, true, nullptr, ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(uint32_t, r_CullWorkPerBatch, 500, nullptr, ConsoleFunctorFlags::Null, "");
|
||||
|
||||
#ifdef AZ_CULL_DEBUG_ENABLED
|
||||
void DebugDrawWorldCoordinateAxes(AuxGeomDraw* auxGeom)
|
||||
{
|
||||
auxGeom->DrawCylinder(Vector3(.5, .0, .0), Vector3(1, 0, 0), 0.02f, 1.0f, Colors::Red, AuxGeomDraw::DrawStyle::Solid, AuxGeomDraw::DepthTest::Off);
|
||||
@@ -198,6 +199,7 @@ namespace AZ
|
||||
AZ_Assert(false, "invalid frustum, cannot draw");
|
||||
}
|
||||
}
|
||||
#endif //AZ_CULL_DEBUG_ENABLED
|
||||
|
||||
CullingDebugContext::~CullingDebugContext()
|
||||
{
|
||||
@@ -282,7 +284,7 @@ namespace AZ
|
||||
const Scene& scene,
|
||||
View& view,
|
||||
Frustum& frustum,
|
||||
[[maybe_unused]]void* maskedOcclusionCulling)
|
||||
[[maybe_unused]] void* maskedOcclusionCulling)
|
||||
{
|
||||
AZStd::shared_ptr<WorklistData> worklistData = AZStd::make_shared<WorklistData>();
|
||||
worklistData->m_debugCtx = &debugCtx;
|
||||
@@ -318,14 +320,16 @@ namespace AZ
|
||||
for (const AzFramework::IVisibilityScene::NodeData& nodeData : worklist)
|
||||
{
|
||||
//If a node is entirely contained within the frustum, then we can skip the fine grained culling.
|
||||
bool nodeIsContainedInFrustum = ShapeIntersection::Contains(worklistData->m_frustum, nodeData.m_bounds);
|
||||
bool nodeIsContainedInFrustum =
|
||||
!worklistData->m_debugCtx->m_enableFrustumCulling ||
|
||||
ShapeIntersection::Contains(worklistData->m_frustum, nodeData.m_bounds);
|
||||
|
||||
#ifdef AZ_CULL_PROFILE_VERBOSE
|
||||
AZ_PROFILE_SCOPE(RPI, "process node (view: %s, skip fine cull: %d",
|
||||
m_view->GetName().GetCStr(), nodeIsContainedInFrustum ? 1 : 0);
|
||||
AZ_PROFILE_SCOPE(RPI, "process node (view: %s, skip fine cull: %ds",
|
||||
worklistData->m_view->GetName().GetCStr(), nodeIsContainedInFrustum ? "true" : "false");
|
||||
#endif
|
||||
|
||||
if (nodeIsContainedInFrustum || !worklistData->m_debugCtx->m_enableFrustumCulling)
|
||||
if (nodeIsContainedInFrustum)
|
||||
{
|
||||
//Add all objects within this node to the view, without any extra culling
|
||||
for (AzFramework::VisibilityEntry* visibleEntry : nodeData.m_entries)
|
||||
@@ -391,7 +395,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef AZ_CULL_DEBUG_ENABLED
|
||||
if (worklistData->m_debugCtx->m_debugDraw && (worklistData->m_view->GetName() == worklistData->m_debugCtx->m_currentViewSelectionName))
|
||||
{
|
||||
AZ_PROFILE_SCOPE(RPI, "debug draw culling");
|
||||
@@ -443,8 +447,10 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef AZ_CULL_DEBUG_ENABLED
|
||||
if (worklistData->m_debugCtx->m_enableStats)
|
||||
{
|
||||
CullingDebugContext::CullStats& cullStats = worklistData->m_debugCtx->GetCullStatsForView(worklistData->m_view);
|
||||
@@ -454,6 +460,7 @@ namespace AZ
|
||||
cullStats.m_numVisibleCullables += numVisibleCullables;
|
||||
++cullStats.m_numJobs;
|
||||
}
|
||||
#endif //AZ_CULL_DEBUG_ENABLED
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_MASKED_OCCLUSION_CULLING_SUPPORTED
|
||||
@@ -466,6 +473,10 @@ namespace AZ
|
||||
return MaskedOcclusionCulling::CullingResult::VISIBLE;
|
||||
}
|
||||
|
||||
#ifdef AZ_CULL_PROFILE_VERBOSE
|
||||
AZ_PROFILE_SCOPE(RPI, "TestOcclusionCulling");
|
||||
#endif
|
||||
|
||||
if (visibleEntry->m_boundingVolume.Contains(worklistData->m_view->GetCameraTransform().GetTranslation()))
|
||||
{
|
||||
// camera is inside bounding volume
|
||||
@@ -515,10 +526,15 @@ namespace AZ
|
||||
}
|
||||
#endif
|
||||
|
||||
void CullingScene::ProcessCullablesCommon(const Scene& scene, View& view, AZ::Frustum& frustum, [[maybe_unused]]void*& maskedOcclusionCulling)
|
||||
void CullingScene::ProcessCullablesCommon(
|
||||
const Scene& scene [[maybe_unused]],
|
||||
View& view,
|
||||
AZ::Frustum& frustum [[maybe_unused]],
|
||||
void*& maskedOcclusionCulling [[maybe_unused]])
|
||||
{
|
||||
AZ_PROFILE_SCOPE(RPI, "CullingScene::ProcessCullablesCommon() - %s", view.GetName().GetCStr());
|
||||
|
||||
#ifdef AZ_CULL_DEBUG_ENABLED
|
||||
if (m_debugCtx.m_freezeFrustums)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_debugCtx.m_frozenFrustumsMutex);
|
||||
@@ -543,7 +559,7 @@ namespace AZ
|
||||
CullingDebugContext::CullStats& cullStats = m_debugCtx.GetCullStatsForView(&view);
|
||||
cullStats.m_cameraViewToWorld = view.GetViewToWorldMatrix();
|
||||
}
|
||||
|
||||
#endif //AZ_CULL_DEBUG_ENABLED
|
||||
#if AZ_TRAIT_MASKED_OCCLUSION_CULLING_SUPPORTED
|
||||
// setup occlusion culling, if necessary
|
||||
maskedOcclusionCulling = m_occlusionPlanes.empty() ? nullptr : view.GetMaskedOcclusionCulling();
|
||||
@@ -805,6 +821,7 @@ namespace AZ
|
||||
beginCullingDescriptor,
|
||||
[&view]()
|
||||
{
|
||||
AZ_PROFILE_SCOPE(RPI, "CullingScene: BeginCullingTaskGraph");
|
||||
view->BeginCulling();
|
||||
});
|
||||
}
|
||||
@@ -822,6 +839,7 @@ namespace AZ
|
||||
{
|
||||
const auto cullingLambda = [&view]()
|
||||
{
|
||||
AZ_PROFILE_SCOPE(RPI, "CullingScene: BeginCullingJob");
|
||||
view->BeginCulling();
|
||||
};
|
||||
|
||||
@@ -843,7 +861,11 @@ namespace AZ
|
||||
|
||||
m_taskGraphActive = AZ::Interface<AZ::TaskGraphActiveInterface>::Get();
|
||||
|
||||
if (m_taskGraphActive && m_taskGraphActive->IsTaskGraphActive())
|
||||
if(views.size() == 1) // avoid job overhead when only 1 job
|
||||
{
|
||||
views[0]->BeginCulling();
|
||||
}
|
||||
else if (m_taskGraphActive && m_taskGraphActive->IsTaskGraphActive())
|
||||
{
|
||||
BeginCullingTaskGraph(views);
|
||||
}
|
||||
@@ -852,6 +874,7 @@ namespace AZ
|
||||
BeginCullingJobs(views);
|
||||
}
|
||||
|
||||
#if AZ_CULL_DEBUG_ENABLED
|
||||
AuxGeomDrawPtr auxGeom;
|
||||
if (m_debugCtx.m_debugDraw)
|
||||
{
|
||||
@@ -884,6 +907,7 @@ namespace AZ
|
||||
m_debugCtx.m_frozenFrustums.clear();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CullingScene::EndCulling()
|
||||
|
||||
@@ -311,7 +311,6 @@ namespace AZ
|
||||
Pass::FramePrepareParams params{ &frameGraphBuilder };
|
||||
|
||||
{
|
||||
AZ_PROFILE_SCOPE(RPI, "Pass: FrameBegin");
|
||||
m_rootPass->FrameBegin(params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,10 +399,11 @@ namespace AZ
|
||||
for (FeatureProcessorPtr& fp : m_featureProcessors)
|
||||
{
|
||||
FeatureProcessor* featureProcessor = fp.get();
|
||||
const auto jobLambda = [this, featureProcessor]()
|
||||
const auto jobLambda = [this, featureProcessor](AZ::Job& owner)
|
||||
{
|
||||
|
||||
featureProcessor->Simulate(m_simulatePacket);
|
||||
FeatureProcessor::SimulatePacket jobPacket = m_simulatePacket;
|
||||
jobPacket.m_parentJob = &owner;
|
||||
featureProcessor->Simulate(jobPacket);
|
||||
};
|
||||
|
||||
AZ::Job* simulationJob = AZ::CreateJobFunction(AZStd::move(jobLambda), true, nullptr); //auto-deletes
|
||||
@@ -515,7 +516,7 @@ namespace AZ
|
||||
collectDrawPacketsTG.Submit(&collectDrawPacketsTGEvent);
|
||||
|
||||
// Launch CullingSystem::ProcessCullables() jobs (will run concurrently with FeatureProcessor::Render() jobs if m_parallelOctreeTraversal)
|
||||
bool parallelOctreeTraversal = m_cullingScene->GetDebugContext().m_parallelOctreeTraversal;
|
||||
const bool parallelOctreeTraversal = m_cullingScene->GetDebugContext().m_parallelOctreeTraversal;
|
||||
m_cullingScene->BeginCulling(m_renderPacket.m_views);
|
||||
static const AZ::TaskDescriptor processCullablesDescriptor{"AZ::RPI::Scene::ProcessCullables", "Graphics"};
|
||||
AZ::TaskGraphEvent processCullablesTGEvent;
|
||||
@@ -575,6 +576,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
// Launch CullingSystem::ProcessCullables() jobs (will run concurrently with FeatureProcessor::Render() jobs)
|
||||
const bool parallelOctreeTraversal = m_cullingScene->GetDebugContext().m_parallelOctreeTraversal;
|
||||
m_cullingScene->BeginCulling(m_renderPacket.m_views);
|
||||
for (ViewPtr& viewPtr : m_renderPacket.m_views)
|
||||
{
|
||||
@@ -583,7 +585,7 @@ namespace AZ
|
||||
m_cullingScene->ProcessCullablesJobs(*this, *viewPtr, thisJob); // can't call directly because ProcessCullables needs a parent job
|
||||
},
|
||||
true, nullptr); //auto-deletes
|
||||
if (m_cullingScene->GetDebugContext().m_parallelOctreeTraversal)
|
||||
if (parallelOctreeTraversal)
|
||||
{
|
||||
processCullablesJob->SetDependent(collectDrawPacketsCompletion);
|
||||
processCullablesJob->Start();
|
||||
@@ -730,20 +732,19 @@ namespace AZ
|
||||
// Add dynamic draw data for all the views
|
||||
if (m_dynamicDrawSystem)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(RPI, "DynamicDraw SubmitDrawData");
|
||||
m_dynamicDrawSystem->SubmitDrawData(this, m_renderPacket.m_views);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
AZ_PROFILE_BEGIN(RPI, "FinalizeDrawLists");
|
||||
if (jobPolicy == RHI::JobPolicy::Serial)
|
||||
AZ_PROFILE_SCOPE(RPI, "FinalizeDrawLists");
|
||||
if (jobPolicy == RHI::JobPolicy::Serial ||
|
||||
m_renderPacket.m_views.size() <= 1) // FinalizeDrawListsX both immediately wait for the job to complete, skip job if only 1 job would be generated
|
||||
{
|
||||
for (auto& view : m_renderPacket.m_views)
|
||||
{
|
||||
view->FinalizeDrawLists();
|
||||
}
|
||||
AZ_PROFILE_END(RPI);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -755,7 +756,6 @@ namespace AZ
|
||||
{
|
||||
FinalizeDrawListsJobs();
|
||||
}
|
||||
AZ_PROFILE_END(RPI);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace ScriptCanvasEditor
|
||||
AZ_Assert(loadResult.m_runtimeAsset, "failed to load dependent asset");
|
||||
|
||||
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> luaAssetOutcome = AZ::Failure(AZStd::string("lua asset creation for function failed"));
|
||||
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(luaAssetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateLuaAsset, loadResult.m_editorAsset, loadResult.m_graphPath);
|
||||
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(luaAssetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateLuaAsset, loadResult.m_editorAsset, loadResult.m_editorAsset.Path().c_str());
|
||||
AZ_Assert(luaAssetOutcome.IsSuccess(), "failed to create Lua asset");
|
||||
|
||||
AZStd::string modulePath = namespacePath[0].data();
|
||||
@@ -111,18 +111,19 @@ namespace ScriptCanvasEditor
|
||||
|
||||
AZ_INLINE LoadTestGraphResult LoadTestGraph(AZStd::string_view graphPath)
|
||||
{
|
||||
AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset> editorAsset;
|
||||
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(editorAsset, &ScriptCanvasEditor::EditorAssetConversionBusTraits::LoadAsset, graphPath);
|
||||
|
||||
if (editorAsset.GetData())
|
||||
if (auto loadFileOutcome = LoadFromFile(graphPath); loadFileOutcome.IsSuccess())
|
||||
{
|
||||
AZ::Outcome< AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> assetOutcome = AZ::Failure(AZStd::string("asset creation failed"));
|
||||
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(assetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateRuntimeAsset, editorAsset);
|
||||
auto& source = loadFileOutcome.GetValue();
|
||||
auto testableSource = SourceHandle(source, AZ::Uuid::CreateRandom(), source.Path().c_str());
|
||||
|
||||
AZ::Outcome<AZ::Data::Asset<ScriptCanvas::RuntimeAsset>, AZStd::string> assetOutcome(AZ::Failure(AZStd::string("asset create failed")));
|
||||
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(assetOutcome
|
||||
, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateRuntimeAsset, testableSource);
|
||||
|
||||
if (assetOutcome.IsSuccess())
|
||||
{
|
||||
LoadTestGraphResult result;
|
||||
result.m_graphPath = graphPath;
|
||||
result.m_editorAsset = editorAsset;
|
||||
result.m_editorAsset = AZStd::move(testableSource);
|
||||
result.m_runtimeAsset = assetOutcome.GetValue();
|
||||
result.m_entity = AZStd::make_unique<AZ::Entity>("Loaded Graph");
|
||||
return result;
|
||||
@@ -163,8 +164,7 @@ namespace ScriptCanvasEditor
|
||||
reporter.SetExecutionMode(mode);
|
||||
|
||||
LoadTestGraphResult loadResult;
|
||||
loadResult.m_graphPath = asset.GetHint().c_str();
|
||||
loadResult.m_editorAsset = asset;
|
||||
loadResult.m_editorAsset = SourceHandle(nullptr, assetId.m_guid, asset.GetHint());
|
||||
AZ::EntityId scriptCanvasId;
|
||||
loadResult.m_entity = AZStd::make_unique<AZ::Entity>("Loaded test graph");
|
||||
loadResult.m_runtimeAsset = runtimeAsset;
|
||||
@@ -205,7 +205,8 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
ScopedOutputSuppression outputSuppressor;
|
||||
AZ::Outcome<ScriptCanvas::Translation::LuaAssetResult, AZStd::string> luaAssetOutcome = AZ::Failure(AZStd::string("lua asset creation failed"));
|
||||
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(luaAssetOutcome, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateLuaAsset, loadResult.m_editorAsset, loadResult.m_graphPath);
|
||||
ScriptCanvasEditor::EditorAssetConversionBus::BroadcastResult(luaAssetOutcome
|
||||
, &ScriptCanvasEditor::EditorAssetConversionBusTraits::CreateLuaAsset, loadResult.m_editorAsset, loadResult.m_editorAsset.Path().c_str());
|
||||
reporter.MarkParseAttemptMade();
|
||||
|
||||
if (luaAssetOutcome.IsSuccess())
|
||||
@@ -219,6 +220,8 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
RuntimeDataOverrides runtimeDataOverrides;
|
||||
runtimeDataOverrides.m_runtimeAsset = loadResult.m_runtimeAsset;
|
||||
runtimeDataOverrides.m_runtimeAsset.SetHint("original");
|
||||
runtimeDataOverrides.m_runtimeAsset.Get()->m_runtimeData.m_script.SetHint("original");
|
||||
|
||||
#if defined(LINUX) //////////////////////////////////////////////////////////////////////////
|
||||
// Temporarily disable testing on the Linux build until the file name casing discrepancy
|
||||
@@ -264,6 +267,10 @@ namespace ScriptCanvasEditor
|
||||
|
||||
RuntimeDataOverrides dependencyRuntimeDataOverrides;
|
||||
dependencyRuntimeDataOverrides.m_runtimeAsset = dependency.runtimeAsset;
|
||||
AZStd::string dependencyHint = AZStd::string::format("dependency_%d", index);
|
||||
dependencyRuntimeDataOverrides.m_runtimeAsset.SetHint(dependencyHint);
|
||||
dependencyRuntimeDataOverrides.m_runtimeAsset.Get()->m_runtimeData.m_script.SetHint(dependencyHint);
|
||||
|
||||
runtimeDataOverrides.m_dependencies.push_back(dependencyRuntimeDataOverrides);
|
||||
|
||||
RuntimeData& dependencyData = dependencyDataBuffer[index];
|
||||
|
||||
@@ -52,7 +52,6 @@ namespace ScriptCanvasEditor
|
||||
m_view->textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn);
|
||||
connect(m_view->scanButton, &QPushButton::pressed, this, &Controller::OnButtonPressScan);
|
||||
connect(m_view->closeButton, &QPushButton::pressed, this, &Controller::OnButtonPressClose);
|
||||
m_view->upgradeAllButton->setVisible(false);
|
||||
connect(m_view->upgradeAllButton, &QPushButton::pressed, this, &Controller::OnButtonPressUpgrade);
|
||||
m_view->progressBar->setValue(0);
|
||||
m_view->progressBar->setVisible(false);
|
||||
@@ -103,9 +102,9 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
}
|
||||
|
||||
QList<QTableWidgetItem*> Controller::FindTableItems(const AZ::Data::AssetInfo& info)
|
||||
QList<QTableWidgetItem*> Controller::FindTableItems(const SourceHandle& info)
|
||||
{
|
||||
return m_view->tableWidget->findItems(info.m_relativePath.c_str(), Qt::MatchFlag::MatchExactly);
|
||||
return m_view->tableWidget->findItems(info.Path().c_str(), Qt::MatchFlag::MatchExactly);
|
||||
}
|
||||
|
||||
void Controller::OnButtonPressClose()
|
||||
@@ -116,30 +115,20 @@ namespace ScriptCanvasEditor
|
||||
void Controller::OnButtonPressScan()
|
||||
{
|
||||
// \todo move to another file
|
||||
auto isUpToDate = [this](AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
auto isUpToDate = [this](const SourceHandle& asset)
|
||||
{
|
||||
AZ::Entity* scriptCanvasEntity = nullptr;
|
||||
auto graphComponent = asset.Get();
|
||||
|
||||
if (asset.GetType() == azrtti_typeid<ScriptCanvasAsset>())
|
||||
{
|
||||
ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs<ScriptCanvasAsset>();
|
||||
if (!scriptCanvasAsset)
|
||||
{
|
||||
AZ_Warning
|
||||
(ScriptCanvas::k_VersionExplorerWindow.data()
|
||||
, false
|
||||
, "InspectAsset: %s, AsestData failed to return ScriptCanvasAsset"
|
||||
, asset.GetHint().c_str());
|
||||
return true;
|
||||
}
|
||||
AZ_Warning
|
||||
( ScriptCanvas::k_VersionExplorerWindow.data()
|
||||
, asset.Get() != nullptr
|
||||
, "InspectAsset: %s, failed to load valid graph"
|
||||
, asset.Path().c_str());
|
||||
|
||||
scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity();
|
||||
AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity");
|
||||
}
|
||||
|
||||
auto graphComponent = scriptCanvasEntity->FindComponent<ScriptCanvasEditor::Graph>();
|
||||
AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component");
|
||||
return !m_view->forceUpgrade->isChecked() && graphComponent->GetVersion().IsLatest();
|
||||
return graphComponent
|
||||
&& (!graphComponent->GetVersion().IsLatest() || m_view->forceUpgrade->isChecked())
|
||||
? ScanConfiguration::Filter::Include
|
||||
: ScanConfiguration::Filter::Exclude;
|
||||
};
|
||||
|
||||
ScanConfiguration config;
|
||||
@@ -155,59 +144,19 @@ namespace ScriptCanvasEditor
|
||||
OnButtonPressUpgradeImplementation({});
|
||||
}
|
||||
|
||||
void Controller::OnButtonPressUpgradeImplementation(const AZ::Data::AssetInfo& assetInfo)
|
||||
void Controller::OnButtonPressUpgradeImplementation(const SourceHandle& assetInfo)
|
||||
{
|
||||
auto simpleUpdate = [this](AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
auto simpleUpdate = [this](SourceHandle& asset)
|
||||
{
|
||||
if (asset.GetType() == azrtti_typeid<ScriptCanvasAsset>())
|
||||
AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), asset.Get() != nullptr
|
||||
, "The Script Canvas asset must have a Graph component");
|
||||
|
||||
if (asset.Get())
|
||||
{
|
||||
ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs<ScriptCanvasAsset>();
|
||||
AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s"
|
||||
, azrtti_typeid<ScriptCanvasAsset>().template ToString<AZStd::string>().c_str());
|
||||
if (!scriptCanvasAsset)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity();
|
||||
AZ_Assert(scriptCanvasEntity, "View::UpgradeGraph The Script Canvas asset must have a valid entity");
|
||||
if (!scriptCanvasEntity)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ::Entity* queryEntity = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(queryEntity, &AZ::ComponentApplicationRequests::FindEntity, scriptCanvasEntity->GetId());
|
||||
if (queryEntity)
|
||||
{
|
||||
if (queryEntity->GetState() == AZ::Entity::State::Active)
|
||||
{
|
||||
queryEntity->Deactivate();
|
||||
}
|
||||
|
||||
scriptCanvasEntity = queryEntity;
|
||||
}
|
||||
|
||||
if (scriptCanvasEntity->GetState() == AZ::Entity::State::Constructed)
|
||||
{
|
||||
scriptCanvasEntity->Init();
|
||||
}
|
||||
|
||||
if (scriptCanvasEntity->GetState() == AZ::Entity::State::Init)
|
||||
{
|
||||
scriptCanvasEntity->Activate();
|
||||
}
|
||||
|
||||
AZ_Assert(scriptCanvasEntity->GetState() == AZ::Entity::State::Active, "Graph entity is not active");
|
||||
auto graphComponent = scriptCanvasEntity->FindComponent<ScriptCanvasEditor::Graph>();
|
||||
AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component");
|
||||
if (graphComponent)
|
||||
{
|
||||
graphComponent->UpgradeGraph
|
||||
(asset
|
||||
, m_view->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate
|
||||
, m_view->verbose->isChecked());
|
||||
}
|
||||
asset.Mod()->UpgradeGraph
|
||||
( asset
|
||||
, m_view->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate
|
||||
, m_view->verbose->isChecked());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -215,7 +164,7 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
int result = QMessageBox::No;
|
||||
QMessageBox mb
|
||||
(QMessageBox::Warning
|
||||
( QMessageBox::Warning
|
||||
, QObject::tr("Failed to Save Upgraded File")
|
||||
, QObject::tr("The upgraded file could not be saved because the file is read only.\n"
|
||||
"Do you want to make it writeable and overwrite it?")
|
||||
@@ -234,12 +183,12 @@ namespace ScriptCanvasEditor
|
||||
ModelRequestsBus::Broadcast(&ModelRequestsTraits::Modify, config);
|
||||
}
|
||||
|
||||
void Controller::OnButtonPressUpgradeSingle(const AZ::Data::AssetInfo& assetInfo)
|
||||
void Controller::OnButtonPressUpgradeSingle(const SourceHandle& info)
|
||||
{
|
||||
OnButtonPressUpgradeImplementation(assetInfo);
|
||||
OnButtonPressUpgradeImplementation(info);
|
||||
}
|
||||
|
||||
void Controller::OnUpgradeModificationBegin([[maybe_unused]] const ModifyConfiguration& config, const AZ::Data::AssetInfo& info)
|
||||
void Controller::OnUpgradeModificationBegin([[maybe_unused]] const ModifyConfiguration& config, const SourceHandle& info)
|
||||
{
|
||||
for (auto* item : FindTableItems(info))
|
||||
{
|
||||
@@ -251,16 +200,16 @@ namespace ScriptCanvasEditor
|
||||
|
||||
void Controller::OnUpgradeModificationEnd
|
||||
( [[maybe_unused]] const ModifyConfiguration& config
|
||||
, const AZ::Data::AssetInfo& info
|
||||
, const SourceHandle& info
|
||||
, ModificationResult result)
|
||||
{
|
||||
if (result.errorMessage.empty())
|
||||
{
|
||||
VE_LOG("Successfully modified %s", result.assetInfo.m_relativePath.c_str());
|
||||
VE_LOG("Successfully modified %s", result.asset.Path().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
VE_LOG("Failed to modify %s: %s", result.assetInfo.m_relativePath.c_str(), result.errorMessage.data());
|
||||
VE_LOG("Failed to modify %s: %s", result.asset.Path().c_str(), result.errorMessage.data());
|
||||
}
|
||||
|
||||
for (auto* item : FindTableItems(info))
|
||||
@@ -288,12 +237,10 @@ namespace ScriptCanvasEditor
|
||||
AddLogEntries();
|
||||
}
|
||||
|
||||
void Controller::OnGraphUpgradeComplete(AZ::Data::Asset<AZ::Data::AssetData>& asset, bool skipped)
|
||||
void Controller::OnGraphUpgradeComplete(ScriptCanvasEditor::SourceHandle& asset, bool skipped)
|
||||
{
|
||||
ModificationResult result;
|
||||
result.asset = asset;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult
|
||||
( result.assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, asset.GetId());
|
||||
|
||||
if (skipped)
|
||||
{
|
||||
@@ -341,19 +288,19 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::OnScanFilteredGraph(const AZ::Data::AssetInfo& info)
|
||||
void Controller::OnScanFilteredGraph(const SourceHandle& info)
|
||||
{
|
||||
OnScannedGraph(info, Filtered::Yes);
|
||||
}
|
||||
|
||||
void Controller::OnScannedGraph(const AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] Filtered filtered)
|
||||
void Controller::OnScannedGraph(const SourceHandle& assetInfo, [[maybe_unused]] Filtered filtered)
|
||||
{
|
||||
const int rowIndex = m_view->tableWidget->rowCount();
|
||||
|
||||
if (filtered == Filtered::No || !m_view->onlyShowOutdated->isChecked())
|
||||
{
|
||||
m_view->tableWidget->insertRow(rowIndex);
|
||||
QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.m_relativePath.c_str()));
|
||||
QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.Path().c_str()));
|
||||
m_view->tableWidget->setItem(rowIndex, static_cast<int>(ColumnAsset), rowName);
|
||||
SetRowSucceeded(rowIndex);
|
||||
|
||||
@@ -375,17 +322,11 @@ namespace ScriptCanvasEditor
|
||||
|
||||
m_view->tableWidget->setCellWidget(rowIndex, static_cast<int>(ColumnAction), upgradeButton);
|
||||
}
|
||||
|
||||
char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 };
|
||||
AZStd::string path = AZStd::string::format("@devroot@/%s", assetInfo.m_relativePath.c_str());
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN);
|
||||
AZ::StringFunc::Path::GetFullPath(resolvedBuffer, path);
|
||||
AZ::StringFunc::Path::Normalize(path);
|
||||
|
||||
|
||||
bool result = false;
|
||||
AZ::Data::AssetInfo info;
|
||||
AZStd::string watchFolder;
|
||||
QByteArray assetNameUtf8 = assetInfo.m_relativePath.c_str();
|
||||
QByteArray assetNameUtf8 = assetInfo.Path().c_str();
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
|
||||
( result
|
||||
, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath
|
||||
@@ -412,41 +353,41 @@ namespace ScriptCanvasEditor
|
||||
OnScannedGraphResult(assetInfo);
|
||||
}
|
||||
|
||||
void Controller::OnScannedGraphResult([[maybe_unused]] const AZ::Data::AssetInfo& info)
|
||||
void Controller::OnScannedGraphResult([[maybe_unused]] const SourceHandle& info)
|
||||
{
|
||||
m_view->progressBar->setValue(aznumeric_cast<int>(m_handledAssetCount));
|
||||
++m_handledAssetCount;
|
||||
AddLogEntries();
|
||||
}
|
||||
|
||||
void Controller::OnScanLoadFailure(const AZ::Data::AssetInfo& info)
|
||||
void Controller::OnScanLoadFailure(const SourceHandle& info)
|
||||
{
|
||||
const int rowIndex = m_view->tableWidget->rowCount();
|
||||
m_view->tableWidget->insertRow(rowIndex);
|
||||
QTableWidgetItem* rowName = new QTableWidgetItem
|
||||
( tr(AZStd::string::format("Load Error: %s", info.m_relativePath.c_str()).c_str()));
|
||||
( tr(AZStd::string::format("Load Error: %s", info.Path().c_str()).c_str()));
|
||||
m_view->tableWidget->setItem(rowIndex, static_cast<int>(ColumnAsset), rowName);
|
||||
SetRowFailed(rowIndex, "Load failed");
|
||||
OnScannedGraphResult(info);
|
||||
}
|
||||
|
||||
void Controller::OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info)
|
||||
void Controller::OnScanUnFilteredGraph(const SourceHandle& info)
|
||||
{
|
||||
OnScannedGraph(info, Filtered::No);
|
||||
}
|
||||
|
||||
void Controller::OnUpgradeBegin
|
||||
( const ModifyConfiguration& config
|
||||
, [[maybe_unused]] const WorkingAssets& assets)
|
||||
, [[maybe_unused]] const AZStd::vector<SourceHandle>& assets)
|
||||
{
|
||||
QString spinnerText = QStringLiteral("Upgrade in progress - ");
|
||||
if (config.modifySingleAsset.m_assetId.IsValid())
|
||||
if (!config.modifySingleAsset.Path().empty())
|
||||
{
|
||||
spinnerText.append(" single graph");
|
||||
|
||||
if (assets.size() == 1)
|
||||
{
|
||||
for (auto* item : FindTableItems(assets.front().info))
|
||||
for (auto* item : FindTableItems(assets.front()))
|
||||
{
|
||||
int row = item->row();
|
||||
SetRowBusy(row);
|
||||
@@ -497,7 +438,7 @@ namespace ScriptCanvasEditor
|
||||
m_view->scanButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void Controller::OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result)
|
||||
void Controller::OnUpgradeDependenciesGathered(const SourceHandle& info, Result result)
|
||||
{
|
||||
for (auto* item : FindTableItems(info))
|
||||
{
|
||||
@@ -526,7 +467,7 @@ namespace ScriptCanvasEditor
|
||||
|
||||
void Controller::OnUpgradeDependencySortBegin
|
||||
( [[maybe_unused]] const ModifyConfiguration& config
|
||||
, const WorkingAssets& assets)
|
||||
, const AZStd::vector<SourceHandle>& assets)
|
||||
{
|
||||
m_handledAssetCount = 0;
|
||||
m_view->progressBar->setVisible(true);
|
||||
@@ -552,7 +493,7 @@ namespace ScriptCanvasEditor
|
||||
|
||||
void Controller::OnUpgradeDependencySortEnd
|
||||
( [[maybe_unused]] const ModifyConfiguration& config
|
||||
, const WorkingAssets& assets
|
||||
, const AZStd::vector<SourceHandle>& assets
|
||||
, [[maybe_unused]] const AZStd::vector<size_t>& sortedOrder)
|
||||
{
|
||||
m_handledAssetCount = 0;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/FileSaver.h>
|
||||
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
|
||||
#include <ScriptCanvas/Assets/ScriptCanvasFileHandling.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
@@ -27,6 +28,11 @@ namespace ScriptCanvasEditor
|
||||
, m_onComplete(onComplete)
|
||||
{}
|
||||
|
||||
const SourceHandle& FileSaver::GetSource() const
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
void FileSaver::PerformMove
|
||||
( AZStd::string tmpFileName
|
||||
, AZStd::string target
|
||||
@@ -37,7 +43,7 @@ namespace ScriptCanvasEditor
|
||||
AZ::SystemTickBus::QueueFunction([this, tmpFileName]()
|
||||
{
|
||||
FileSaveResult result;
|
||||
result.fileSaveError = "Failed to move updated file from temporary location to tmpFileName destination";
|
||||
result.fileSaveError = "Failed to move updated file from temporary location to original destination.";
|
||||
result.tempFileRemovalError = RemoveTempFile(tmpFileName);
|
||||
m_onComplete(result);
|
||||
});
|
||||
@@ -65,7 +71,9 @@ namespace ScriptCanvasEditor
|
||||
auto streamer = AZ::Interface<AZ::IO::IStreamer>::Get();
|
||||
AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str());
|
||||
// Bump the slice asset up in the asset processor's queue.
|
||||
AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str());
|
||||
AzFramework::AssetSystemRequestBus::Broadcast
|
||||
(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str());
|
||||
|
||||
AZ::SystemTickBus::QueueFunction([this, tmpFileName]()
|
||||
{
|
||||
FileSaveResult result;
|
||||
@@ -75,28 +83,29 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to tmpFileName destination failed: %s, trying again", target.c_str());
|
||||
AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false
|
||||
, "moving converted file to tmpFileName destination failed: %s, trying again", target.c_str());
|
||||
auto streamer = AZ::Interface<AZ::IO::IStreamer>::Get();
|
||||
AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str());
|
||||
streamer->SetRequestCompleteCallback(flushRequest, [this, tmpFileName, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request)
|
||||
streamer->SetRequestCompleteCallback(flushRequest
|
||||
, [this, tmpFileName, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request)
|
||||
{
|
||||
// Continue saving.
|
||||
AZ::SystemTickBus::QueueFunction([this, tmpFileName, target, remainingAttempts]() { PerformMove(tmpFileName, target, remainingAttempts - 1); });
|
||||
AZ::SystemTickBus::QueueFunction(
|
||||
[this, tmpFileName, target, remainingAttempts]() { PerformMove(tmpFileName, target, remainingAttempts - 1); });
|
||||
});
|
||||
streamer->QueueRequest(flushRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileSaver::OnSourceFileReleased(AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
void FileSaver::OnSourceFileReleased(const SourceHandle& source)
|
||||
{
|
||||
AZStd::string relativePath, fullPath;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId());
|
||||
bool fullPathFound = false;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fullPathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativePath, fullPath);
|
||||
AZStd::string fullPath = source.Path().c_str();
|
||||
AZStd::string tmpFileName;
|
||||
// here we are saving the graph to a temp file instead of the original file and then copying the temp file to the original file.
|
||||
// This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing. Temp files are ignored by AP.
|
||||
// This ensures that AP will not a get a file change notification on an incomplete graph file causing it to fail processing.
|
||||
// Temp files are ignored by AP.
|
||||
if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName))
|
||||
{
|
||||
FileSaveResult result;
|
||||
@@ -105,23 +114,24 @@ namespace ScriptCanvasEditor
|
||||
return;
|
||||
}
|
||||
|
||||
bool tempSavedSucceeded = false;
|
||||
AZStd::string saveError;
|
||||
|
||||
AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText);
|
||||
if (fileStream.IsOpen())
|
||||
{
|
||||
if (asset.GetType() == azrtti_typeid<ScriptCanvasEditor::ScriptCanvasAsset>())
|
||||
auto saveOutcome = ScriptCanvasEditor::SaveToStream(source, fileStream);
|
||||
if (!saveOutcome.IsSuccess())
|
||||
{
|
||||
ScriptCanvasEditor::ScriptCanvasAssetHandler handler;
|
||||
tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream);
|
||||
saveError = saveOutcome.TakeError();
|
||||
}
|
||||
|
||||
fileStream.Close();
|
||||
}
|
||||
|
||||
if (!tempSavedSucceeded)
|
||||
if (!saveError.empty())
|
||||
{
|
||||
FileSaveResult result;
|
||||
result.fileSaveError = "Save asset data to temporary file failed";
|
||||
result.fileSaveError = AZStd::string::format("Save asset data to temporary file failed: %s", saveError.c_str());
|
||||
m_onComplete(result);
|
||||
return;
|
||||
}
|
||||
@@ -131,26 +141,26 @@ namespace ScriptCanvasEditor
|
||||
, fullPath.c_str()
|
||||
, true
|
||||
, [this, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info)
|
||||
{
|
||||
constexpr const size_t k_maxAttemps = 10;
|
||||
{
|
||||
constexpr const size_t k_maxAttemps = 10;
|
||||
|
||||
if (!info.IsReadOnly())
|
||||
{
|
||||
PerformMove(tmpFileName, fullPath, k_maxAttemps);
|
||||
}
|
||||
else if (m_onReadOnlyFile && m_onReadOnlyFile())
|
||||
{
|
||||
AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true);
|
||||
PerformMove(tmpFileName, fullPath, k_maxAttemps);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileSaveResult result;
|
||||
result.fileSaveError = "Source file was and remained read-only";
|
||||
result.tempFileRemovalError = RemoveTempFile(tmpFileName);
|
||||
m_onComplete(result);
|
||||
}
|
||||
});
|
||||
if (!info.IsReadOnly())
|
||||
{
|
||||
PerformMove(tmpFileName, fullPath, k_maxAttemps);
|
||||
}
|
||||
else if (m_onReadOnlyFile && m_onReadOnlyFile())
|
||||
{
|
||||
AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true);
|
||||
PerformMove(tmpFileName, fullPath, k_maxAttemps);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileSaveResult result;
|
||||
result.fileSaveError = "Source file was and remained read-only";
|
||||
result.tempFileRemovalError = RemoveTempFile(tmpFileName);
|
||||
m_onComplete(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AZStd::string FileSaver::RemoveTempFile(AZStd::string_view tempFile)
|
||||
@@ -158,7 +168,7 @@ namespace ScriptCanvasEditor
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
if (!fileIO)
|
||||
{
|
||||
return "GraphUpgradeComplete: No FileIO instance";
|
||||
return "No FileIO instance";
|
||||
}
|
||||
|
||||
if (fileIO->Exists(tempFile.data()) && !fileIO->Remove(tempFile.data()))
|
||||
@@ -169,30 +179,30 @@ namespace ScriptCanvasEditor
|
||||
return "";
|
||||
}
|
||||
|
||||
void FileSaver::Save(AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
void FileSaver::Save(const SourceHandle& source)
|
||||
{
|
||||
AZStd::string relativePath, fullPath;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(relativePath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, asset.GetId());
|
||||
bool fullPathFound = false;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult
|
||||
(fullPathFound
|
||||
, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath
|
||||
, relativePath, fullPath);
|
||||
m_source = source;
|
||||
|
||||
if (!fullPathFound)
|
||||
if (source.Path().empty())
|
||||
{
|
||||
FileSaveResult result;
|
||||
result.fileSaveError = "Full source path not found";
|
||||
result.fileSaveError = "No save location specified";
|
||||
m_onComplete(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto streamer = AZ::Interface<AZ::IO::IStreamer>::Get();
|
||||
AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath);
|
||||
streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request)
|
||||
AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(source.Path().c_str());
|
||||
streamer->SetRequestCompleteCallback(flushRequest, [this]([[maybe_unused]] AZ::IO::FileRequestHandle request)
|
||||
{
|
||||
this->OnSourceFileReleased(asset);
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
|
||||
if (!m_sourceFileReleased)
|
||||
{
|
||||
m_sourceFileReleased = true;
|
||||
AZ::SystemTickBus::QueueFunction([this]() { this->OnSourceFileReleased(m_source); });
|
||||
}
|
||||
});
|
||||
|
||||
streamer->QueueRequest(flushRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace GraphCpp
|
||||
VariablePanelSymantics,
|
||||
AddVersionData,
|
||||
RemoveFunctionGraphMarker,
|
||||
FixupVersionDataTypeId,
|
||||
// label your version above
|
||||
Current
|
||||
};
|
||||
@@ -70,9 +71,17 @@ namespace ScriptCanvas
|
||||
componentElementNode.AddElementWithData(context, "m_assetType", azrtti_typeid<RuntimeAsset>());
|
||||
}
|
||||
|
||||
if (componentElementNode.GetVersion() < GraphCpp::GraphVersion::RemoveFunctionGraphMarker)
|
||||
if (auto subElement = componentElementNode.FindElement(AZ_CRC_CE("isFunctionGraph")); subElement > 0)
|
||||
{
|
||||
componentElementNode.RemoveElementByName(AZ_CRC_CE("isFunctionGraph"));
|
||||
componentElementNode.RemoveElement(subElement);
|
||||
}
|
||||
|
||||
if (auto subElement = componentElementNode.FindSubElement(AZ_CRC_CE("versionData")))
|
||||
{
|
||||
if (subElement->GetId() == azrtti_typeid<SlotId>())
|
||||
{
|
||||
componentElementNode.RemoveElementByName(AZ_CRC_CE("versionData"));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1189,11 +1198,6 @@ namespace ScriptCanvas
|
||||
m_isObserved = isObserved;
|
||||
}
|
||||
|
||||
AZ::Data::AssetType Graph::GetAssetType() const
|
||||
{
|
||||
return m_assetType;
|
||||
}
|
||||
|
||||
void Graph::VersioningRemoveSlot(ScriptCanvas::Node& scriptCanvasNode, const SlotId& slotId)
|
||||
{
|
||||
bool deletedSlot = true;
|
||||
|
||||
Reference in New Issue
Block a user